c#(实现rsa非对称加密算法)-mile米乐体育

c#,实现rsa非对称加密算法

目录
  •   公钥与私钥
  •   c#实现

  公钥与私钥

  公钥与私钥是成对的,一般的,我们认为的是公钥加密、私钥解密、私钥签名、公钥验证,有人说成私钥加密,公钥解密时不对的。

  公钥与私钥的生成有多种方式,可以通过程序生成(下文具体实现),可以通过openssl工具:  

     # 生成一个私钥,推荐使用1024位的秘钥,秘钥以pem格式保存到-out参数指定的文件中,采用pkcs1格式     openssl genrsa -out rsa.pem 1024      # 生成与私钥对应的公钥,生成的是subject public key,一般配合pkcs8格式私钥使用     openssl rsa -in rsa.pem -pubout -out rsa.pub  

  rsa生成公钥与私钥一般有两种格式:pkcs1和pkcs8,上面的命令生成的秘钥是pkcs1格式的,而公钥是subject public key,一般配合pkcs8格式私钥使用,所以就可能会涉及到pkcs1和pkcs8之间的转换:

     # pkcs1格式私钥转换为pkcs8格式私钥,私钥直接输出到-out参数指定的文件中     openssl pkcs8 -topk8 -inform pem -in rsa.pem -outform pem -nocrypt -out rsa_pkcs8.pem     # pkcs8格式私钥转换为pkcs1格式私钥,私钥直接输出到-out参数指定的文件中     openssl rsa -in rsa_pkcs8.pem -out rsa_pkcs1.pem      # pkcs1格式公钥转换为pkcs8格式公钥,转换后的内容直接输出     openssl rsa -pubin -in rsa.pub -rsapublickey_out     # pkcs8格式公钥转换为pkcs1格式公钥,转换后的内容直接输出     openssl rsa -rsapublickey_in -pubout -in rsa.pub

  现实中,我们往往从pem、crt、pfx文件获取公私和私钥,crt、pfx的制作可以参考:简单的制作ssl证书,并在nginx和iis中使用,或者使用现成的:https://www.zzm8.com/d/file/p/2021062118042516953/2021062118042516954 (提取码:c6tj),密码都是:123456

  c#实现

  为了方便读取pem、crt、pfx文件中的公私和私钥,这里我使用了第三方的包:portable.bouncycastle,可以使用nuget安装:install-package portable.bouncycastle

  接着,这里我封装了一个rsahelper辅助类来实现各种rsa加密的过程: 

 using org.bouncycastle.utilities.io.pem; using system; using system.collections.generic; using system.io; using system.security.cryptography; using system.security.cryptography.x509certificates; using system.text;  namespace consoleapp1 {     public class rsahelper     {          #region key         ///          /// 将秘钥保存到pem文件         ///          ///          ///          ///          ///          public static void writetopem(byte[] buffer, bool isprivatekey, string pemfilename)         {             pemobject pemobject = new pemobject(isprivatekey ? "rsa private key" : "rsa public key", buffer);             if (file.exists(pemfilename))             {                 file.delete(pemfilename);             }             using (var filestream = new filestream(pemfilename, filemode.openorcreate, fileaccess.write))             {                 using (var sw = new streamwriter(filestream))                 {                     var writer = new pemwriter(sw);                     writer.writeobject(pemobject);                     sw.flush();                 }             }         }         ///          /// 从pem文件中读取秘钥         ///          ///          ///          public static byte[] readfrompem(string pemfilename)         {             using (var filestream = new filestream(pemfilename, filemode.open, fileaccess.read))             {                 using (var sw = new streamreader(filestream))                 {                     var writer = new pemreader(sw);                     return writer.readpemobject().content;                 }             }         }          ///          /// 从xml中读取秘钥         ///          ///          ///          ///          ///          public static byte[] readfromxml(string xml, bool isprivatekey, bool usepkcs8)         {             using (var rsa = new rsacryptoserviceprovider())             {                 rsa.fromxmlstring(xml);                 if (isprivatekey)                 {                     return usepkcs8 ? rsa.exportpkcs8privatekey() : rsa.exportrsaprivatekey();                 }                 return usepkcs8 ? rsa.exportsubjectpublickeyinfo() : rsa.exportrsapublickey();             }         }         ///          /// 将秘钥保存到xml中         ///          ///          ///          ///          ///          public static string writetoxml(byte[] buffer, bool isprivatekey, bool usepkcs8)         {             using (var rsa = creatersacryptoserviceprovider(buffer, isprivatekey, usepkcs8))             {                 return rsa.toxmlstring(isprivatekey);             }         }          ///          /// 获取rsa非对称加密的key         ///          ///          ///          public static void generatersakey(bool usepkcs8, out byte[] publickey, out byte[] privatekey)         {             using (rsacryptoserviceprovider rsa = new rsacryptoserviceprovider())             {                 rsa.keysize = 1024;//1024位                 if (usepkcs8)                 {                     //使用pkcs8填充方式导出                     publickey = rsa.exportsubjectpublickeyinfo();//公钥                     privatekey = rsa.exportpkcs8privatekey();//私钥                 }                 else                 {                     //使用pkcs1填充方式导出                     publickey = rsa.exportrsapublickey();//公钥                     privatekey = rsa.exportrsaprivatekey();//私钥                 }             }         }         ///          /// 从pfx文件获取rsa非对称加密的key         ///          ///          ///          ///          public static void readfrompfx(string pfxfilename, string password, out byte[] publickey, out byte[] privatekey)         {             x509certificate2 x509certificate2 = new x509certificate2(pfxfilename, password, x509keystorageflags.exportable);             publickey = x509certificate2.getrsapublickey().exportrsapublickey();             privatekey = x509certificate2.getrsaprivatekey().exportrsaprivatekey();         }         ///          /// 从crt文件中读取公钥         ///          ///          ///          ///          public static byte[] readpublickeyfromcrt(string crtfilename, string password)         {             x509certificate2 x509certificate2 = new x509certificate2(crtfilename, password, x509keystorageflags.exportable);             var publickey = x509certificate2.getrsapublickey().exportrsapublickey();             return publickey;         }         #endregion          #region pkcs1 and pkcs8          ///          /// pkcs1转pkcs8         ///          ///          ///          ///          public static byte[] pkcs1topkcs8(bool isprivatekey, byte[] buffer)         {             using (var rsa = new rsacryptoserviceprovider())             {                 if (isprivatekey)                 {                     rsa.importrsaprivatekey(buffer, out _);                     return rsa.exportpkcs8privatekey();                 }                 else                 {                     rsa.importrsapublickey(buffer, out _);                     return rsa.exportsubjectpublickeyinfo();                 }             }         }         ///          /// pkcs8转pkcs1         ///          ///          ///          ///          public static byte[] pkcs8topkcs1(bool isprivatekey, byte[] buffer)         {             using (var rsa = new rsacryptoserviceprovider())             {                 if (isprivatekey)                 {                     rsa.importpkcs8privatekey(buffer, out _);                     return rsa.exportrsaprivatekey();                 }                 else                 {                     rsa.importsubjectpublickeyinfo(buffer, out _);                     return rsa.exportrsapublickey();                 }             }         }          #endregion          #region rsa          ///          /// 获取一个rsacryptoserviceprovider         ///          ///          ///          ///          ///          public static rsacryptoserviceprovider creatersacryptoserviceprovider(byte[] buffer, bool isprivatekey, bool usepkcs8 = false)         {             rsacryptoserviceprovider rsa = new rsacryptoserviceprovider();             if (isprivatekey)             {                 if (usepkcs8)                     rsa.importpkcs8privatekey(buffer, out _);                 else                     rsa.importrsaprivatekey(buffer, out _);             }             else             {                 if (usepkcs8)                     rsa.importsubjectpublickeyinfo(buffer, out _);                 else                     rsa.importrsapublickey(buffer, out _);             }             return rsa;         }          ///          /// rsa公钥加密         ///          /// 待加密的明文         /// 公钥         /// 是否使用pkcs8填充         ///          public static string rsaencrypt(string value, byte[] publickey, bool usepkcs8 = false)         {             if (string.isnullorempty(value)) return value;              using (rsacryptoserviceprovider rsa = creatersacryptoserviceprovider(publickey, false, usepkcs8))             {                 var buffer = encoding.utf8.getbytes(value);                 buffer = rsa.encrypt(buffer, false);                  //使用hex格式输出数据                 stringbuilder result = new stringbuilder();                 foreach (byte b in buffer)                 {                     result.appendformat("{0:x2}", b);                 }                 return result.tostring();                 //或者使用下面的输出                 //return bitconverter.tostring(buffer).replace("-", "").tolower();             }         }         ///          /// rsa私钥解密         ///          /// 密文         /// 私钥         /// 是否使用pkcs8填充         ///          public static string rsadecrypt(string value, byte[] privatekey, bool usepkcs8 = false)         {             if (string.isnullorempty(value)) return value;              using (rsacryptoserviceprovider rsa = creatersacryptoserviceprovider(privatekey, true, usepkcs8))             {                 //转换hex格式数据为byte数组                 var buffer = new byte[value.length / 2];                 for (var i = 0; i < buffer.length; i  )                 {                     buffer[i] = (byte)convert.toint32(value.substring(i * 2, 2), 16);                 }                 buffer = rsa.decrypt(buffer, false);                 return encoding.utf8.getstring(buffer);             }         }         ///          /// rsa私钥生成签名         ///          /// 原始值         /// 公钥         /// 签名hash算法:sha,sha1,md5,sha256,sha384,sha512         /// 是否使用pkcs8填充         ///          public static string sign(string value, byte[] privatekey, string halg = "md5", bool usepkcs8 = false)         {             if (string.isnullorempty(value)) return value;              using (rsacryptoserviceprovider rsa = creatersacryptoserviceprovider(privatekey, true, usepkcs8))             {                 byte[] buffer = encoding.utf8.getbytes(value);                 buffer = rsa.signdata(buffer, hashalgorithm.create(halg));                  //使用hex格式输出数据                 stringbuilder result = new stringbuilder();                 foreach (byte b in buffer)                 {                     result.appendformat("{0:x2}", b);                 }                 return result.tostring();                 //或者使用下面的输出                 //return bitconverter.tostring(buffer).replace("-", "").tolower();             }         }         ///          /// rsa公钥验证签名         ///          /// 原始值         /// 公钥         /// 签名         /// 签名hash算法:sha,sha1,md5,sha256,sha384,sha512         /// 是否使用pkcs8填充         ///          public static bool verify(string value, byte[] publickey, string signature, string halg = "md5", bool usepkcs8 = false)         {             if (string.isnullorempty(value)) return false;              using (rsacryptoserviceprovider rsa = creatersacryptoserviceprovider(publickey, false, usepkcs8))             {                 //转换hex格式数据为byte数组                 var buffer = new byte[signature.length / 2];                 for (var i = 0; i < buffer.length; i  )                 {                     buffer[i] = (byte)convert.toint32(signature.substring(i * 2, 2), 16);                 }                 return rsa.verifydata(encoding.utf8.getbytes(value), hashalgorithm.create(halg), buffer);             }         }         #endregion     } }

  可以使用生成rsa的公私秘钥:  

     //通过程序生成     rsahelper.generatersakey(usepkcs8, out publickey, out privatekey);

  生成秘钥后,需要保存,一般保存到pem文件中:  

     //保存到pem文件,filepath是文件目录     rsahelper.writetopem(publickey, false, path.combine(filepath, "rsa.pub"));     rsahelper.writetopem(privatekey, true, path.combine(filepath, "rsa.pem"));

  还以将公钥和私钥输出为xml格式:  

     //保存到xml中     string publickeyxml = rsahelper.writetoxml(publickey, false, usepkcs8);     string privatekeyxml = rsahelper.writetoxml(privatekey, true, usepkcs8);

  保存到pem文件和xml中后,也可以从中读取:  

     //从pem文件获取,filepath是文件目录     publickey = rsahelper.readfrompem(path.combine(filepath, "rsa.pub"));     privatekey = rsahelper.readfrompem(path.combine(filepath, "rsa.pem"));      //从xml中读取     publickey = rsahelper.readfromxml(publickeyxml, false, usepkcs8);     privatekey = rsahelper.readfromxml(privatekeyxml, true, usepkcs8);

  还可以从crt证书中读取公钥,而crt文件不包含私钥,因此需要单独获取私钥:

     //从crt文件读取,filepath是文件目录     publickey = rsahelper.readpublickeyfromcrt(path.combine(filepath, "demo.crt"), "");     privatekey = rsahelper.readfrompem(path.combine(filepath, "demo.key"));

  pfx文件中包含了公钥和私钥,可以很方便就读取到:  

     //从demo.pfx文件读取(demo.pfx采用的是pkcs1),filepath是文件目录     rsahelper.readfrompfx(path.combine(filepath, "demo.pfx"), "123456", out publickey, out privatekey);

  有时候我们还可能需要进行秘钥的转换:  

     // pkcs8格式公钥转换为pkcs1格式公钥     publickey = rsahelper.pkcs8topkcs1(false, publickey);     // pkcs8格式私钥转换为pkcs1格式私钥     privatekey = rsahelper.pkcs8topkcs1(true, privatekey);     // pkcs1格式公钥转换为pkcs8格式公钥     publickey = rsahelper.pkcs1topkcs8(false, publickey);     // pkcs1格式私钥转换为pkcs8格式私钥     privatekey = rsahelper.pkcs1topkcs8(true, privatekey);

  有了公钥和私钥,接下就就能实现加密、解密、签名、验证签名等操作了:  

     string encrypttext = rsahelper.rsaencrypt(text, publickey, usepkcs8);     console.writeline($"【{text}】经过【rsa】加密后:{encrypttext}");      string decrypttext = rsahelper.rsadecrypt(encrypttext, privatekey, usepkcs8);     console.writeline($"【{encrypttext}】经过【rsa】解密后:{decrypttext}");      string signature = rsahelper.sign(text, privatekey, "md5", usepkcs8);     console.writeline($"【{text}】经过【rsa】签名后:{signature}");      bool result = rsahelper.verify(text, publickey, signature, "md5", usepkcs8);     console.writeline($"【{text}】的签名【{signature}】经过【rsa】验证后结果是:{result}");

  完整的demo代码:  

     using system;     using system.io;          namespace consoleapp1     {         class program         {             static void main(string[] args)             {                 string text = "上山打老虎";                 bool usepkcs8 = true;// usepkcs8=true表示是否成pkcs8格式的公私秘钥,否则乘车pkcs1格式的公私秘钥                 string filepath = directory.getcurrentdirectory();                 console.writeline($"文件路径:{filepath}");// 存放pem,crt,pfx等文件的目录                 byte[] publickey, privatekey;// 公钥和私钥                      //通过程序生成                 rsahelper.generatersakey(usepkcs8, out publickey, out privatekey);                 //从pem文件获取,filepath是文件目录                 //publickey = rsahelper.readfrompem(path.combine(filepath, "rsa.pub"));                 //privatekey = rsahelper.readfrompem(path.combine(filepath, "rsa.pem"));                      //从demo.pfx文件读取(demo.pfx采用的是pkcs1),filepath是文件目录                 //rsahelper.readfrompfx(path.combine(filepath, "demo.pfx"), "123456", out publickey, out privatekey);                 //从crt文件读取,filepath是文件目录                 //publickey = rsahelper.readpublickeyfromcrt(path.combine(filepath, "demo.crt"), "");                 //privatekey = rsahelper.readfrompem(path.combine(filepath, "demo.key"));                      //保存到pem文件,filepath是文件目录                 rsahelper.writetopem(publickey, false, path.combine(filepath, "rsa.pub"));                 rsahelper.writetopem(privatekey, true, path.combine(filepath, "rsa.pem"));                      //保存到xml中                 string publickeyxml = rsahelper.writetoxml(publickey, false, usepkcs8);                 string privatekeyxml = rsahelper.writetoxml(privatekey, true, usepkcs8);                      //从xml中读取                 publickey = rsahelper.readfromxml(publickeyxml, false, usepkcs8);                 privatekey = rsahelper.readfromxml(privatekeyxml, true, usepkcs8);                      // pkcs8格式公钥转换为pkcs1格式公钥                 publickey = rsahelper.pkcs8topkcs1(false, publickey);                 // pkcs8格式私钥转换为pkcs1格式私钥                 privatekey = rsahelper.pkcs8topkcs1(true, privatekey);                 // pkcs1格式公钥转换为pkcs8格式公钥                 publickey = rsahelper.pkcs1topkcs8(false, publickey);                 // pkcs1格式私钥转换为pkcs8格式私钥                 privatekey = rsahelper.pkcs1topkcs8(true, privatekey);                      string encrypttext = rsahelper.rsaencrypt(text, publickey, usepkcs8);                 console.writeline($"【{text}】经过【rsa】加密后:{encrypttext}");                      string decrypttext = rsahelper.rsadecrypt(encrypttext, privatekey, usepkcs8);                 console.writeline($"【{encrypttext}】经过【rsa】解密后:{decrypttext}");                      string signature = rsahelper.sign(text, privatekey, "md5", usepkcs8);                 console.writeline($"【{text}】经过【rsa】签名后:{signature}");                      bool result = rsahelper.verify(text, publickey, signature, "md5", usepkcs8);                 console.writeline($"【{text}】的签名【{signature}】经过【rsa】验证后结果是:{result}");             }         }     }

以上就是c# 实现rsa非对称加密算法的详细内容,更多关于c# rsa非对称加密算法的资料请关注趣讯吧其它相关文章!

展开全文
内容来源于互联网和用户投稿,文章中一旦含有米乐app官网登录的联系方式务必识别真假,本站仅做信息展示不承担任何相关责任,如有侵权或涉及法律问题请联系米乐app官网登录删除

最新文章

网站地图