• Cipher 使用 RSA非对称加密算法 公钥加密后,只有私钥才可以解密,私钥加密后,只有公钥才可以解密 java具体使用 非对称加密算法 总结心得


    1.背景

    有个需求,需要把加密验证数据给前端,该数据为访问对象文档库的授权加密信息,怎么办?

    解决方案是使用 RSA 非对称加密算法,公钥加密后,只有私钥才可以解密,私钥加密后,只有公钥才可以解密

    对象文档库自己存了一条私钥,把公钥给了用户,永久保存,用户加密授权信息后,给前端,前端就可以每次操作文档库时将这个密钥带上去即可

    至于具体的使用文档库实现步骤,这里就不细说了

    这里的算法是RSA,千万要与DSA区分开,两个是有区别的,对于DSA讲解请看我这篇随笔

    RS256 - DSA 算法之一 - java具体使用 非对称加密算法 - 总结心得 - 岑惜 - 博客园 (cnblogs.com)

    2.直接看代码,不多说了

    package cn.cenxi.common.token;
    
    import javax.crypto.Cipher;
    import java.nio.charset.StandardCharsets;
    import java.security.*;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Base64;
    
    public class RSAUtil {
    
        //实例密钥对生成器的加密算法键名【非对称加密】
        private static final String KEY_ALGORITHM = "RSA";
    
        /**
         * 公钥加密
         *
         * @param input     明文
         * @param publicKey 公钥
         * @return 密文
         */
        public static String encrypt(String input, String publicKey) throws GeneralSecurityException {
            //实例加密算法的转换器
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            //恢复公钥
            PublicKey pubKey = KeyFactory.getInstance(KEY_ALGORITHM)
                    .generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey)));
            //设置公钥
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            //执行加密数据
            byte[] data = cipher.doFinal(input.getBytes(StandardCharsets.UTF_8));
            //转字符串后返回
            return Base64.getEncoder().encodeToString(data);
        }
    
        /**
         * 私钥解密
         *
         * @param input      密文
         * @param privateKey 私钥
         * @return 明文
         */
        public static String decrypt(String input, String privateKey) throws GeneralSecurityException {
            //实例加密算法的转换器
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            //恢复私钥
            PrivateKey priKey = KeyFactory.getInstance(KEY_ALGORITHM)
                    .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
            //设置私钥
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            //执行加密数据
            byte[] data = cipher.doFinal(Base64.getDecoder().decode(input));
            //转字符串后返回
            return new String(data, StandardCharsets.UTF_8);
        }
    
        /**
         * 私钥加密
         *
         * @param input      明文
         * @param privateKey 私钥
         * @return 密文
         */
        public static String encryptByPri(String input, String privateKey) throws GeneralSecurityException {
            //实例加密算法的转换器
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            PrivateKey priKey = KeyFactory.getInstance(KEY_ALGORITHM)
                    .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
            cipher.init(Cipher.ENCRYPT_MODE, priKey);
            byte[] data = cipher.doFinal(input.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(data);
        }
    
        /**
         * 公钥解密
         *
         * @param input     密文
         * @param publicKey 公钥
         * @return 明文
         */
        public static String decryptByPri(String input, String publicKey) throws GeneralSecurityException {
            //实例加密算法的转换器
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            PublicKey pubKey = KeyFactory.getInstance(KEY_ALGORITHM)
                    .generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey)));
            cipher.init(Cipher.DECRYPT_MODE, pubKey);
            byte[] data = cipher.doFinal(Base64.getDecoder().decode(input));
            return new String(data, StandardCharsets.UTF_8);
        }
    
        public static void main(String[] args) throws GeneralSecurityException {
            //密钥对生成器
            KeyPairGenerator kpGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
            //初始化配置,参数:密钥长度,安全随机数
            kpGen.initialize(1024, new SecureRandom());
            //生成公钥私钥键值对
            KeyPair keyPair = kpGen.generateKeyPair();
            //将公钥转为字符串【方便存储】
            String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
            //将私钥转为字符串【方便存储】
            String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
            System.out.println("公钥:" + publicKey);
            System.out.println("私钥:" + privateKey);
    
            //公钥加密,私钥解密
            String msg = "我喜欢你,可以做我女朋友吗?";
            System.out.println("加密前:" + msg);
            String pwd = RSAUtil.encrypt(msg, publicKey);
            System.out.println("公钥加密后:" + pwd);
            System.out.println("私钥解密后:" + RSAUtil.decrypt(pwd, privateKey));
    
            //私钥加密,公钥解密
            msg = "当然了,我的小可爱";
            System.out.println("加密前:" + msg);
            String pwd2 = RSAUtil.encryptByPri(msg, privateKey);
            System.out.println("私钥加密后:" + pwd2);
            System.out.println("公钥解密后:" + RSAUtil.decryptByPri(pwd2, publicKey));
    
            //使用错误的密钥来解密
            //System.out.println("私钥解密后:" + RSAUtil.decrypt(pwd, privateKey.replace("2","3")));
            //报错 javax.crypto.BadPaddingException: Decryption error
    
            //使用错误的公钥解密
            //System.out.println("公钥解密后:" + RSAUtil.decryptByPri(pwd2, publicKey.replace("2", "3")));
            //报错 javax.crypto.BadPaddingException: Decryption error
        }
    }
    View Code

    3.测试

     4.使用错误的解密密钥来解密会报错

    javax.crypto.BadPaddingException: Decryption error
  • 相关阅读:
    堆排序算法
    基数排序
    快速排序
    OpenSSL加密证书
    jobs后台任务
    at,crontab例行性任务
    dns
    ftp
    ssh
    iptables
  • 原文地址:https://www.cnblogs.com/c2g5201314/p/16593893.html
Copyright © 2020-2023  润新知