吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1203|回复: 5
收起左侧

[学习记录] Java对称与非对称加密解密(AES与RSA)

[复制链接]
742 发表于 2022-7-1 09:13

一、对称加密技术与非对称加密技术简述

加密技术可以分为对称与非对称两种。

对称加密、解密即加密与解密用的是同一把秘钥,常用的对称加密技术有DES,AES等。

而非对称技术的加密与解密用的是不同的秘钥,常用的非对称加密技术有RSA等。

二、对称加密技术与非对称加密技术的使用场景简述

为什么要有非对称加密,解密技术呢?

假设这样一种场景A要发送一段消息给B,但是又不想以明文发送,所以就需要对消息进行加密。如果采用对称加密技术,那么加密与解密用的是同一把秘钥,除非B事先就知道A的秘钥,并且保存好,这样才可以解密A发来的消息。

由于对称技术只有一把秘钥,所以秘钥的管理是一个很麻烦的问题,而非对称技术的诞生就解决了这个问题,非对称加密与解密使用的是不同的秘钥,并且秘钥对是一一对应的,即用A的私钥加密的密文只有用A的公钥才能解密。

这样的话,每个人都有两把秘钥,私钥和公钥,私钥是只有自己才知道的,不能告诉别人,而公钥是公开的,大家都可以知道。这样,当A想要发送消息给B的时候,只需要用B的公钥对消息进行加密就可以了,由于B的私钥只有B才拥有,所以A用B的公钥加密的消息只有B才能解开。而B想更换自己的秘要时也很方便,只须把公钥告诉大家就可以了。

那么,既然非对称加密如此之好,对称加密就没有存在的必要了吗,其实不然,由于非对称加密算法的开销很大,所以如果直接以非对称技术来加密发送的消息效率会很差。那么怎么办呢?解决的办法也很简单,就是把对称加密技术与非对称加密技术结合起来使用。

还是这个例子:

第一个场景(公钥加密):A要发送一个消息给B。

第一步:A先 生成一个对称秘钥,这个秘钥可以是随机生成的;

第二步:A用B的公钥加密第一步生成的这个对称秘钥; (事先生成公钥、私钥)

第三步:A把加密过的对称秘钥发给B; (Aes秘钥发给B)

第四步:A用第一步生成的这个对称秘钥加密实际要发的消息 (用aes加密)

第五步:A把用对称秘钥加密的消息发给B (加密内容发给B)

对于B

他先收到A发来的对称秘钥,这个秘钥是用B的公钥加密过的,所以B需要用自己的私钥来解密这个秘钥,

然后B又收到A发来的密文,这时候用刚才解密出来的秘钥来解密密文

这样子的整个过程既保证了安全,又保证了效率。

第二个场景(私钥加密):B要发送一个消息给A。

第一步:B先生成一个对称秘钥,这个秘钥可以是随机生成的;

第二步:B用自己的私钥加密第一步生成的这个对称秘钥;

第三步:B把加密过的对称秘钥发给A;

第四步:B用第一步生成的这个对称秘钥加密实际要发的消息

第五步:B把用对称秘钥加密的消息发给A

对于A

他先收到B发来的对称秘钥,这个秘钥是用B的私钥加密过的,所以A需要用B的公钥来解密这个秘钥,

然后A又收到B发来的密文,这时候用刚才解密出来的秘钥来解密密文

这样子的整个过程既保证了安全,又保证了效率。

三、Java实现使用的是AES的对称加密和RSA的非对称加密

接下来是Java实现:

我这个Java实现使用的是AES的对称加密和RSA的非对称加密(DES的对称加密实现方法和AES的是一样的,但是由于DES算法本身有缺陷,容易被破解,所以现在多用其升级版AES对称加密)

AES加密工具类封装

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;

/**
 * 〈Function overview〉<br>
 *
 * @className: AESUtil
 * @package: com.soft.team.base.encryption
 * @author: yuanzf
 * @date: 2022/3/16 16:41
 */
public class AESUtil {
    /**
     *
     * @Param str 加密前数据
     * @param key 对称密钥,必须为16位
     * @Return 返回加密后数据
     */
    public static String encrypt(String str,String key){
        AES aes = SecureUtil.aes(key.getBytes());
        return aes.encryptBase64(str);
    }

    /**
     *
     * @param str 加密后的数据
     * @param key 盐,必须为16位
     * @return 返回解密后数据
     */
    public static String decrypt (String str,String key){
        AES aes = SecureUtil.aes(key.getBytes());
        return aes.decryptStr(str);
    }
}

RSA加密工具类封装

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import org.apache.commons.codec.binary.Base64;
import java.security.KeyPair;

/**
 * 〈Function overview〉<br>
 *
 * @className: RSA
 * @package: com.soft.team.base.encryption
 * @author: yuanzf
 * @date: 2022/3/16 15:02
 */

public class RSAUtil {
    private String publicKey;
    private String privateKey;

