RSA非对称加解密算法以及签名验证

目录

1.生成证书

2.导出公钥 

3.导出私钥

4.加解密签名RSAUtils工具

5.Base64Utils工具

6.测试验证


1.生成证书

  • keytool -genkeypair -v -alias rsa1 -keyalg RSA -sigalg MD5withRSA -keysize 2048 -validity 36500 -storetype PKCS12 -keystore rsa1.keystore

2.导出公钥 

  • keytool -export -alias rsa1 -keystore /user/rsa1.keystore -file rsa1.cer

       注:rsa1.keystore 路径保证正确

3.导出私钥

      注:分三步

       3.1 第一步

  • keytool -importkeystore -srckeystore rsa1.keystore -destkeystore rsa1.p12 -deststoretype pkcs12

       3.2 第二步

  • openssl pkcs12 -in rsa1.p12 -out rsa1.pem

       3.3 第三步

        用文本编辑器打开PEM格式文件,从PEM格式的certificate chain中取出私钥,保存为rsa1.key

  • openssl rsa -in rsa1.key  -check

           或

  • openssl req -new -config openssl.cnf -key rsa1.key >rsa1.csr

4.加解密签名RSAUtils工具

  • package com.example.demo.util;
    
    
    import org.springframework.core.io.ClassPathResource;
    
    import javax.crypto.Cipher;
    import java.io.ByteArrayOutputStream;
    import java.io.InputStream;
    import java.security.*;
    import java.security.cert.Certificate;
    import java.security.cert.CertificateFactory;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * <p>
     * RSA公钥/私钥/签名工具包
     */
    public class RSAUtils {
    
        /**
         * 加密算法RSA
         */
        public static final String KEY_ALGORITHM = "RSA";
    
         /**
         * 签名算法
         *
         * 常用的数字签名算法包括:MD5withRSA/SHA1withRSA/SHA256withRSA/SHA1withDSA/SHA256withDSA/SHA512withDSA/ECDSA等
         *
         */
        public static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
    
        /**
         * 获取公钥的key
         */
        private static final String PUBLIC_KEY = "RSAPublicKey";
    
        /**
         * 获取私钥的key
         */
        private static final String PRIVATE_KEY = "RSAPrivateKey";
    
        /**
         * RSA最大加密明文大小
         */
        private static final int MAX_ENCRYPT_BLOCK = 245;
    
        /**
         * RSA最大解密密文大小
         */
        private static final int MAX_DECRYPT_BLOCK = 256;
    
        /**
         * <p>
         * 生成密钥对(公钥和私钥)
         * </p>
         *
         * @return
         * @throws Exception
         */
        public static Map<String, Object> genKeyPair() throws Exception {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
            keyPairGen.initialize(2048);
            KeyPair keyPair = keyPairGen.generateKeyPair();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            Map<String, Object> keyMap = new HashMap<String, Object>(2);
            keyMap.put(PUBLIC_KEY, publicKey);
            keyMap.put(PRIVATE_KEY, privateKey);
            return keyMap;
        }
    
        public static Map<String, Object> genKeyPairToFile() throws Exception {
            PublicKey publicKey = getPublicKeyFromFile();
            PrivateKey privateKey = getPrivateKeyFromFile();
            Map<String, Object> keyMap = new HashMap<String, Object>(2);
            keyMap.put(PUBLIC_KEY, publicKey);
            keyMap.put(PRIVATE_KEY, privateKey);
            return keyMap;
        }
    
    
        // 从文件中获取公钥
        public static PublicKey getPublicKeyFromFile() throws Exception {
            CertificateFactory cff = CertificateFactory.getInstance("X.509");
            // resources 下的文件
            ClassPathResource classPathResource = new ClassPathResource("keystore/rsa1.cer");
            InputStream fis1 =classPathResource.getInputStream();
            Certificate cf = cff.generateCertificate(fis1);
            return cf.getPublicKey();
        }
        
        // 从文件中获取私钥 
        // 用证书的私钥解密 - 该私钥存在生成该证书的密钥库中
        public static PrivateKey getPrivateKeyFromFile() throws Exception{
            // resources 下的文件
            ClassPathResource classPathResource = new ClassPathResource("keystore/rsa1.keystore");
            InputStream fis2 =classPathResource.getInputStream();
            KeyStore ks = KeyStore.getInstance("JKS");         // 加载证书库
            char[] kspwd = "123321".toCharArray();          // 证书库密码
            char[] keypwd = "123321".toCharArray();          // 证书密码
            ks.load(fis2, kspwd);              // 加载证书
            PrivateKey pk2 = (PrivateKey)ks.getKey("rsa1", keypwd);     // 获取证书私钥
            fis2.close();
            return pk2;
        }
    
        /**
         * <p>
         * 用私钥对信息生成数字签名
         * </p>
         *
         * @param data 已加密数据
         * @param privateKey 私钥(BASE64编码)
         *
         * @return
         * @throws Exception
         */
        public static String sign(byte[] data, String privateKey) throws Exception {
            byte[] keyBytes = Base64Utils.decode(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initSign(privateK);
            signature.update(data);
            return Base64Utils.encode(signature.sign());
        }
    
        /**
         * <p>
         * 校验数字签名
         * </p>
         *
         * @param data 已加密数据
         * @param publicKey 公钥(BASE64编码)
         * @param sign 数字签名
         *
         * @return
         * @throws Exception
         *
         */
        public static boolean verify(byte[] data, String publicKey, String sign)
                throws Exception {
            byte[] keyBytes = Base64Utils.decode(publicKey);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PublicKey publicK = keyFactory.generatePublic(keySpec);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initVerify(publicK);
            signature.update(data);
            return signature.verify(Base64Utils.decode(sign));
        }
    
        /**
         * <P>
         * 私钥解密
         * </p>
         *
         * @param encryptedData 已加密数据
         * @param privateKey 私钥(BASE64编码)
         * @return
         * @throws Exception
         */
        public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
                throws Exception {
            byte[] keyBytes = Base64Utils.decode(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateK);
            int inputLen = encryptedData.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            return decryptedData;
        }
    
        /**
         * <p>
         * 公钥解密
         * </p>
         *
         * @param encryptedData 已加密数据
         * @param publicKey 公钥(BASE64编码)
         * @return
         * @throws Exception
         */
        public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
                throws Exception {
            byte[] keyBytes = Base64Utils.decode(publicKey);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key publicK = keyFactory.generatePublic(x509KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, publicK);
            int inputLen = encryptedData.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            return decryptedData;
        }
    
        /**
         * <p>
         * 公钥加密
         * </p>
         *
         * @param data 源数据
         * @param publicKey 公钥(BASE64编码)
         * @return
         * @throws Exception
         */
        public static byte[] encryptByPublicKey(byte[] data, String publicKey)
                throws Exception {
            byte[] keyBytes = Base64Utils.decode(publicKey);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key publicK = keyFactory.generatePublic(x509KeySpec);
            // 对数据加密
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicK);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            return encryptedData;
        }
    
        /**
         * <p>
         * 私钥加密
         * </p>
         *
         * @param data 源数据
         * @param privateKey 私钥(BASE64编码)
         * @return
         * @throws Exception
         */
        public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
                throws Exception {
            byte[] keyBytes = Base64Utils.decode(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, privateK);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            return encryptedData;
        }
    
        /**
         * <p>
         * 获取私钥
         * </p>
         *
         * @param keyMap 密钥对
         * @return
         * @throws Exception
         */
        public static String getPrivateKey(Map<String, Object> keyMap)
                throws Exception {
            Key key = (Key) keyMap.get(PRIVATE_KEY);
            return Base64Utils.encode(key.getEncoded());
        }
    
        /**
         * <p>
         * 获取公钥
         * </p>
         *
         * @param keyMap 密钥对
         * @return
         * @throws Exception
         */
        public static String getPublicKey(Map<String, Object> keyMap)
                throws Exception {
            Key key = (Key) keyMap.get(PUBLIC_KEY);
            return Base64Utils.encode(key.getEncoded());
        }
    
    }

