前言:
RSA算法是利用公钥与密钥对数据进行加密验证的一种算法。一般是拿私钥对数据进行签名,公钥发给友商,将数据及签名一同发给友商,友商利用公钥对签名进行验证。也可以使用公钥对数据加密,然后用私钥对数据进行解密。
.Net平台生成的RSA公私钥是xml格式的,java平台下一般是使用der或者pem格式的公私钥,pem格式就是比der格式多了-----BEGIN PUBLIC KEY-----开头及结尾。
.Net平台要使用der/pem公私钥要先转换成xml格式,这需要用到 BouncyCastle.Crypto 这个开源dll,网上已经很多例子。也可以用该dll将.Net生成的公私钥转换成Java平台使用的公私钥。
AES加解密的数据也能在.Net平台和Java平台下互相加解密。
以下.net代码加密的数据皆能在java环境中验证或解密,反之亦然。
---------------------------------------------------------------------------------------------------
/// <summary> /// Xml转换成Der,传入公钥文件格式 /// </summary> /// <param name="publickey"></param> /// <returns></returns> private byte[] RSAPublicKeytoJava(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 serializedPublicBytes; }
/// <summary> /// Xml转换成Der,传入私钥文件格式 /// </summary> /// <param name="privateKey"></param> /// <returns></returns> private byte[] RSAPrivateKeytoJava(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 privateParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv); var publicKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateParam); byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded(); return serializedPublicBytes; }
/// <summary> /// rsa公钥加密 /// </summary> /// <param name="privateKeyfile"></param> /// <param name="text"></param> /// <returns></returns> private string RsaEncry(string privateKeyfile, string text) { var pubKey = File.ReadAllText(this.pubPath); var rsa = new RSACryptoServiceProvider(rsaSize); rsa.FromXmlString(pubKey); var bytesToEncrypt = Encoding.Unicode.GetBytes(text); var encrypt = rsa.Encrypt(bytesToEncrypt, false); return Convert.ToBase64String(encrypt); }
/// <summary> /// RSA私钥解密 /// </summary> /// <param name="privateKey">私钥文件</param> /// <param name="text">待解密字符串</param> /// <returns></returns> private string RsaDecry(string privateKey,string text) { var provider = new RSACryptoServiceProvider(this.rsaSize); provider.FromXmlString(privateKey); var bytesEncrypted = Convert.FromBase64String(text); var bytesPlainText = provider.Decrypt(bytesEncrypted, false); return Encoding.Unicode.GetString(bytesPlainText); }
/// <summary> /// RSA签名 /// </summary> /// <param name="text">待加密文本</param> /// <param name="privateKey">私钥</param> /// <returns></returns> private string RsaSign(string text, string privateKey) { var bytesToEncrypt = Encoding.UTF8.GetBytes(text); var rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(privateKey); var sha = SHA256.Create(); var encrypt = rsa.SignData(bytesToEncrypt, sha); return Convert.ToBase64String(encrypt); }
/// <summary> /// rsa验证签名 /// </summary> /// <param name="txt">明文</param> /// <param name="sign">签名串</param> /// <param name="pubKey">公钥</param> /// <returns></returns> private bool RsaVerifyData(string txt, string sign, string pubKey) { var soures = Encoding.UTF8.GetBytes(txt); var bytes = Convert.FromBase64String(sign); var rsa = new RSACryptoServiceProvider(rsaSize); rsa.FromXmlString(pubKey); SHA256 sha = SHA256.Create(); return rsa.VerifyData(soures, sha, bytes); }
/// <summary> /// AES加密 /// </summary> /// <param name="text">加密字符串</param> /// <param name="key"></param> /// <param name="iv"></param> /// <returns></returns> private string AESEncry(string text, string key, string iv) { var bytes = Encoding.UTF8.GetBytes(text); var keyBytes = new byte[16]; var pwkBytes = Encoding.UTF8.GetBytes(key); //注意这段代码,很重要,没有则java验证不通过 var len = pwkBytes.Length; if (len > keyBytes.Length) len = keyBytes.Length; Array.Copy(pwkBytes, keyBytes, len); var rm = new RijndaelManaged { Key = keyBytes, Mode = CipherMode.CBC, IV = Encoding.UTF8.GetBytes(iv), Padding = PaddingMode.PKCS7, }; var tramsform = rm.CreateEncryptor(); var rst = tramsform.TransformFinalBlock(bytes, 0, bytes.Length); return Convert.ToBase64String(rst); }
/// <summary> /// AES解密 /// </summary> /// <param name="text">解密字符串</param> /// <param name="key"></param> /// <param name="iv"></param> /// <returns></returns> private string AesDecry(string text, string key, string iv) { var bytes = Convert.FromBase64String(text); var keyBytes = new byte[16]; var pwkBytes = Encoding.UTF8.GetBytes(key); var len = pwkBytes.Length; if (len > keyBytes.Length) len = keyBytes.Length; Array.Copy(pwkBytes, keyBytes, len); var rm = new RijndaelManaged() { Key = keyBytes, Mode = CipherMode.CBC, IV = Encoding.UTF8.GetBytes(iv), Padding = PaddingMode.PKCS7 }; var transform = rm.CreateDecryptor(); var rst = transform.TransformFinalBlock(bytes, 0, bytes.Length); return Encoding.UTF8.GetString(rst); }
这有一篇数字证书的原理文章写得比较清楚:数字证书原理(ssl,https)