用Java实现RSA加解密及签名和验签(1)——.pem文件格式秘钥

一、***.pem文件格式的秘钥(获取秘钥:可通过文件读取内容或者直接打开文件复制内容),我这里是打开文件复制秘钥直接使用

1、准备秘钥对,通过openssl生成秘钥对,生成秘钥可参考:https://www.cnblogs.com/ouyanxia/p/12427955.html

A_RSA_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDnPzYKf20JIzaEEkeQTnDAkM1s+nzPbRIA2vU/FOQ47XGIa16lFQ//mxb2ichRF/YGRrBseoK4qxs5zAdNJwXWxQE5nsLzQvSsnQetROczUAdrNVMA4p+rySycYbMF3WK3TFODh1XUZ6KPPZ41PIABFPuqRsK3gHOhAtSmx8LP4cvgnFbCNQl7n7lWmEaTrSOiv+Ld8XlBIIG+jbIzDh6pHCYVsQBkhhC16awxNsbMVKAuGxpDO7OqEqOcmpTODDUuI99YBIuWrxHSHEOGDyK4FlGn9Ryd0fBLMsPPPfxZkC/KiJHIXm/k3I2CtR7E0+iQz3M5nogAsGzBIdVmcod/AgMBAAECggEBAMg2vG1eYmM077BtuzRAFfND6/hc788P2jSPXyMczXRUcKXygGFh2RYvizQtmxhLLKHGdl2VvLRywQHLms676JxIuYTP5m6EHB+PXeQw8hRFSAcUhicQD7rGVS+Yj02Wni+hj/UjKbbbe62VZfMlzJYjOrn0xgXm2zYeo0s7TXp5mWkmhhy3SVbz7AGDOJ4uZo8Hh3ORm6SfDChBi5fOBqH+4gBASQUPgTUczWZuq/5MhBHTTFPjief5mY7uSD8algBdlPnXeqGO1NiCE7/3m/PddI+xX35JyfwvosaHq3GKWAoAEEOVMWyG8tsveSMNV2YsPCj14LPPrbo9umwfCvECgYEA+ybodq1Fmt82qQR+BAyjGrNUOVQe0MtghrGvuH7yjJf9dzoU0+nmF7qS64Rya6udD+nDE34pH+Wz7Y22pfX6GL2Qino+vLLVTjXVJ7oSFt17l3V8WiMBBFdsr0aCQTlP/rmlS+Gzx+DP9BzIf3EXmYxcZMVYBLN8lJbogMHF3wMCgYEA67XwshfsuY6yxVAFjQIs8VU2ROxzp8FO0zKPCk8xXm96ikyidQ5slWzJ7HfogFqCTB8ZOT2kedF5WZyxNSykcipyxPcgSFtkyxNhkp/bwC2KS0JxePftaDGzzb7fAM61SfWunKTDTa0CQJTKMnDJ13Fcv9Z8HzCBt7DBN/DZ/tUCgYEA2SAwBLmT3WpwRPq/Pxz1vVWf0Ngqs/O/hXMEKYqGgom79WFfND2YUJdaAQbGLNN2u5UqsyV0xEC/pvXHG/9lshHgbfd1WYl5412i4+93SBE+khhd40czz98M9RMN9PlpcRxqDQoZdQmkfrSLmbHZ50NzdSMvDxFk+MjmRLpBKKUCgYEAzMenkoI4lslDxSqNeAFA3HYEjQLERCUsf034eaNtp7bARnDn3zyl13fJQhi2tPRtKQcHmfRU9cSoYdNBHYpoYAtC5J4yvMoyGj//UCxz9VVbRaE3BjqXViOAK6q9AW2UkOnSRqLaTpyVTVg3BnV41iTVyJDmCw7QU69LXndwXPUCgYBAambp9pl16WnjXNq2FJ+hlkbDDzWxSfHx0MVDmnd7Ptko0mMPCDjXP/3k18N2I0fucsVMDnxUnzi+bopp/MPunWPFKvBhjCG6r2C6NP7GjU1YyQv7cYJ1/FVQ1W4Sb/HWH0d3OLHR1YddOwvJ0o2T1TFfJ5hRUAlGyr07z4SNDA==-----END PRIVATE KEY-----
A_RSA_PUBILC_KEY=-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5z82Cn9tCSM2hBJHkE5wwJDNbPp8z20SANr1PxTkOO1xiGtepRUP/5sW9onIURf2BkawbHqCuKsbOcwHTScF1sUBOZ7C80L0rJ0HrUTnM1AHazVTAOKfq8ksnGGzBd1it0xTg4dV1Geijz2eNTyAART7qkbCt4BzoQLUpsfCz+HL4JxWwjUJe5+5VphGk60jor/i3fF5QSCBvo2yMw4eqRwmFbEAZIYQtemsMTbGzFSgLhsaQzuzqhKjnJqUzgw1LiPfWASLlq8R0hxDhg8iuBZRp/UcndHwSzLDzz38WZAvyoiRyF5v5NyNgrUexNPokM9zOZ6IALBswSHVZnKHfwIDAQAB-----END PUBLIC KEY-----