5.Base64Utils工具

  • package com.example.demo.util;
    
    
    
    import com.sun.org.apache.xml.internal.security.utils.Base64;
    
    import java.io.*;
    
    
    /**
     * <p>
     * BASE64编码解码工具包
     * </p>
     */
    public class Base64Utils {
    
        /**
         * 文件读取缓冲区大小
         */
        private static final int CACHE_SIZE = 1024;
    
        /**
         * <p>
         * BASE64字符串解码为二进制数据
         * </p>
         *
         * @param base64
         * @return
         * @throws Exception
         */
        public static byte[] decode(String base64) throws Exception {
            return Base64.decode(base64.getBytes());
        }
    
        /**
         * <p>
         * 二进制数据编码为BASE64字符串
         * </p>
         *
         * @param bytes
         * @return
         * @throws Exception
         */
        public static String encode(byte[] bytes) throws Exception {
            return new String(Base64.encode(bytes));
        }
    
        /**
         * <p>
         * 将文件编码为BASE64字符串
         * </p>
         * <p>
         * 大文件慎用,可能会导致内存溢出
         * </p>
         *
         * @param filePath
         *            文件绝对路径
         * @return
         * @throws Exception
         */
        public static String encodeFile(String filePath) throws Exception {
            byte[] bytes = fileToByte(filePath);
            return encode(bytes);
        }
    
        /**
         * <p>
         * BASE64字符串转回文件
         * </p>
         *
         * @param filePath
         *            文件绝对路径
         * @param base64
         *            编码字符串
         * @throws Exception
         */
        public static void decodeToFile(String filePath, String base64) throws Exception {
            byte[] bytes = decode(base64);
            byteArrayToFile(bytes, filePath);
        }
    
        /**
         * <p>
         * 文件转换为二进制数组
         * </p>
         *
         * @param filePath
         *            文件路径
         * @return
         * @throws Exception
         */
        public static byte[] fileToByte(String filePath) throws Exception {
            byte[] data = new byte[0];
            File file = new File(filePath);
            if (file.exists()) {
                FileInputStream in = new FileInputStream(file);
                ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
                byte[] cache = new byte[CACHE_SIZE];
                int nRead = 0;
                while ((nRead = in.read(cache)) != -1) {
                    out.write(cache, 0, nRead);
                    out.flush();
                }
                out.close();
                in.close();
                data = out.toByteArray();
            }
            return data;
        }
    
        /**
         * <p>
         * 二进制数据写文件
         * </p>
         *
         * @param bytes
         *            二进制数据
         * @param filePath
         *            文件生成目录
         */
        public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
            InputStream in = new ByteArrayInputStream(bytes);
            File destFile = new File(filePath);
            if (!destFile.getParentFile().exists()) {
                destFile.getParentFile().mkdirs();
            }
            destFile.createNewFile();
            OutputStream out = new FileOutputStream(destFile);
            byte[] cache = new byte[CACHE_SIZE];
            int nRead = 0;
            while ((nRead = in.read(cache)) != -1) {
                out.write(cache, 0, nRead);
                out.flush();
            }
            out.close();
            in.close();
        }
    
    }

