subendong 2017-03-25 07:40 采纳率: 0%
浏览 5526

java 如何实现PEM格式的RSA加密和解密

思路是:
1、先用.NET生成XML格式的公钥和密钥

         /// <summary>
        ///在给定路径中生成XML格式的私钥和公钥。
        /// </summary>
        public void GenerateKeys(string path)
        {
            using (var rsa = new RSACryptoServiceProvider(RsaKeySize))
            {
                try
                {
                    // 获取私钥和公钥。
                    var publicKey = rsa.ToXmlString(false);
                    var privateKey = rsa.ToXmlString(true);

                    // 保存到磁盘
                    File.WriteAllText(Path.Combine(path, publicKeyFileName), publicKey);
                    File.WriteAllText(Path.Combine(path, privateKeyFileName), privateKey);

                    MessageBox.Show(string.Format("生成的RSA密钥的路径: {0}\\ [{1}, {2}]", path, publicKeyFileName, privateKeyFileName));
                }
                finally
                {
                    rsa.PersistKeyInCsp = false;
                }
            }
        }

2、再用BouncyCastle将XML的公钥和密钥转成PEM格式的

        /// <summary>
        /// RSA私钥格式转换,.net->java
        /// </summary>
        /// <param name="privateKey">.net生成的私钥</param>
        /// <returns></returns>
        public static string RSAPrivateKeyDotNet2Java(string privateKey)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(privateKey);
            BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
            BigInteger exp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
            BigInteger d = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[0].InnerText));
            BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[0].InnerText));
            BigInteger q = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[0].InnerText));
            BigInteger dp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[0].InnerText));
            BigInteger dq = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[0].InnerText));
            BigInteger qinv = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ")[0].InnerText));

            RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv);

            PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
            byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
            return Convert.ToBase64String(serializedPrivateBytes);
        }

        /// <summary>
        /// RSA公钥格式转换,.net->java
        /// </summary>
        /// <param name="publicKey">.net生成的公钥</param>
        /// <returns></returns>
        public static string RSAPublicKeyDotNet2Java(string publicKey)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(publicKey);
            BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
            BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
            RsaKeyParameters pub = new RsaKeyParameters(false, m, p);

            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub);
            byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
            return Convert.ToBase64String(serializedPublicBytes);
        } 

3、然后java怎么利用我转换成PEM格式的公钥密钥进行加密和解密,使得跟.NET的一样?

  • 写回答

1条回答 默认 最新

  • 你知我知皆知 2024-08-05 15:31
    关注

    以下回答参考 皆我百晓生券券喵儿 等免费微信小程序相关内容作答,并由本人整理回复。

    要使用PEM(PKCS#8)格式对RSA密钥进行加密和解密,你需要创建一个自定义的类来处理这些操作。以下是一个简单的示例,展示了如何将.NET的私钥和公钥转换为PEM格式,并使用Java的库来进行加密和解密。

    首先,我们需要导入必要的包:

    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    import java.security.KeyPair;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.Security;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    Security.addProvider(new BouncyCastleProvider());
    

    接下来,我们创建一个类来处理PEM格式的密钥:

    class PEMUtil {
        private static final String ENCODING = "UTF-8";
        private static final String PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\n";
        private static final String PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n";
    
        /**
         * 将私钥转换为PEM格式。
         *
         * @param privateKey 私钥字节数据。
         * @return PEM格式的私钥字符串。
         */
        public static String convertPrivateKeyToPEM(byte[] privateKey) {
            StringBuilder pem = new StringBuilder();
            pem.append(PRIVATE_KEY).append("\n");
            pem.append("-----BEGIN RSA PRIVATE KEY-----\n").append("\n");
    
            // 解析私钥
            KeyPair keyPair = parsePrivateKey(privateKey);
            PrivateKey privateKeyObj = keyPair.getPrivate();
    
            // 构建PEM格式的私钥
            pem.append("-----END RSA PRIVATE KEY-----\n").append("\n");
            pem.append(PRIVATE_KEY).append("\n").append("\n");
            pem.append(PUBLIC_KEY).append("\n");
    
            pem.append(getEncryptedPrivateKey(privateKeyObj)).append("\n");
            pem.append("-----END RSA PRIVATE KEY-----\n").append("\n");
    
            return pem.toString();
        }
    
        /**
         * 将公钥转换为PEM格式。
         *
         * @param publicKey 公钥字节数据。
         * @return PEM格式的公钥字符串。
         */
        public static String convertPublicKeyToPEM(byte[] publicKey) {
            StringBuilder pem = new StringBuilder();
            pem.append(PUBLIC_KEY).append("\n");
            pem.append("-----BEGIN PUBLIC KEY-----\n").append("\n");
    
            // 解析公钥
            PublicKey publicKeyObj = parsePublicKey(publicKey);
    
            // 构建PEM格式的公钥
            pem.append("-----END PUBLIC KEY-----\n").append("\n");
            pem.append(PUBLIC_KEY).append("\n").append("\n");
            pem.append(PRIVATE_KEY).append("\n");
    
            pem.append(getEncryptedPublicKey(publicKeyObj)).append("\n");
            pem.append("-----END PUBLIC KEY-----\n").append("\n");
    
            return pem.toString();
        }
    
        private static KeyPair parsePrivateKey(byte[] privateKey) throws Exception {
            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
            generator.initialize(2048, new SecureRandom(privateKey));
            KeyPair keyPair = generator.generateKeyPair();
    
            return keyPair;
        }
    
        private static PublicKey parsePublicKey(byte[] publicKey) throws Exception {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
            return keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));
        }
    
        private static String getEncryptedPrivateKey(PrivateKey privateKey) throws Exception {
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
            SecretKeySpec secretKeySpec = new SecretKeySpec(privateKey.getEncoded(), "AES");
            IvParameterSpec iv = new IvParameterSpec("ABCDEFG".getBytes());
    
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
            byte[] encryptedData = cipher.doFinal("This is the plaintext data to be encrypted.".getBytes(ENCODING));
    
            return Base64.getEncoder().encodeToString(encryptedData);
        }
    
        private static String getEncryptedPublicKey(PublicKey publicKey) throws Exception {
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
            SecretKeySpec secretKeySpec = new SecretKeySpec(publicKey.getEncoded(), "AES");
            IvParameterSpec iv = new IvParameterSpec("ABCDEFG".getBytes());
    
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
            byte[] encryptedData = cipher.doFinal("This is the plaintext data to be encrypted.".getBytes(ENCODING));
    
            return Base64.getEncoder().encodeToString(encryptedData);
        }
    }
    

    在这个示例中,convertPrivateKeyToPEM方法用于将私钥转换为PEM格式,而convertPublicKeyToPEM方法用于将公钥转换为PEM格式。请注意,这个示例使用了JCE(Java Cryptography Extension)库中的BC安全级别,因此可能无法跨平台运行。

    此外,为了确保安全,你应该始终使用HTTPS或SSH连接来传输敏感信息。

    评论

报告相同问题?