• openssl 加解密相关


    常用命令 

    #查看私钥信息
    openssl rsa -in private.key -text -noout
    
    #查看公钥信息
    openssl rsa -in public.key -pubin -text -noout
    
    #生成私钥,PKCS1格式
    openssl genrsa -out rsa_private_key.pem 1024
    
    #私钥转为PKCS8格式,java 默认只支持该格式私钥
    openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out rsa_private_key_pcks8.pem
    
    #生成公钥
    openssl rsa -in rsa_private_key.pem  -pubout -out rsa_public_key.pem 
    
    #pem(base64)转换为der格式(二进制)
    openssl rsa -in rsa_private_key.pem -out rsa_private_key.der -outform DER

     帮助命令

    #查看帮助
    man openssl
    
    #查看子命令帮助
    man gendsa
    
    #其他
    asn1parse(1), ca(1), config(5), crl(1), crl2pkcs7(1), dgst(1), dhparam(1), dsa(1), dsaparam(1),
    enc(1), gendsa(1), genpkey(1), genrsa(1), nseq(1), openssl(1), sslpasswd(1), pkcs12(1), pkcs7(1),
    pkcs8(1), sslrand(1), req(1), rsa(1), rsautl(1), s_client(1), s_server(1), s_time(1), smime(1),
    spkac(1), verify(1), version(1), x509(1), crypto(3), ssl(3), x509v3_config(5)

    pem 密钥格式

    pkcs1 头:-----BEGIN RSA PRIVATE KEY-----
    pkcs8头:-----BEGIN PRIVATE KEY-----

    数字证书格式

    • *.DER或*.CER文件: 这样的证书文件是二进制格式,只含有证书信息,不包含私钥。
    • *.CRT文件: 这样的证书文件可以是二进制格式,也可以是文本格式,一般均为文本格式,功能与 *.DER及*.CER证书文件相同。
    • *.PEM文件: 这样的证书文件一般是文本格式,可以存放证书或私钥,或者两者都包含。 *.PEM 文件如果只包含私钥,一般用*.KEY文件代替。
    • *.PFX或*.P12文件: 这样的证书文件是二进制格式,同时包含证书和私钥,且一般有密码保护。

      

    • 如果存在——BEGIN CERTIFICATE——,则说明这是一个证书文件。
    • 如果存在—–BEGIN RSA PRIVATE KEY—–,则说明这是一个私钥文件。

    java加解密【rsa】

      读取公钥:X509EncodedKeySpec
      读取私钥:PKCS8EncodedKeySpec ,java 只支持PKCS8格式

      der 格式为二进制存储
      pem 格式为 base64存储和一些格式化

    明文长度:密钥长度(Bytes)-11
        理论上为密钥长度,但是有时候明文小于密钥长度,这时候需要 padding
        只要用到padding,那么就要占用实际的明文长度,于是才有117字节的说法。我们一般使用的padding标准有NoPPadding、OAEPPadding、PKCS1Padding等,其中PKCS#1建议的padding就占用了11个字节。

        如果加密字段过长,需要切分后在分块加密

    密文长度:密文位长跟密钥的位长度是相同的

    java 原生代码读取 der 格式

    class Signer {
        private KeyFactory keyFactory;
    
        public Signer() {
            this.keyFactory = KeyFactory.getInstance("RSA");
        }
    
        public PublicKey getPublicKey() {
            byte[] publicKey = readFileAsBytes("public-key.der");
    
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
    
            return keyFactory.generatePublic(keySpec);
        }
    
        public PrivateKey getPrivateKey() {
            byte[] privateKey = readFileAsBytes("private-key.der");
    
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        
            return keyFactory.generatePrivate(keySpec);
        }
    
        private URI readFileAsBytes(String name) {
            URI fileUri = getClass().getClassLoader().getResource(name).toURI();
    
            return Files.readAllBytes(Paths.get(fileUri));
        }
    }

    node 加密 ,java 解密【rsa】

      node 加密

    /**
     * 参考
     *  https://tomoya92.github.io/2018/10/12/node-rsa/
     *  https://github.com/rzcoder/node-rsa/wiki/Advanced-options
     *
     */
    var NodeRSA = require('node-rsa')
    var fs = require('fs')
    const constants = require("constants");
    
    function encrypt() {
        fs.readFile('./pem/rsa_public_key.pem', function (err, data) {
            var key = new NodeRSA(data);
    
            options = {
                encryptionScheme: {
                    scheme: 'pkcs1', //默认 pkcs1_oaep
                    padding: constants.RSA_PKCS1_PADDING
                }
            }
    
            key.setOptions(options)
    
            let cipherText = key.encrypt('hello world', 'base64');
            console.log(cipherText);
        });
    }
    
    //generator();
    encrypt();

      java 解密

    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    import java.security.KeyPair;
    import java.security.PrivateKey;
    import java.security.Security;
    import java.util.Objects;
    
    import javax.crypto.Cipher;
    
    import org.apache.commons.codec.binary.Base64;
    import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import org.bouncycastle.openssl.PEMKeyPair;
    import org.bouncycastle.openssl.PEMParser;
    import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
    import org.junit.Test;
    
    public class RsaTest2 {
    
        static {
            Security.addProvider(new BouncyCastleProvider());
        }
    
        /**
         * 公钥
         */
        private static final File PUBLIC_KEY_FILE = new File(
            Objects.requireNonNull(RsaTest2.class.getClassLoader().getResource("rsa_public_key.pem"))
                .getFile());
    
        /**
         * 私钥 PKCS1
         */
        private static final File PRIVATE_KEY_FILE = new File(
            Objects.requireNonNull(RsaTest2.class.getClassLoader().getResource("rsa_private_key.pem"))
                .getFile());
        /**
         * 私钥 PKCS8 java 支持此格式
         */
        private static final File PRIVATE_PKCS8_KEY_FILE = new File(
            Objects.requireNonNull(RsaTest2.class.getClassLoader().getResource("rsa_private_key_8.pem"))
                .getFile());
    
        /**
         * 测试解密
         */
        @Test
        public void testUnencrypt() throws Exception {
            PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
            PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE);
    
            String encrypt = "gE0OmGUdTp5z+6HwmMUc5JPGOAY4nU84/OFvk0sWV+Zk392m91isaYoE64A2k"
                + "+REv7zZMDu1w1ucmk1jQzFj4N9CoqBGN9QisMDo7WyDB1NAg5enXd9Rz9gvZ4j"
                + "+z6cuk0SVrpPpUTlPCLIUz8CGAkvVGOCqUNQedwQkl4GwBO0=";
            String unencrypt = this.decrypt(rsaPrivateKey2, encrypt);
            System.out.println(unencrypt);
    
            unencrypt = this.decrypt(rsaPrivateKey2, encrypt);
            System.out.println(unencrypt);
    
            System.out.println(rsaPrivateKey2.equals(rsaPrivateKey1));
        }
    
        public PrivateKey readPrivateKeySecondApproach(File file) throws IOException {
            try (FileReader keyReader = new FileReader(file)) {
    
                PEMParser pemParser = new PEMParser(keyReader);
                JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
    
                Object obj = pemParser.readObject();
                if (obj instanceof PrivateKeyInfo) {//
                    //pkcs#8 case
                    return converter.getPrivateKey((PrivateKeyInfo)obj);
                } else {
                    //pkcs#1 case
                    KeyPair kp = converter.getKeyPair((PEMKeyPair)obj);
                    return kp.getPrivate();
                }
            }
        }
    
        public static String decrypt(PrivateKey privateKey, String enStr) throws Exception {
    
            //Cipher.getInstance("RSA"); 等价于 Cipher.getInstance("RSA/ECB/PKCS1Padding");
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] deBytes = cipher.doFinal(Base64.decodeBase64(enStr));
            return new String(deBytes);
        }
    }

    node 加密 ,java 解密【aes】

      node 加密

    /**
     * 对标 java 中 AES/CBC/PKCS7Padding
     * PKCS5 是 PKCS7 的特殊情况,固定 8bit 分组
     * 在线测试: http://tools.jb51.net/password/rsa_encode
     *
     * @type {{}}
     */
    
    const CryptoJS = require("crypto-js");
    
    // 加密
    // let str = '思齐';
    
    // 密钥 16 位
    let key = '491c15367010fbe1';
    
    // 初始向量 initial vector 16 位
    let iv = '13bf32d4419b54b8';
    // key 和 iv 可以一致
    
    key = CryptoJS.enc.Utf8.parse(key);
    iv = CryptoJS.enc.Utf8.parse(iv);
    {
    
        var encrypted = CryptoJS.AES.encrypt(str, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
    
    
    // 转换为字符串 16 进制
    //     encrypted = encrypted.toString(CryptoJS.format.Hex);
    //     console.log(encrypted)
    
    // 转换为字符串 base64
        encrypted = encrypted.toString(CryptoJS.format.Base64);
        console.log(encrypted)
    }
    
    {
    
    // mode 支持 CBC、CFB、CTR、ECB、OFB, 默认 CBC
    // padding 支持 Pkcs7、AnsiX923、Iso10126
    // NoPadding、ZeroPadding, 默认 Pkcs7, 即 Pkcs5
    
    // 解密
        var decrypted = CryptoJS.AES.decrypt(encrypted, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
    
    // 转换为 utf8 字符串
        decrypted = CryptoJS.enc.Utf8.stringify(decrypted);
    }

      java 解密

    /**
     * AES加解密
     *
     *
     * java 中默认要求支持以下实现 https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher
     *
     * AES/CBC/NoPadding (128)
     * AES/CBC/PKCS5Padding (128)
     * AES/ECB/NoPadding (128)
     * AES/ECB/PKCS5Padding (128)
     * DES/CBC/NoPadding (56)
     * DES/CBC/PKCS5Padding (56)
     * DES/ECB/NoPadding (56)
     * DES/ECB/PKCS5Padding (56)
     * DESede/CBC/NoPadding (168)
     * DESede/CBC/PKCS5Padding (168)
     * DESede/ECB/NoPadding (168)
     * DESede/ECB/PKCS5Padding (168)
     * RSA/ECB/PKCS1Padding (1024, 2048)
     * RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
     * RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
     *
     *
     * @date
     * @author
     */
    @Slf4j
    public class AesCrypt2 {
        /**
         * 使用固定长度密钥
         */
        private static final int KEY_LENGTH = 16;
        /**
         * 算法/模式/填充方式
         */
        private static final String TRANSFORMATION = "AES/CBC/PKCS7Padding";
        private static final String AES_ALGORITHM = "AES";
        private static final IvParameterSpec IV = new IvParameterSpec("13bf32d4419b54b8".getBytes());
    
        static {
            //support PKCS7Padding
            if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
                Security.addProvider(new BouncyCastleProvider());
            }
        }
    
        /**
         * aes解密
         * @param data 加密数据
         * @param key 解密密钥
         * @return null 参数不符合要求或解密失败
         */
        public static byte[] decrypt(byte[] data, byte[] key) {
            if (data == null || key == null) {
                return null;
            }
    
            if (key.length != KEY_LENGTH) {
                throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
            }
    
            try {
                SecretKeySpec secretKey = new SecretKeySpec(key, AES_ALGORITHM);
                byte[] enCodeFormat = secretKey.getEncoded();
                SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, AES_ALGORITHM);
    
                Cipher cipher = Cipher.getInstance(TRANSFORMATION);
                cipher.init(Cipher.DECRYPT_MODE, seckey, IV);
    
                return cipher.doFinal(data);
            } catch (Exception e) {
                log.error(" decrypt fail:{}", e.getMessage(), e);
            }
    
            return null;
        }
    
        /**
         * aes加密
         * @param data 需要加密的内容
         * @param key  加密密钥
         * @return 参数不符合要求或加密失败
         */
        public static byte[] encrypt(byte[] data, byte[] key) {
            if (data == null || key == null) {
                return null;
            }
    
            if (key.length != KEY_LENGTH) {
                throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
            }
    
            try {
                SecretKeySpec secretKey = new SecretKeySpec(key, AES_ALGORITHM);
                byte[] enCodeFormat = secretKey.getEncoded();
                SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, AES_ALGORITHM);
    
                Cipher cipher = Cipher.getInstance(TRANSFORMATION);
    
                cipher.init(Cipher.ENCRYPT_MODE, seckey, IV);
                return cipher.doFinal(data);
            } catch (Exception e) {
                log.error(" encrypt fail:{}", e.getMessage(), e);
            }
    
            return null;
        }
    }
            String raw = "eFsqUJGjPd6FO16dgZ6xlg==";
    
            byte[] decode = Base64.getDecoder().decode(raw);
            byte[] last = OgnvAesCrypt.decrypt(decode, "491c15367010fbe1".getBytes());
            //System.out.println(Hex.encodeHex(last));
            System.out.println(new String(last));

    java 读写公钥、私钥

    /**
     * RSA 加解密
     *
     * BouncyCastle 三方开发的加解密和消息摘要组件, 需要添加 provider
     *
     * https://www.baeldung.com/java-read-pem-file-keys
     * https://github.com/rzcoder/node-rsa
     */
    public class RsaTest {
    
        static {
            Security.addProvider(new BouncyCastleProvider());
        }
    
        /**
         * 公钥
         */
        private static final File PUBLIC_KEY_FILE = new File(
            Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_public_key.pem"))
                .getFile());
    
        /**
         * 私钥 PKCS1
         */
        private static final File PRIVATE_KEY_FILE = new File(
            Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_private_key.pem"))
                .getFile());
        /**
         * 私钥 PKCS8 java 支持此格式
         */
        private static final File PRIVATE_PKCS8_KEY_FILE = new File(
            Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_private_key_8.pem"))
                .getFile());
    
        @Test
        public void testReadKey() throws Exception {
    
            //PublicKey rsaPublicKey = this.readPublicKey(PUBLIC_KEY_FILE);
            //PublicKey rsaPrivateKey = this.readPrivateKey(PRIVATE_PKCS8_KEY_FILE);
    
            //BouncyCastle library supports the PKCS1 format,需要加载 provider
            PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE);
    
            PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
            PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE);
    
        }
    
        /**
         * 测试加密
         */
        @Test
        public void testEncrypt() throws Exception {
            //BouncyCastle library supports the PKCS1 format,需要加载 provider
            PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE);
    
            // fFAajnaTQOJUDllbS1qkr/w7yx4vgkMyro8xDIpUEYMYbi43PpdMEF9TnO5hMnL1HmgA4PhD1Uws/EpQtDFBE+0ls+iQa1F6
            // +QwakVrUTMttnJF5kS2WQ0+0yLstXclR1JMFmSZnJGL2dlg1tTIJjREmrKljC2c1VJfoZK5kPps=
            String data = "jksong";
            String encrypt = this.encrypt(rsaPublicKey, data);
            System.out.println(encrypt);
        }
    
        /**
         * 测试解密
         */
        @Test
        public void testUnencrypt() throws Exception {
            PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
            PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE);
    
            String encrypt = "gE0OmGUdTp5z+6HwmMUc5JPGOAY4nU84/OFvk0sWV+Zk392m91isaYoE64A2k"
                + "+REv7zZMDu1w1ucmk1jQzFj4N9CoqBGN9QisMDo7WyDB1NAg5enXd9Rz9gvZ4j"
                + "+z6cuk0SVrpPpUTlPCLIUz8CGAkvVGOCqUNQedwQkl4GwBO0=";
            String unencrypt = this.decrypt(rsaPrivateKey2, encrypt);
            System.out.println(unencrypt);
    
            //unencrypt = this.decrypt(rsaPrivateKey2, encrypt);
            //System.out.println(unencrypt);
            //
            //System.out.println(rsaPrivateKey2.equals(rsaPrivateKey1));
        }
    
        //public static void main(String[] args) throws IOException {
        //    RsaTest rsaTest = new RsaTest();
        //    PrivateKey rsaPrivateKey = rsaTest.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
        //    rsaTest.readPrivateKeySecondApproach(PRIVATE_KEY_FILE);
        //
        //}
    
        public PublicKey readPublicKey(File file) throws Exception {
            String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());
    
            String publicKeyPEM = key
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replaceAll(System.lineSeparator(), "")
                .replace("-----END PUBLIC KEY-----", "");
    
            byte[] encoded = Base64.decodeBase64(publicKeyPEM);
    
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
            return keyFactory.generatePublic(keySpec);
        }
    
        public RSAPrivateKey readPrivateKey(File file) throws Exception {
            String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());
    
            String privateKeyPEM = key
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replaceAll(System.lineSeparator(), "")
                .replace("-----END PRIVATE KEY-----", "");
    
            byte[] encoded = Base64.decodeBase64(privateKeyPEM);
    
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
            return (RSAPrivateKey)keyFactory.generatePrivate(keySpec);
        }
    
        /**
         * 使用 BouncyCastle,可以支持读取 pem 文件
         * @param file
         * @return
         * @throws IOException
         */
        public RSAPublicKey readPublicKeySecondApproach(File file) throws IOException {
            try (FileReader keyReader = new FileReader(file)) {
                PEMParser pemParser = new PEMParser(keyReader);
                JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
                SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pemParser.readObject());
                return (RSAPublicKey)converter.getPublicKey(publicKeyInfo);
            }
        }
    
        public PrivateKey readPrivateKeySecondApproach(File file) throws IOException {
            try (FileReader keyReader = new FileReader(file)) {
    
                PEMParser pemParser = new PEMParser(keyReader);
                JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
    
                Object obj = pemParser.readObject();
                if (obj instanceof PrivateKeyInfo) {//
                    //pkcs#8 case
                    return converter.getPrivateKey((PrivateKeyInfo)obj);
                } else {
                    //pkcs#1 case
                    KeyPair kp = converter.getKeyPair((PEMKeyPair)obj);
                    return kp.getPrivate();
                }
            }
        }
    
        public String encrypt(PublicKey publicKey, String plainText) throws Exception {
    
            //等价于 RSA/ECB/PKCS1Padding (1024, 2048) => RSA/None/PKCS1Padding
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] enBytes = cipher.doFinal(plainText.getBytes());
            return Base64.encodeBase64String(enBytes);
        }
    
        public static String decrypt(PrivateKey privateKey, String enStr) throws Exception {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] deBytes = cipher.doFinal(Base64.decodeBase64(enStr));
            return new String(deBytes);
        }
    }

    数字签名【防篡改】

    /**
     * RSA 加解密
     *
     * BouncyCastle 三方开发的加解密和消息摘要组件, 需要添加 provider
     *
     * https://www.baeldung.com/java-read-pem-file-keys
     * https://github.com/rzcoder/node-rsa
     */
    public class RsaTest {
    
        static {
            Security.addProvider(new BouncyCastleProvider());
        }
    
        /**
         * 公钥
         */
        private static final File PUBLIC_KEY_FILE = new File(
            Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_public_key.pem"))
                .getFile());
    
        /**
         * 私钥 PKCS1
         */
        private static final File PRIVATE_KEY_FILE = new File(
            Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_private_key.pem"))
                .getFile());
        /**
         * 私钥 PKCS8 java 支持此格式
         */
        private static final File PRIVATE_PKCS8_KEY_FILE = new File(
            Objects.requireNonNull(RsaTest.class.getClassLoader().getResource("rsa_private_key_8.pem"))
                .getFile());
    
        @Test
        public void testReadKey() throws Exception {
    
            //PublicKey rsaPublicKey = this.readPublicKey(PUBLIC_KEY_FILE);
            //PublicKey rsaPrivateKey = this.readPrivateKey(PRIVATE_PKCS8_KEY_FILE);
    
            //BouncyCastle library supports the PKCS1 format,需要加载 provider
            PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE);
    
            PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
            PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE);
    
        }
    
        /**
         * 测试加密
         */
        @Test
        public void testEncrypt() throws Exception {
            //BouncyCastle library supports the PKCS1 format,需要加载 provider
            PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE);
    
            // fFAajnaTQOJUDllbS1qkr/w7yx4vgkMyro8xDIpUEYMYbi43PpdMEF9TnO5hMnL1HmgA4PhD1Uws/EpQtDFBE+0ls+iQa1F6
            // +QwakVrUTMttnJF5kS2WQ0+0yLstXclR1JMFmSZnJGL2dlg1tTIJjREmrKljC2c1VJfoZK5kPps=
            String data = "jksong";
            String encrypt = this.encrypt(rsaPublicKey, data);
            System.out.println(encrypt);
        }
    
        /**
         * 测试解密
         */
        @Test
        public void testUnencrypt() throws Exception {
            PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
            PrivateKey rsaPrivateKey2 = this.readPrivateKeySecondApproach(PRIVATE_KEY_FILE);
    
            String encrypt = "gE0OmGUdTp5z+6HwmMUc5JPGOAY4nU84/OFvk0sWV+Zk392m91isaYoE64A2k"
                + "+REv7zZMDu1w1ucmk1jQzFj4N9CoqBGN9QisMDo7WyDB1NAg5enXd9Rz9gvZ4j"
                + "+z6cuk0SVrpPpUTlPCLIUz8CGAkvVGOCqUNQedwQkl4GwBO0=";
            String unencrypt = this.decrypt(rsaPrivateKey2, encrypt);
            System.out.println(unencrypt);
    
            //unencrypt = this.decrypt(rsaPrivateKey2, encrypt);
            //System.out.println(unencrypt);
            //
            //System.out.println(rsaPrivateKey2.equals(rsaPrivateKey1));
        }
    
        /**
         * 数字签名
         * @throws Exception
         */
        @Test
        public void testSign() throws Exception {
    
            /**
             * 签名算法
             * MD2withRSA
             * MD5withRSA
             * RSASSA-PSS
             * SHA1withRSA
             * SHA224withRSA
             * SHA256withRSA
             * SHA384withRSA
             * SHA512withRSA
             * SHA512/224withRSA
             * SHA512/256withRSA
             * 等
             *
             * https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#Introduction
             *
             */
            String signType = "SHA1withRSA";
    
            //待签名数据
            byte[] data = "思齐".getBytes(StandardCharsets.UTF_8);
    
            //生成签名
            PrivateKey rsaPrivateKey1 = this.readPrivateKeySecondApproach(PRIVATE_PKCS8_KEY_FILE);
            String sign = this.sign("SHA1withRSA", data, rsaPrivateKey1);
            System.out.println("签名:" + sign);
    
            //验证签名
            PublicKey rsaPublicKey = this.readPublicKeySecondApproach(PUBLIC_KEY_FILE);
    
            boolean verifySign = this.verifySign("SHA1withRSA", data, rsaPublicKey, sign);
            System.out.println("签名验证结果:" + verifySign);
        }
    
        public PublicKey readPublicKey(File file) throws Exception {
            String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());
    
            String publicKeyPEM = key
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replaceAll(System.lineSeparator(), "")
                .replace("-----END PUBLIC KEY-----", "");
    
            byte[] encoded = Base64.decodeBase64(publicKeyPEM);
    
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
            return keyFactory.generatePublic(keySpec);
        }
    
        public RSAPrivateKey readPrivateKey(File file) throws Exception {
            String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());
    
            String privateKeyPEM = key
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replaceAll(System.lineSeparator(), "")
                .replace("-----END PRIVATE KEY-----", "");
    
            byte[] encoded = Base64.decodeBase64(privateKeyPEM);
    
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
            return (RSAPrivateKey)keyFactory.generatePrivate(keySpec);
        }
    
        /**
         * 使用 BouncyCastle,可以支持读取 pem 文件
         * @param file
         * @return
         * @throws IOException
         */
        public RSAPublicKey readPublicKeySecondApproach(File file) throws IOException {
            try (FileReader keyReader = new FileReader(file)) {
                PEMParser pemParser = new PEMParser(keyReader);
                JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
                SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pemParser.readObject());
                return (RSAPublicKey)converter.getPublicKey(publicKeyInfo);
            }
        }
    
        public PrivateKey readPrivateKeySecondApproach(File file) throws IOException {
            try (FileReader keyReader = new FileReader(file)) {
    
                PEMParser pemParser = new PEMParser(keyReader);
                JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
    
                Object obj = pemParser.readObject();
                if (obj instanceof PrivateKeyInfo) {//
                    //pkcs#8 case
                    return converter.getPrivateKey((PrivateKeyInfo)obj);
                } else {
                    //pkcs#1 case
                    KeyPair kp = converter.getKeyPair((PEMKeyPair)obj);
                    return kp.getPrivate();
                }
            }
        }
    
        public String encrypt(PublicKey publicKey, String plainText) throws Exception {
    
            //等价于 RSA/ECB/PKCS1Padding (1024, 2048) => RSA/None/PKCS1Padding
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] enBytes = cipher.doFinal(plainText.getBytes());
            return Base64.encodeBase64String(enBytes);
        }
    
        public static String decrypt(PrivateKey privateKey, String enStr) throws Exception {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] deBytes = cipher.doFinal(Base64.decodeBase64(enStr));
            return new String(deBytes);
        }
    
        public String sign(String signType, byte[] data, PrivateKey privateKey) throws Exception {
            Signature signature = Signature.getInstance(signType);
            signature.initSign(privateKey);
            signature.update(data);
    
            return Base64.encodeBase64String(signature.sign());
        }
    
        public boolean verifySign(String signType, byte[] data, PublicKey publicKey, String sign) throws Exception {
            Signature signature = Signature.getInstance(signType);
            signature.initVerify(publicKey);
            signature.update(data);
            return signature.verify(Base64.decodeBase64(sign));
        }
    
    }

     读取证书

    /**
         * 读取证书信息
         * @throws CertificateException
         */
        @Test
        public void test497() throws CertificateException {
            InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("pub_server.crt");
    
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            X509Certificate x509Cert = (X509Certificate)certificateFactory.generateCertificate(resourceAsStream);
    
            PublicKey publicKey = x509Cert.getPublicKey();
            BASE64Encoder encoder = new BASE64Encoder();
            String encoded = encoder.encode(publicKey.getEncoded());
            System.out.println("公钥:" + encoded);
    
            System.out.println("输出证书信息:" + x509Cert.toString());
            System.out.println("版本号:" + x509Cert.getVersion());
            System.out.println("序列号:" + x509Cert.getSerialNumber().toString(16));
            System.out.println("主体名:" + x509Cert.getSubjectDN());
            System.out.println("签发者:" + x509Cert.getIssuerDN());
            System.out.println("有效期:" + x509Cert.getNotBefore());
            System.out.println("签名算法:" + x509Cert.getSigAlgName());
            byte[] sig = x509Cert.getSignature();
            System.out.println("签名值:" + Arrays.toString(sig));
        }

    测试密钥

    rsa_private_key.pem

    -----BEGIN PRIVATE KEY-----
    MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMpWEnTXc7jl7fJg
    hMJp5lv3c/Lwv5q7qamRcQIBx6qDNcrMvKfQRqcGS8WqsmWx3qZCWzi40Brexlo/
    V0RN0ktfDXrKl9qO5++yqPk/0mVhN/raF32SSrCP6WNEvSwc5ln3LUV/NPZ6rRTI
    wFLeilruVjvtT1yw/f6cbf5ac+n5AgMBAAECgYAkZy305ZqFZqDT3bek/saaP0AW
    MmhWn3Lb9jXdxZI1xFuWPBWpH5jGjiRt0NM95q2HPiMJZn7ShsgrDoBV4qZ15LdT
    8iHGvDVhmcqv1GPkKoyI1HoCvcff0bhblMb70m14ZnOHgf4MlNeOVvrkd8LdaoST
    7y61akphJdTIKLZVAQJBAPv4rNjA0yjZvwLeR/mZdQyYexI/yJCEJhPj591BeeMI
    ZzPlEcyZS+vMYtMpGaxHqtUJG8zoCcXluj/lZmPlsCECQQDNkj0vLk/ZpRE+paOj
    SKrjQJF/OJ9SWu0FGpQ9PfqrFgLUvVYTzFpFfW0k345r4CK6I9eX/4ey7oGgbUfh
    Zd7ZAkEAnRVt5H9p5SjCnS4oXuIdh6mz6C+dgQLxnirSDSzZqQE/HaosS4oyO6Gi
    5pPT7oSLat6P11G9bgOG9ni0OYkjIQJAHCFOzg4AT0APRAtWgRmIiOBlCIuvAY3/
    sRsZ/edlTdQNPx9JkBv+nlOzg8AztP9OwTn2Xo5Q+2M3ycQqeeV+wQJBAJRyBEh1
    2RuDjCMjz7K8KCWJcZ1wZT+7Xb51ICyQPwnIiz1fSRpwmzO8dS7gZQ9qaqa1uAEl
    O+aDMRvr202Wm2s=
    -----END PRIVATE KEY-----

    rsa_private_key_8.pem

    -----BEGIN PRIVATE KEY-----
    MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMpWEnTXc7jl7fJg
    hMJp5lv3c/Lwv5q7qamRcQIBx6qDNcrMvKfQRqcGS8WqsmWx3qZCWzi40Brexlo/
    V0RN0ktfDXrKl9qO5++yqPk/0mVhN/raF32SSrCP6WNEvSwc5ln3LUV/NPZ6rRTI
    wFLeilruVjvtT1yw/f6cbf5ac+n5AgMBAAECgYAkZy305ZqFZqDT3bek/saaP0AW
    MmhWn3Lb9jXdxZI1xFuWPBWpH5jGjiRt0NM95q2HPiMJZn7ShsgrDoBV4qZ15LdT
    8iHGvDVhmcqv1GPkKoyI1HoCvcff0bhblMb70m14ZnOHgf4MlNeOVvrkd8LdaoST
    7y61akphJdTIKLZVAQJBAPv4rNjA0yjZvwLeR/mZdQyYexI/yJCEJhPj591BeeMI
    ZzPlEcyZS+vMYtMpGaxHqtUJG8zoCcXluj/lZmPlsCECQQDNkj0vLk/ZpRE+paOj
    SKrjQJF/OJ9SWu0FGpQ9PfqrFgLUvVYTzFpFfW0k345r4CK6I9eX/4ey7oGgbUfh
    Zd7ZAkEAnRVt5H9p5SjCnS4oXuIdh6mz6C+dgQLxnirSDSzZqQE/HaosS4oyO6Gi
    5pPT7oSLat6P11G9bgOG9ni0OYkjIQJAHCFOzg4AT0APRAtWgRmIiOBlCIuvAY3/
    sRsZ/edlTdQNPx9JkBv+nlOzg8AztP9OwTn2Xo5Q+2M3ycQqeeV+wQJBAJRyBEh1
    2RuDjCMjz7K8KCWJcZ1wZT+7Xb51ICyQPwnIiz1fSRpwmzO8dS7gZQ9qaqa1uAEl
    O+aDMRvr202Wm2s=
    -----END PRIVATE KEY-----

    rsa_public_key.pem

    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKVhJ013O45e3yYITCaeZb93Py
    8L+au6mpkXECAceqgzXKzLyn0EanBkvFqrJlsd6mQls4uNAa3sZaP1dETdJLXw16
    ypfajufvsqj5P9JlYTf62hd9kkqwj+ljRL0sHOZZ9y1FfzT2eq0UyMBS3opa7lY7
    7U9csP3+nG3+WnPp+QIDAQAB
    -----END PUBLIC KEY-----

     参考

      Java Cryptography Architecture Standard Algorithm Name

      Java Cryptography Architecture Oracle Providers Documentation for JDK 8

      数字签名是什么

      rsa 在线加解密工具

      数字证书格式

  • 相关阅读:
    Layui数据表格用法
    初识Vue
    使用NPOI导出Excel表
    使用NPOI将Excel表导入到数据库中
    新随笔
    AX2012/D365 SSRS报表开发
    AX2012自定义注释脚本开发
    D365做文件导入导出CSV
    Azure文件上传下载删除(D365可以直接用)
    关于D365/AX2012/C#中的那些json、对象、字符串类型间的转换
  • 原文地址:https://www.cnblogs.com/siqi/p/15166679.html
Copyright © 2020-2023  润新知