在C#中,RSA私钥只能签名,不能加密,如果要加密,要借助BouncyCastle库。
nuget 中引用 Portable.BouncyCastle。
工具类:
RsaEncryptUtil
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using System; using System.Security.Cryptography; using System.Text; namespace CommonUtils { public static class RsaEncryptUtil { /// <summary> /// 私钥加密 .Net平台默认是使用公钥进行加密,私钥进行解密。私钥加密需要自己实现或者使用第三方dll /// </summary> /// <param name="data"></param> /// <param name="key">私钥,格式:PKCS8</param> /// <returns></returns> public static byte[] encryptByPrivateKey(String data, String key) { String priKey = key.Trim(); String xmlPrivateKey = RSAPrivateKeyJava2DotNet(priKey); //加载私钥 RSACryptoServiceProvider privateRsa = new RSACryptoServiceProvider(); privateRsa.FromXmlString(xmlPrivateKey); //转换密钥 AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetKeyPair(privateRsa); IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");// 参数与Java中加密解密的参数一致 c.Init(true, keyPair.Private); //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥 byte[] DataToEncrypt = Encoding.UTF8.GetBytes(data); byte[] outBytes = c.DoFinal(DataToEncrypt);//加密 return outBytes; } /// <summary> /// 私钥加密 /// </summary> /// <param name="data">明文</param> /// <param name="key">私钥</param> /// <param name="keyFormat">私钥格式:PKCS1,PKCS8</param> /// <returns></returns> public static byte[] encryptByPrivateKey(String data, String key,string keyFormat) { String priKey = key.Trim(); //加载私钥 RSACryptoServiceProvider privateRsa = RsaUtil.LoadPrivateKey(key,keyFormat); //转换密钥 AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetKeyPair(privateRsa); IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");// 参数与Java中加密解密的参数一致 c.Init(true, keyPair.Private); //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥 byte[] DataToEncrypt = Encoding.UTF8.GetBytes(data); byte[] outBytes = c.DoFinal(DataToEncrypt);//加密 return outBytes; } /// <summary> /// RSA私钥格式转换,java->.net /// </summary> /// <param name="privateKey"></param> /// <returns></returns> private static string RSAPrivateKeyJava2DotNet(string privateKey) { RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey)); return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>", Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned())); } /// <summary> /// 用公钥解密 /// </summary> /// <param name="data"></param> /// <param name="key"></param> /// <returns></returns> public static byte[] decryptByPublicKey(String data, String key) { String pubKey = key.Trim(); String xmlPublicKey = RSAPublicKeyJava2DotNet(pubKey); RSACryptoServiceProvider publicRsa = new RSACryptoServiceProvider(); publicRsa.FromXmlString(xmlPublicKey); AsymmetricKeyParameter keyPair = DotNetUtilities.GetRsaPublicKey(publicRsa); //转换密钥 // AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetRsaKeyPair(publicRsa); IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");// 参数与Java中加密解密的参数一致 c.Init(false, keyPair); //第一个参数为true表示加密,为false表示解密;第二个参数表示密钥 byte[] DataToEncrypt = Convert.FromBase64String(data); byte[] outBytes = c.DoFinal(DataToEncrypt);//解密 return outBytes; } /// <summary> /// RSA公钥格式转换,java->.net /// </summary> /// <param name="publicKey"></param> /// <returns></returns> private static string RSAPublicKeyJava2DotNet(string publicKey) { RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey)); return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>", Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); } } }
RsaUtil
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using System; using System.IO; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; namespace CommonUtils { public static class RsaUtil { #region 加载私钥 /// <summary> /// 转换私钥字符串为RSACryptoServiceProvider /// </summary> /// <param name="privateKeyStr">私钥字符串</param> /// <param name="keyFormat">PKCS8,PKCS1</param> /// <param name="signType">RSA 私钥长度1024 ,RSA2 私钥长度2048</param> /// <returns></returns> public static RSACryptoServiceProvider LoadPrivateKey(string privateKeyStr, string keyFormat) { string signType = "RSA"; if (privateKeyStr.Length > 1024) { signType = "RSA2"; } //PKCS8,PKCS1 if (keyFormat == "PKCS1") { return LoadPrivateKeyPKCS1(privateKeyStr, signType); } else { return LoadPrivateKeyPKCS8(privateKeyStr); } } /// <summary> /// PKCS1 格式私钥转 RSACryptoServiceProvider 对象 /// </summary> /// <param name="strKey">pcsk1 私钥的文本内容</param> /// <param name="signType">RSA 私钥长度1024 ,RSA2 私钥长度2048 </param> /// <returns></returns> public static RSACryptoServiceProvider LoadPrivateKeyPKCS1(string privateKeyPemPkcs1, string signType) { try { privateKeyPemPkcs1 = privateKeyPemPkcs1.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim(); privateKeyPemPkcs1 = privateKeyPemPkcs1.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim(); byte[] data = null; //读取带 data = Convert.FromBase64String(privateKeyPemPkcs1); RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(data, signType); return rsa; } catch (Exception ex) { throw ex; } return null; } private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey, string signType) { byte[] MODULUS, E, D, P, Q, DP, DQ, IQ; // --------- Set up stream to decode the asn.1 encoded RSA private key ------ MemoryStream mem = new MemoryStream(privkey); BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading byte bt = 0; ushort twobytes = 0; int elems = 0; try { twobytes = binr.ReadUInt16(); if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81) binr.ReadByte(); //advance 1 byte else if (twobytes == 0x8230) binr.ReadInt16(); //advance 2 bytes else return null; twobytes = binr.ReadUInt16(); if (twobytes != 0x0102) //version number return null; bt = binr.ReadByte(); if (bt != 0x00) return null; //------ all private key components are Integer sequences ---- elems = GetIntegerSize(binr); MODULUS = binr.ReadBytes(elems); elems = GetIntegerSize(binr); E = binr.ReadBytes(elems); elems = GetIntegerSize(binr); D = binr.ReadBytes(elems); elems = GetIntegerSize(binr); P = binr.ReadBytes(elems); elems = GetIntegerSize(binr); Q = binr.ReadBytes(elems); elems = GetIntegerSize(binr); DP = binr.ReadBytes(elems); elems = GetIntegerSize(binr); DQ = binr.ReadBytes(elems); elems = GetIntegerSize(binr); IQ = binr.ReadBytes(elems); // ------- create RSACryptoServiceProvider instance and initialize with public key ----- CspParameters CspParameters = new CspParameters(); CspParameters.Flags = CspProviderFlags.UseMachineKeyStore; int bitLen = 1024; if ("RSA2".Equals(signType)) { bitLen = 2048; } RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(bitLen, CspParameters); //RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); RSAParameters RSAparams = new RSAParameters(); RSAparams.Modulus = MODULUS; RSAparams.Exponent = E; RSAparams.D = D; RSAparams.P = P; RSAparams.Q = Q; RSAparams.DP = DP; RSAparams.DQ = DQ; RSAparams.InverseQ = IQ; RSA.ImportParameters(RSAparams); return RSA; } catch (Exception ex) { throw ex; // return null; } finally { binr.Close(); } } private static int GetIntegerSize(BinaryReader binr) { byte bt = 0; byte lowbyte = 0x00; byte highbyte = 0x00; int count = 0; bt = binr.ReadByte(); if (bt != 0x02) //expect integer return 0; bt = binr.ReadByte(); if (bt == 0x81) count = binr.ReadByte(); // data size in next byte else if (bt == 0x82) { highbyte = binr.ReadByte(); // data size in next 2 bytes lowbyte = binr.ReadByte(); byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; count = BitConverter.ToInt32(modint, 0); } else { count = bt; // we already have the data size } while (binr.ReadByte() == 0x00) { //remove high order zeros in data count -= 1; } binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte return count; } /// <summary> /// PKCS8 文本转RSACryptoServiceProvider 对象 /// </summary> /// <param name="privateKeyPemPkcs8"></param> /// <returns></returns> public static RSACryptoServiceProvider LoadPrivateKeyPKCS8(string privateKeyPemPkcs8) { try { //PKCS8是“BEGIN PRIVATE KEY” privateKeyPemPkcs8 = privateKeyPemPkcs8.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim(); privateKeyPemPkcs8 = privateKeyPemPkcs8.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\r", "").Replace("\n", "").Trim(); //pkcs8 文本先转为 .NET XML 私钥字符串 string privateKeyXml = RSAPrivateKeyJava2DotNet(privateKeyPemPkcs8); RSACryptoServiceProvider publicRsa = new RSACryptoServiceProvider(); publicRsa.FromXmlString(privateKeyXml); return publicRsa; } catch (Exception ex) { throw ex; } } /// <summary> /// PKCS8 私钥文本 转 .NET XML 私钥文本 /// </summary> /// <param name="privateKeyPemPkcs8"></param> /// <returns></returns> public static string RSAPrivateKeyJava2DotNet(string privateKeyPemPkcs8) { RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKeyPemPkcs8)); return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>", Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned())); } #endregion /// <summary> /// 加载公钥证书 /// </summary> /// <param name="publicKeyCert">公钥证书文本内容</param> /// <returns></returns> public static RSACryptoServiceProvider LoadPublicCert(string publicKeyCert) { publicKeyCert = publicKeyCert.Replace("-----BEGIN CERTIFICATE-----", "").Replace("-----END CERTIFICATE-----", "").Replace("\r", "").Replace("\n", "").Trim(); byte[] bytesCerContent = Convert.FromBase64String(publicKeyCert); X509Certificate2 x509 = new X509Certificate2(bytesCerContent); RSACryptoServiceProvider rsaPub = (RSACryptoServiceProvider)x509.PublicKey.Key; return rsaPub; } /// <summary> /// pem 公钥文本 转 .NET RSACryptoServiceProvider。 /// </summary> /// <param name="publicKeyPem"></param> /// <returns></returns> public static RSACryptoServiceProvider LoadPublicKey(string publicKeyPem) { publicKeyPem = publicKeyPem.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\r", "").Replace("\n", "").Trim(); //pem 公钥文本 转 .NET XML 公钥文本。 string publicKeyXml = RSAPublicKeyJava2DotNet(publicKeyPem); RSACryptoServiceProvider publicRsa = new RSACryptoServiceProvider(); publicRsa.FromXmlString(publicKeyXml); return publicRsa; } /// <summary> /// pem 公钥文本 转 .NET XML 公钥文本。 /// </summary> /// <param name="publicKey"></param> /// <returns></returns> private static string RSAPublicKeyJava2DotNet(string publicKey) { RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey)); return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>", Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); } } }
使用:
这个方法只能加密 私钥长度/8 -11 个字符,分段加密的代码要自己处理了。
私钥加密:
private void btnPrivateKeyEncrypt_Click(object sender, EventArgs e) { try { //byte[] rst = RsaEncryptUtil.encryptByPrivateKey(txtMingWen.Text, txtPrivateKey.Text); byte[] rst = RsaEncryptUtil.encryptByPrivateKey(txtMingWen.Text, txtPrivateKey.Text,cbxPrivateKeyFormat.Text); //加密后一般转Base64String ,Base64FormattingOptions.InsertLineBreaks. string base64str = Convert.ToBase64String(rst, Base64FormattingOptions.InsertLineBreaks); txtJiaMiHou.Text = base64str; } catch (Exception ex) { MessageBox.Show(ex.Message); } }
公钥解密:
private void btnPubKeyDecrypt_Click(object sender, EventArgs e) { try { byte[] rst = RsaEncryptUtil.decryptByPublicKey(txtJiaMiHou.Text, txtPubKey.Text); string strRst = Encoding.UTF8.GetString(rst); txtJieMiHou.Text = strRst; } catch (Exception ex) { MessageBox.Show(ex.Message); } }
-