今天在跟同事一块儿调试TCP通信的时候,在RSA私钥解密这块,着实让我费了一番心思。
流程大体是这样的,终端登陆的时候使用固定的des密码加密数据发送,平台接收后确认登陆信息后,会返回一个字符串,
该字符串是使用rsa公钥加密的一个字符串,做为后续通信时使用的des密码。平台是使用JAVA开发的,该私钥和公钥文件会
在终端存一份。可是该文件是pem格式的,并且公钥使用证书的方式,调试使用公钥加密后的发送给平台,平台都是能够解密的。
可是平台发送回来的公钥加密就是解密不正常。其中查找资料就很少说了,总算是解决了。这里作一个记录,也作个分享。
其中使用到一个第三方库:BouncyCastle,能够使用NuGet来安装.
首先是RSA密钥与Pem密钥的互转。c#
/// <summary> /// Pem密钥转RSA密钥 /// </summary> /// <param name="pemKey">Pem密钥</param> /// <param name="isPrivateKey">是不是私钥</param> /// <returns>RSA密钥</returns> public static string PemToRSAKey(string pemKeyFileName, bool isPrivateKey) { string rsaKey = string.Empty; object pemObject = null; RSAParameters rsaPara = new RSAParameters(); using (StreamReader sReader = new StreamReader(pemKeyFileName)) { var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(sReader); pemObject = pemReader.ReadObject(); } //RSA私钥 if (isPrivateKey) { RsaPrivateCrtKeyParameters key = (RsaPrivateCrtKeyParameters)pemObject; rsaPara = new RSAParameters { Modulus = key.Modulus.ToByteArrayUnsigned(), Exponent = key.PublicExponent.ToByteArrayUnsigned(), D = key.Exponent.ToByteArrayUnsigned(), P = key.P.ToByteArrayUnsigned(), Q = key.Q.ToByteArrayUnsigned(), DP = key.DP.ToByteArrayUnsigned(), DQ = key.DQ.ToByteArrayUnsigned(), InverseQ = key.QInv.ToByteArrayUnsigned(), }; } //RSA公钥 else { RsaKeyParameters key = (RsaKeyParameters)pemObject; rsaPara = new RSAParameters { Modulus = key.Modulus.ToByteArrayUnsigned(), Exponent = key.Exponent.ToByteArrayUnsigned(), }; } RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.ImportParameters(rsaPara); using (StringWriter sw = new StringWriter()) { sw.Write(rsa.ToXmlString(isPrivateKey ? true : false)); rsaKey = sw.ToString(); } return rsaKey; } /// <summary> /// RSA密钥转Pem密钥 /// </summary> /// <param name="RSAKey">RSA密钥</param> /// <param name="isPrivateKey">是不是私钥</param> /// <returns>Pem密钥</returns> public static string RSAKeyToPem(string RSAKey, bool isPrivateKey) { string pemKey = string.Empty; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(RSAKey); RSAParameters rsaPara = new RSAParameters(); RsaKeyParameters key = null; //RSA私钥 if (isPrivateKey) { rsaPara = rsa.ExportParameters(true); key = new RsaPrivateCrtKeyParameters( new BigInteger(1, rsaPara.Modulus), new BigInteger(1, rsaPara.Exponent), new BigInteger(1, rsaPara.D), new BigInteger(1, rsaPara.P), new BigInteger(1, rsaPara.Q), new BigInteger(1, rsaPara.DP), new BigInteger(1, rsaPara.DQ), new BigInteger(1, rsaPara.InverseQ)); } //RSA公钥 else { rsaPara = rsa.ExportParameters(false); key = new RsaKeyParameters(false, new BigInteger(1, rsaPara.Modulus), new BigInteger(1, rsaPara.Exponent)); } using (TextWriter sw = new StringWriter()) { var pemWriter = new PemWriter(sw); pemWriter.WriteObject(key); pemWriter.Writer.Flush(); pemKey = sw.ToString(); } return pemKey; }
公钥加密,以证书方式打开pem密钥文件ide
/// <summary> /// RSA公钥加密 /// </summary> /// <param name="data"></param> /// <param name="publicKey"></param> /// <returns></returns> public static byte[] RSAPublicEncrypt(byte[] data, string publicKeyFileName) { X509Certificate2 x509Certificate2 = new X509Certificate2(publicKeyFileName); RSACryptoServiceProvider pubKey = (RSACryptoServiceProvider)x509Certificate2.PublicKey.Key; byte[] bys = pubKey.Encrypt(data, false); //string result = Convert.ToBase64String(bys); //return Encoding.UTF8.GetBytes(result); return bys; }
私钥解密加密
/// <summary> /// RSA私钥解密 /// </summary> /// <param name="data"></param> /// <param name="privateKey"></param> /// <returns></returns> public static byte[] RSAPrivateDecrypt(byte[] data, string privateKeyFileName) { string xml = PemToRSAKey(privateKeyFileName, true);//将pem密钥转为RSA密钥 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(xml); return rsa.Decrypt(data, false); }