欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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;
}

C#实现RSA加密解密

  • 实现公钥加密私钥解密
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加密解密
C#实现RSA加密解密

密钥格式的转换

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);
            }
        }
    }
}