C#实现RSA加密解密
程序员文章站
2022-05-26 14:29:14
.Net自带API结合BouncyCastle类库实现RSA加密解密,RSA密钥生成和密钥格式转换. ......
rsa介绍
rsa公钥加密算法是1977年由ron rivest、adi shamirh和lenadleman在(美国麻省理工学院)开发的。rsa取名来自开发他们三者的名字。
rsa的缺点:
-
产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次一密。
-
分组长度太大,为保证安全性,n 至少也要 600bits以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。目前,set(secure electronic transaction)协议中要求ca采用2048bits长的密钥,其他实体使用1024比特的密钥。c)rsa密钥长度随着保密级别提高,增加很快。下表列出了对同一安全级别所对应的密钥长度。
保密级别 对称密钥长度(bit) rsa密钥长度(bit) ecc密钥长度(bit) 保密年限 80 80 1024 160 2010 112 112 2048 224 2030 128 128 3072 256 2040 192 192 7680 384 2080 256 256 15360 512 2120
c#中rsa的相关操作
- 生成公钥和私钥
struct rsasecretkey { public rsasecretkey(string privatekey, string publickey) { privatekey = privatekey; publickey = publickey; } public string publickey { get; set; } public string privatekey { get; set; } public override string tostring() { return string.format( "privatekey: {0}\r\npublickey: {1}", privatekey, publickey); } } /// <summary> /// generate rsa secret key /// </summary> /// <param name="keysize">the size of the key,must from 384 bits to 16384 bits in increments of 8 </param> /// <returns></returns> rsasecretkey generatersasecretkey(int keysize) { rsasecretkey rsakey = new rsasecretkey(); using (rsacryptoserviceprovider rsa = new rsacryptoserviceprovider(keysize)) { rsakey.privatekey = rsa.toxmlstring(true); rsakey.publickey = rsa.toxmlstring(false); } return rsakey; }
- 实现公钥加密私钥解密
string rsaencrypt(string xmlpublickey,string content) { string encryptedcontent = string.empty; using(rsacryptoserviceprovider rsa = new rsacryptoserviceprovider()) { rsa.fromxmlstring(xmlpublickey); byte[] encrypteddata = rsa.encrypt(encoding.default.getbytes(content), false); encryptedcontent = convert.tobase64string(encrypteddata); } return encryptedcontent; } string rsadecrypt(string xmlprivatekey, string content) { string decryptedcontent = string.empty; using (rsacryptoserviceprovider rsa = new rsacryptoserviceprovider()) { rsa.fromxmlstring(xmlprivatekey); byte[] decrypteddata = rsa.decrypt(convert.frombase64string(content), false); decryptedcontent = encoding.getencoding("gb2312").getstring(decrypteddata); } return decryptedcontent; }
密钥格式的转换
c#中rsa公钥和私钥的格式都是xml的,而在其他语言如java中,生成的rsa密钥就是普通的base64字符串,所以需要将c#xml格式的密钥转换成普通的base64字符串,同时也要实现base64密钥字符串生成c#中xml格式的密钥.
安装 bouncycastle 这个nuget包pm > install-package bouncycastle
bouncycastle项目网址
bouncycastlegithub地址
构造一个rsakeyconventer类
namespace rsa { using system; using system.security.cryptography; using org.bouncycastle.asn1.pkcs; using org.bouncycastle.math; using org.bouncycastle.pkcs; using org.bouncycastle.asn1.x509; using org.bouncycastle.x509; using org.bouncycastle.security; using org.bouncycastle.crypto.parameters; public class rsakeyconverter { /// <summary> /// xml private key -> base64 private key string /// </summary> /// <param name="xmlprivatekey"></param> /// <returns></returns> public static string fromxmlprivatekey(string xmlprivatekey) { string result = string.empty; using(rsacryptoserviceprovider rsa = new rsacryptoserviceprovider()) { rsa.fromxmlstring(xmlprivatekey); rsaparameters param = rsa.exportparameters(true); rsaprivatecrtkeyparameters privatekeyparam = new rsaprivatecrtkeyparameters( new biginteger(1, param.modulus), new biginteger(1, param.exponent), new biginteger(1, param.d), new biginteger(1, param.p), new biginteger(1, param.q), new biginteger(1, param.dp), new biginteger(1, param.dq), new biginteger(1, param.inverseq)); privatekeyinfo privatekey = privatekeyinfofactory.createprivatekeyinfo(privatekeyparam); result = convert.tobase64string(privatekey.toasn1object().getencoded()); } return result; } /// <summary> /// xml public key -> base64 public key string /// </summary> /// <param name="xmlpublickey"></param> /// <returns></returns> public static string fromxmlpublickey(string xmlpublickey) { string result = string.empty; using(rsacryptoserviceprovider rsa = new rsacryptoserviceprovider()) { rsa.fromxmlstring(xmlpublickey); rsaparameters p = rsa.exportparameters(false); rsakeyparameters keyparams = new rsakeyparameters( false, new biginteger(1,p.modulus), new biginteger(1, p.exponent)); subjectpublickeyinfo publickeyinfo = subjectpublickeyinfofactory.createsubjectpublickeyinfo(keyparams); result = convert.tobase64string(publickeyinfo.toasn1object().getencoded()); } return result; } /// <summary> /// base64 private key string -> xml private key /// </summary> /// <param name="privatekey"></param> /// <returns></returns> public static string toxmlprivatekey(string privatekey) { rsaprivatecrtkeyparameters privatekeyparams = privatekeyfactory.createkey(convert.frombase64string(privatekey)) as rsaprivatecrtkeyparameters; using(rsacryptoserviceprovider rsa = new rsacryptoserviceprovider()) { rsaparameters rsaparams = new rsaparameters() { modulus = privatekeyparams.modulus.tobytearrayunsigned(), exponent = privatekeyparams.publicexponent.tobytearrayunsigned(), d = privatekeyparams.exponent.tobytearrayunsigned(), dp = privatekeyparams.dp.tobytearrayunsigned(), dq = privatekeyparams.dq.tobytearrayunsigned(), p = privatekeyparams.p.tobytearrayunsigned(), q = privatekeyparams.q.tobytearrayunsigned(), inverseq = privatekeyparams.qinv.tobytearrayunsigned() }; rsa.importparameters(rsaparams); return rsa.toxmlstring(true); } } /// <summary> /// base64 public key string -> xml public key /// </summary> /// <param name="pubilckey"></param> /// <returns></returns> public static string toxmlpublickey(string pubilckey) { rsakeyparameters p = publickeyfactory.createkey(convert.frombase64string(pubilckey)) as rsakeyparameters; using(rsacryptoserviceprovider rsa = new rsacryptoserviceprovider()) { rsaparameters rsaparams = new rsaparameters { modulus = p.modulus.tobytearrayunsigned(), exponent = p.exponent.tobytearrayunsigned() }; rsa.importparameters(rsaparams); return rsa.toxmlstring(false); } } } }