6.测试验证

  • package com.example.demo.util;
    
    
    import java.util.Map;
    
    public class RSATest {
    
        static String publicKey;
        static String privateKey;
    
        static {
            try {
                // 直接生成秘钥对
                // Map<String, Object> keyMap = RSAUtils.genKeyPair();
                // 从文件中获取秘钥信息
                 Map<String, Object> keyMap = RSAUtils.genKeyPairToFile();
                publicKey = RSAUtils.getPublicKey(keyMap);
                privateKey = RSAUtils.getPrivateKey(keyMap);
                System.err.println("公钥: \n\r" + publicKey);
                System.err.println("私钥: \n\r" + privateKey);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) throws Exception {
            test();
            System.out.println("========================");
            test1();
            System.out.println("========================");
            test2();
        }
        static void test() throws Exception {
            String source = "测试公钥加密私钥解密";
            System.out.println("\r加密前文字:\r\n" + source);
            byte[] data = source.getBytes();
            byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);
            System.out.println("加密后文字:\r\n" + new String(encodedData));
            byte[] decodedData = RSAUtils.decryptByPrivateKey(encodedData, privateKey);
            String target = new String(decodedData);
            System.out.println("解密后文字: \r\n" + target);
        }
    
        static void test1() throws Exception {
            String source = "测试私钥加密公钥解密";
            System.out.println("原文字:\r\n" + source);
            byte[] data = source.getBytes();
            byte[] encodedData = RSAUtils.encryptByPrivateKey(data, privateKey);
            System.out.println("加密后:\r\n" + new String(encodedData));
            byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, publicKey);
            String target = new String(decodedData);
            System.out.println("解密后: \r\n" + target);
        }
    
        static void test2() throws Exception {
            System.err.println("私钥签名——公钥验证签名");
            String str ="测试签名验签";
            String sign = RSAUtils.sign(str.getBytes(), privateKey);
            System.err.println("签名:" + sign);
    
            boolean status = RSAUtils.verify(str.getBytes(), publicKey, sign);
            System.err.println("签名验证结果:" + status);
        }
    
    }

参考:https://www.cnblogs.com/linjiqin/p/6005626.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值