    /*有参构造方法,加解密时使用。公钥加密需用私钥解密,私钥加密需用公钥解密*/
    public RSAUtil(String publicKey,String privateKey){
        this.publicKey = publicKey;
        this.privateKey = privateKey;
    }

    /*无参构造方法,新建密钥对时使用*/
    public RSAUtil(){
        KeyPair pair = SecureUtil.generateKeyPair("RSA");
        publicKey = new String(Base64.encodeBase64(pair.getPublic().getEncoded()));
        privateKey= new String(Base64.encodeBase64((pair.getPrivate().getEncoded())));
    }

    /**
     *
     * @param str 加密前数据
     * @return 返回加密后数据
     */
    public String encrypt(String str){
        return SecureUtil.rsa(privateKey,publicKey).encryptBcd(str, privateKey!=null?KeyType.PrivateKey:KeyType.PublicKey);
    }

    /**
     *
     * @param str 加密后的数据
     * @return 返回解密后数据
     */
    public String decrypt (String str){
        return SecureUtil.rsa(privateKey,publicKey).decryptStrFromBcd(str, privateKey!=null?KeyType.PrivateKey:KeyType.PublicKey);
    }

    public String getPublicKey() {
        return publicKey;
    }
    public String getPrivateKey() {
        return privateKey;
    }
}

测试入口类

import cn.hutool.core.util.RandomUtil;
import com.soft.team.base.encrypt.AESUtil;
import com.soft.team.base.encrypt.RSAUtil;
import org.junit.Test;

/**
 * 加解密测试类
 * @author: yuanzf
 * @date: 2022/3/16 11:37
 */
public class SerialUtilTest {
    /**
     * 测试方法
     * 使用公钥加密就必须使用私钥解密,使用私钥加密就必须使用公钥解密
     * 以下测试方式编写了私钥加密公钥解密,公钥加密私钥解密两种情况
     * 真实的业务场景一方持有私钥,一方持有公钥。因此不会存在两种密钥在一个线程里加解密的情况
     * 真实场景应该是加密方式一和解密方式二为一方,加密方式二和解密方式一为一方
     */
    @Test
    public void start(){
        /*获取aes对称密钥*/
        String aesKey = getRandomKey();
        System.out.println("我是aes对称密钥,请将我保存:"+aesKey);
        /*使用aes密钥对内容进行加密*/
        String content = AESUtil.encrypt("我是一封信,请将我加密后发送",aesKey);
        System.out.println("我是加密后的内容:"+content);
        /*生成rsa密钥对*/
        RSAUtil rsa = new RSAUtil();
        System.out.println("我是rsa公钥,请将我保存:"+rsa.getPublicKey());
        System.out.println("我是rsa私钥,请将我保存:"+rsa.getPrivateKey());
        /*rsa加密方式一 公钥加密,在第一个参数放入生成的公钥*/
        RSAUtil rsaUtil1 = new RSAUtil(rsa.getPublicKey(),null);
        String enContent1 = rsaUtil1.encrypt(aesKey);
        System.out.println("我是经过rsa公钥加密后的aes对称密钥,请将我保存:"+enContent1);
        /*rsa加密方式二 私钥加密,在第二个参数放入生成的私钥*/
        RSAUtil rsaUtil2 = new RSAUtil(null,rsa.getPrivateKey());
        String enContent2 = rsaUtil2.encrypt(aesKey);
        System.out.println("我是经过rsa私钥加密后的aes对称密钥,请将我保存:"+enContent2);
        /*解密方式一 私钥解密*/
        String deContent1 = rsaUtil2.decrypt(enContent1);
        System.out.println("我是经过rsa私钥解密后的aes对称密钥,请将我保存:"+deContent1);
        System.out.println("我是解密后的内容:"+AESUtil.decrypt(content,deContent1));
        /*解密方式二 公钥解密*/
        String deContent2 = rsaUtil2.decrypt(enContent1);
        System.out.println("我是经过rsa公钥解密后的aes对称密钥,请将我保存:"+deContent2);
        System.out.println("我是解密后的内容:"+AESUtil.decrypt(content,deContent2));

    }
    /**
     * 随机生成aes的秘钥
     */
    private String getRandomKey() {
        return RandomUtil.randomString(16);
    }
}

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

头像被屏蔽
xiadongming 发表于 2022-7-3 08:11
提示: 作者被禁止或删除 内容自动屏蔽
 楼主| 742 发表于 2022-7-4 09:08
Mr.wang 发表于 2022-7-9 14:55
真不错,看明白了, 得敲敲代码再熟悉熟悉。
 楼主| 742 发表于 2022-7-9 19:25
Mr.wang 发表于 2022-7-9 14:55
真不错,看明白了, 得敲敲代码再熟悉熟悉。

希望对您有帮助~
tongxin779977 发表于 2022-7-15 08:37
真不错,看明白了,但还是得敲敲代码再熟悉熟悉。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 09:52

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表