2、编写RSAUtil类

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.apache.tomcat.util.codec.binary.Base64;


public class RSAUtil {
    public static RSAPublicKey publicKey;
    public static RSAPrivateKey privateKey;

    public static void configure(PemConfig config) {
        try {
            RSAUtil.publicKey = (RSAPublicKey) getRSAPublicKey(config.getRsa_public_key());
            RSAUtil.privateKey = (RSAPrivateKey)getRSAPrivateKey(config.getRsa_private_key());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 私钥签名(A用私钥签名)
     * @param source
     * @param pkcs8_rsa_private_key
     * @return
     */
     public static String doSignBySHA1withRSA(String source) {
            byte[] sourceData = source.getBytes();
            String result = null;

            try {
                Signature sign = Signature.getInstance("SHA1withRSA");
                sign.initSign(privateKey);
                sign.update(sourceData);
        
                byte[] resultData = sign.sign();
                result = Base64.encodeBase64String(resultData);

            } catch (Exception e) {
                e.printStackTrace();
            } 

            return result;
        }

        public static PrivateKey getRSAPrivateKey(String pkcs8_rsa_private_key) {
            byte[] keyBytes = pkcs8_rsa_private_key.getBytes();

            String pem = new String(keyBytes);
            pem = pem.replace("-----BEGIN PRIVATE KEY-----", "");
            pem = pem.replace("-----END PRIVATE KEY-----", "");
            pem = pem.replace("
", "");

            byte[] decoded = Base64.decodeBase64(pem);
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);

            PrivateKey privateKey = null;

            try {
                KeyFactory kf = KeyFactory.getInstance("RSA");
                privateKey = kf.generatePrivate(spec);

            } catch (Exception e) {
                e.printStackTrace();
            }
            return privateKey;
        }
        /**
         * 公钥验签(A用公钥验签)
         * @param sign
         * @param source
         * @param pkcs8_rsa_public_key
         * @return
         */
        public static boolean doVerifyBySHA1withRSA(String sign, String source) {
            byte[] sourceData = source.getBytes();
            boolean result = false;

            try {
                Signature verify = Signature.getInstance("SHA1withRSA");
                verify.initVerify(publicKey);
                verify.update(sourceData);

                byte[] decoded = Base64.decodeBase64(sign);
                result = verify.verify(decoded);

            } catch (Exception e) {
                e.printStackTrace();
            }

            return result;
        }
        private static PublicKey getRSAPublicKey(String pkcs8_rsa_public_key) {
            byte[] keyBytes = pkcs8_rsa_public_key.getBytes();

            String pem = new String(keyBytes);
            pem = pem.replace("-----BEGIN PUBLIC KEY-----", "");
            pem = pem.replace("-----END PUBLIC KEY-----", "");
            pem = pem.replace("
", "");
            byte[] decoded = Base64.decodeBase64(pem);
            X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded);

            PublicKey publicKey = null;

            try {
                java.security.Security.addProvider(
                        new org.bouncycastle.jce.provider.BouncyCastleProvider()
                        );
                KeyFactory kf = KeyFactory.getInstance("RSA");
                publicKey = kf.generatePublic(spec);

            } catch (Exception e) {
                e.printStackTrace();
            }

            return publicKey;
        }
        /**
         * 公钥加密(B用A的公钥加密)
         * @param plainText
         * @param pkcs8_rsa_public_key
         * @return
         */
        public static String doEncryptByRSA(String plainText) {
            byte[] sourceData = plainText.getBytes();
            String result = null;

            try {
                Cipher cipher = Cipher.getInstance("RSA");
                cipher.init(Cipher.ENCRYPT_MODE, publicKey);
                byte[] resultData = cipher.doFinal(sourceData);
                result = Base64.encodeBase64String(resultData);

            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
        /**
         * 私钥解密(A使用私钥解密)
         * @param encryptedText
         * @param pkcs8_rsa_private_key
         * @return
         */
        public static String doDecryptByRSA(String encryptedText) {
            byte[] sourceData = Base64.decodeBase64(encryptedText);
            String result = null;

            try {
                Cipher cipher = Cipher.getInstance("RSA");
                cipher.init(Cipher.DECRYPT_MODE, privateKey);
                byte[] resultData = cipher.doFinal(sourceData);
                result = new String(resultData);

            } catch (Exception e) {
                e.printStackTrace();
            }

            return result;
        }
}

3、为配置方便我增加了PemConfig类

public class PemConfig {

    private String rsa_private_key;
    private String rsa_public_key;

    public String getRsa_private_key() {
        return rsa_private_key;
    }

    public void setRsa_private_key(String rsa_private_key) {
        this.rsa_private_key = rsa_private_key;
    }

    public String getRsa_public_key() {
        return rsa_public_key;
    }

    public void setRsa_public_key(String rsa_public_key) {
        this.rsa_public_key = rsa_public_key;
    }

    public PemConfig(String rsa_private_key, String rsa_public_key) {
        super();
        this.rsa_private_key = rsa_private_key;
        this.rsa_public_key = rsa_public_key;
    }

}

4、main方法测试一下

package com.example.demo.pem;


import com.example.demo.constants.Constants;
import com.gworld.rsautil.pem.PemConfig;
import com.gworld.rsautil.pem.RSAUtil;

public class DemoTest {
    public static void main(String[] args) {
        String id = "123456789";
        PemConfig config = new PemConfig(Constants.A_RSA_PRIVATE_KEY, Constants.A_RSA_PUBLIC_KEY);//读取配置文件的秘钥
        RSAUtil.configure(config);
        String encodeId = RSAUtil.doEncryptByRSA(id);
        String decodeId = RSAUtil.doDecryptByRSA(encodeId);
        System.out.println("encodeId="+encodeId);
        System.out.println("decodeId="+decodeId);
        
        String sign = RSAUtil.doSignBySHA1withRSA(id);
        
        boolean verify = RSAUtil.doVerifyBySHA1withRSA(sign, id);
        System.out.println("verify result="+verify);
    }

}

测试结果:

encodeId=EawlyXvRIvL2Ew21wN3YrWgwfEnlPai3ovb1VjmttNXwPPfn6tw5cy9NKpXppUZ6qriQOUF/Ns/oWtwdLjvJE/420tQaq02mfUOnl7oxjvRi/B+j0qET7gnPgtUvssRyniKEwk3UIBUDyeWAacNqCPtwIVEt6KtWr2HKhS8ad0EMYGn/lgRF6fVIrhKfvPFjwTI8xIHK2i2gkMMlInxa2K7ytmHsjaJUrfpvVfZxC3B++jNg/tDw/f3kpSbuqNlcXDNFgbt6EhiiO/3dItwuoePhiz/QrAHu1608LzolS9MpXflTzTYrQ7yVe7JbtmawaspBRGPT4iQy7lbC9YadWg==
decodeId=123456789
verify result=true