• 非对称加密、数字签名JDK实现


    非对称加密算法

    ● 算法特点

    1. 有2把秘钥,为公钥和私钥。
    2. 如果使用公钥加密,则必须使用私钥解密。
    3. 如果使用私钥解密,则必须使用公钥加密。
    4. 公钥和私钥是一对,成为密钥对。

    对于此类加密算法的实现有 RSA,ECC等,也就是说 对称加密,消息摘要以及非对称加密 是一些算法思想,基于思想才有的实现。那么非对称加密的算法实现就是RSA和ECC等。

    在JDK中当然也为RSA等算法提供了实现

    public class RSATest {
    
        static {
    
            try {
                KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
                KeyPair keyPair = keyPairGenerator.generateKeyPair();//密钥对
                PublicKey publicKey = keyPair.getPublic();
                PrivateKey privateKey = keyPair.getPrivate();
    
                String pub = new String(Base64.getEncoder().encodeToString(publicKey.getEncoded()));
                String pri = new String(Base64.getEncoder().encodeToString(privateKey.getEncoded()));
    
                System.out.println("公钥:" + pub);
                System.out.println("私钥:" + pri);
    
            }catch (Exception e){
                e.printStackTrace();
            }
    
        }
    
        @Test
        public void testKeyPari() throws Exception {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();
            System.out.println(Base64.getEncoder().encodeToString(publicKey.getEncoded()));
            System.out.println("===");
            System.out.println(Base64.getEncoder().encodeToString(privateKey.getEncoded()));
    
            String source = "Ja";
            System.out.println("加密后的密文:");
            String miwen = rsaEncode(source, publicKey);
            System.out.println(miwen);
            System.out.println("解密后的明文:");
            System.out.println(rsaDecode(miwen,privateKey));
    
        }
    
        private String rsaEncode(String source, Key key) throws Exception{
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(1,key);
            byte[] bytes = cipher.doFinal(source.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(bytes);
        }
    
        //RSA算法解密
        private String rsaDecode(String source, Key key) throws Exception{
            Cipher rsa = Cipher.getInstance("RSA");
            rsa.init(2,key);
            byte[] bytes = rsa.doFinal(Base64.getDecoder().decode(source.getBytes(StandardCharsets.UTF_8)));
            return new String(bytes);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    生成密钥对主要是 KeyPairGenerator 这个对象,可以生成RSA算法需要的公钥和私钥。最后还是需要Cipher 这个对象去实现加解密,同时还要注意,Cipher加解密的结果不一定是一堆完整的字符串,所以往往还需要结合Base64或者Base58等可读性算法来存储或者传输。

    数字签名
     * 数字签名
    
    • 1
    • 数字签名是一种验证数据在网络传输过程中完整性、真实性的一种手段。
    • 当传输的数据不需要加密而又不希望被篡改时,就可以使用到数字签名,数字签名的过程还是要用到非对称加密算法的,
      1. 首先发送方使用散列函数将发送的内容生成一个消息摘要,也就是一个固定长度的字符串。
      1. 发送方继续使用私钥对散列函数进行加密
      1. 接收方收到内容之后,使用自己的公钥进行解密。
      1. 接收方使用相同的散列函数再次对内容进行加密。
      1. 此时如果接收方计算出的签名结果和发送方相同,则证明没有被篡改过,反之则被篡改过。
    public class DigestSign {
    
        @Test
        public void testSign() throws Exception {
            //生成密钥对
            KeyPairGenerator pairGenerator = KeyPairGenerator.getInstance("RSA");
            KeyPair keyPair = pairGenerator.generateKeyPair();
            PublicKey publicKey = keyPair.getPublic(); //公钥
            PrivateKey privateKey = keyPair.getPrivate(); //私钥
    
            String pub = Base64.encode(publicKey.getEncoded());
            String pri = Base64.encode(privateKey.getEncoded());
    
            System.out.println("公钥:" + pub);
            System.out.println("私钥:" + pri);
    
            String content = "南山老妖";
    
            String hashRule = "sha256withrsa";//消息摘要算法
    
            //获取签名
            String sign = getSign(privateKey,content,hashRule);
            System.out.println("消息的签名是:" + sign);
    
            //接收方验证消息与签名是否匹配
            boolean verify = verifySign(publicKey,content,hashRule,sign);
            System.out.println("验证签名:" + verify);
        }
    
        private boolean verifySign(PublicKey publicKey, String content, String hashRule, String sign) throws Exception {
            Signature signature = Signature.getInstance(hashRule);
            signature.initVerify(publicKey);
            signature.update(content.getBytes(StandardCharsets.UTF_8));
            //对比签名
            boolean verify = signature.verify(Base64.decode(sign));
            return verify;
        }
    
        private String getSign(PrivateKey privateKey, String content, String hashRule) throws Exception {
            //获取消息签名算法
            Signature signature = Signature.getInstance(hashRule);
    
            //设置公钥
            signature.initSign(privateKey);
            //设置消息摘要泛
            signature.update(content.getBytes());
            byte[] sign = signature.sign();
            return Base64.encode(sign);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    数字签名的过程和RSA的加密解密还有有些相似的,只不过就是在验证数字签名的时候这里要注意,一定是将原文和Base64转码后的签名字节数组去比较。

  • 相关阅读:
    Informer--用于长序列时序预测【2021AAAI Best Paper】
    TensorFlow:GPU的使用
    3D激光SLAM:LIO-SAM整体介绍与安装编译
    Redis 图形化界面下载及使用超详细教程(带安装包)! redis windows下客户端下载
    SaaS 电商设计 (二) 全链路解决方案概述和核心业务流程梳理
    Linux开发讲课18--- “>file 2>&1“ 和 “2>&1 >file“ 的区别
    vue中怎么把reader.onload中的定义的变量在外部调用
    使用python时刻中监控文件夹,记录文件夹中文件异常信息
    ProtoBuf、Grpc、GORM、Go-redis 入门基础
    python 数据可视化
  • 原文地址:https://blog.csdn.net/qq_43750656/article/details/131792116