RSA加解密算法

傷城~ 2021-11-23 08:22 454阅读 0赞

一、什么是RSA

  RSA公开密钥密码体制。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。   

  在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK。正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA 密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法 与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的 密钥解密并可核对信息摘要。   

  RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。RSA是被研究得最广泛的公钥算法,从提出到现在的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。

二、RSA算法密钥长度的选择

  1. 非对称加密算法中1024 bit密钥的强度相当于对称加密算法80bit密钥的强度。

  2. 密钥长度增长一倍,公钥操作所需时间增加约4倍,私钥操作所需时间增加约8倍,公私钥生成时间约增长16倍。

  3. 一次能加密的密文长度与密钥长度成正比,加密后的密文长度跟密钥长度相同(RSA加密内容的长度有限制,和密钥长度有关,这是由它的算法决定的)

  a、加密的明文长度不能超过RSA密钥的长度减去11byte,比如密钥长度是1024位的,1024位=1024bit=128byte,128-11=117byte,所以明文长度不能超过117byte,如果长度超过该值将会抛出异常。

  b、加密后密文的长度为密钥的长度,如密钥长度为1024bit(128Byte),最后生成的密文固定为 1024bit(128Byte)。

三、C#中的RSA加解密

  .NET Framework 类库提供了System.Security 命名空间,System.Security 命名空间提供公共语言运行时安全系统的基础结构,包括权限的基类,而该命名空间下提供了RSACryptoServiceProvider类来执行RSA算法的不对称加密和解密。

1.密钥对的生成:

a、根据RSACryptoServiceProvider直接生成

  1. /// <summary>
  2. /// 生成密钥
  3. /// </summary>
  4. public RSAKey GenerateRSAKey()
  5. {
  6. RSAKey RSAKEY = new RSAKey();
  7. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
  8. RSAKEY.PrivateKey = RSA.ToXmlString(true); //生成私钥
  9. RSAKEY.PublicKey = RSA.ToXmlString(false); //生成公钥
  10. RSA.Clear();
  11. return RSAKEY;
  12. }

b、通过Makecert证书创建工具生成安全证书

  1. makecert -r -pe -n "CN=RSAKey" -b 03/31/2005 -e 12/31/2012 -sky exchange -ss my

可通过”Visual Studio命令提示行”执行以上命令生成证书。

查看生成的证书:

运行->输入mmc打开控制台->选择文件->添加/删除管理单元->在弹出框左侧找到证书->选中证书添加->选择我的用户账户->完成确定

此时就可以在对应位置查看到我们刚刚创建的名为RSAKey的证书了,如下图:

![Image 1][]

最终我们可以将证书导出为:

![Image 1][]

其中RSAKey.cer中含有加密用的公钥,RSAKey.pfx中含有解密用的私钥。

2.创建加解密RSA

  1. /// <summary>
  2. /// 创建加密RSA
  3. /// </summary>
  4. /// <param name="publicKey">公钥</param>
  5. /// <returns></returns>
  6. private RSACryptoServiceProvider CreateEncryptRSA(string publicKey)
  7. {
  8. try
  9. {
  10. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
  11. RSA.FromXmlString(publicKey);
  12. return RSA;
  13. }
  14. catch (CryptographicException ex)
  15. {
  16. throw ex;
  17. }
  18. }
  19. /// <summary>
  20. /// 创建解密RSA
  21. /// </summary>
  22. /// <param name="privateKey">私钥</param>
  23. /// <returns></returns>
  24. private RSACryptoServiceProvider CreateDecryptRSA(string privateKey)
  25. {
  26. try
  27. {
  28. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
  29. RSA.FromXmlString(privateKey);
  30. return RSA;
  31. }
  32. catch (CryptographicException ex)
  33. {
  34. throw ex;
  35. }
  36. }
  37. /// <summary>
  38. /// 根据安全证书创建加密RSA
  39. /// </summary>
  40. /// <param name="certfile">公钥文件</param>
  41. /// <returns></returns>
  42. private RSACryptoServiceProvider X509CertCreateEncryptRSA(string certfile)
  43. {
  44. try
  45. {
  46. X509Certificate2 x509Cert = new X509Certificate2(certfile);
  47. RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)x509Cert.PublicKey.Key;
  48. return RSA;
  49. }
  50. catch (CryptographicException ex)
  51. {
  52. throw ex;
  53. }
  54. }
  55. /// <summary>
  56. /// 根据私钥文件创建解密RSA
  57. /// </summary>
  58. /// <param name="keyfile">私钥文件</param>
  59. /// <param name="password">访问含私钥文件的密码</param>
  60. /// <returns></returns>
  61. private RSACryptoServiceProvider X509CertCreateDecryptRSA(string keyfile, string password)
  62. {
  63. try
  64. {
  65. X509Certificate2 x509Cert = new X509Certificate2(keyfile, password);
  66. RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)x509Cert.PrivateKey;
  67. return RSA;
  68. }
  69. catch (CryptographicException ex)
  70. {
  71. throw ex;
  72. }
  73. }

其中所提及的私钥文件和公钥文件就是根据Makecert证书创建工具生成安全证书,而X509CertCreateDecryptRSA方法中的参数password是我们导出私钥文件所设置的访问密码,如果没有改密码即使有私钥证书也没办法解密。

3.RSA加解密

  1. /// <summary>
  2. /// 加密
  3. /// </summary>
  4. /// <param name="dataToEncrypt">待加密数据</param>
  5. /// <param name="publicKey">公钥</param>
  6. /// <returns></returns>
  7. public string Encrypt(string dataToEncrypt, string publicKey)
  8. {
  9. Encoding encoder = Encoding.UTF8;
  10. byte[] _dataToEncrypt = encoder.GetBytes(dataToEncrypt);
  11. return this.Encrypt(_dataToEncrypt, publicKey);
  12. }
  13. /// <summary>
  14. /// 加密
  15. /// </summary>
  16. /// <param name="dataToEncrypt">待加密数据</param>
  17. /// <param name="publicKey">公钥</param>
  18. /// <returns></returns>
  19. public string Encrypt(byte[] dataToEncrypt, string publicKey)
  20. {
  21. using (RSACryptoServiceProvider RSA = this.CreateEncryptRSA(publicKey))
  22. {
  23. byte[] encryptedData = RSA.Encrypt(dataToEncrypt, false);
  24. return this.BytesToHexString(encryptedData);
  25. }
  26. }
  27. /// <summary>
  28. /// 根据安全证书加密
  29. /// </summary>
  30. /// <param name="dataToEncrypt"></param>
  31. /// <param name="certfile"></param>
  32. /// <returns></returns>
  33. public string X509CertEncrypt(string dataToEncrypt, string certfile)
  34. {
  35. Encoding encoder = Encoding.UTF8;
  36. byte[] _dataToEncrypt = encoder.GetBytes(dataToEncrypt);
  37. return this.X509CertEncrypt(_dataToEncrypt, certfile);
  38. }
  39. /// <summary>
  40. /// 根据安全证书加密
  41. /// </summary>
  42. /// <param name="dataToEncrypt">待加密数据</param>
  43. /// <param name="certfile">安全证书</param>
  44. /// <returns></returns>
  45. public string X509CertEncrypt(byte[] dataToEncrypt, string certfile)
  46. {
  47. if (!File.Exists(certfile))
  48. {
  49. throw new ArgumentNullException(certfile, "加密证书未找到");
  50. }
  51. using (RSACryptoServiceProvider RSA = this.X509CertCreateEncryptRSA(certfile))
  52. {
  53. byte[] encryptedData = RSA.Encrypt(dataToEncrypt, false);
  54. return this.BytesToHexString(encryptedData);
  55. }
  56. }
  57. /// <summary>
  58. /// 解密
  59. /// </summary>
  60. /// <param name="encryptedData">待解密数据</param>
  61. /// <param name="privateKey">私钥</param>
  62. /// <returns></returns>
  63. public string Decrypt(string encryptedData, string privateKey)
  64. {
  65. using (RSACryptoServiceProvider RSA = this.CreateDecryptRSA(privateKey))
  66. {
  67. Encoding encoder = Encoding.UTF8;
  68. byte[] _encryptedData = HexStringToBytes(encryptedData);
  69. byte[] decryptedData = RSA.Decrypt(_encryptedData, false);
  70. return encoder.GetString(decryptedData);
  71. }
  72. }
  73. /// <summary>
  74. /// 解密
  75. /// </summary>
  76. /// <param name="encryptedData">待解密数据</param>
  77. /// <param name="keyfile">私钥文件</param>
  78. /// <param name="password">访问私钥文件密码</param>
  79. /// <returns></returns>
  80. public string X509CertDecrypt(string encryptedData, string keyfile, string password)
  81. {
  82. if (!File.Exists(keyfile))
  83. {
  84. throw new ArgumentNullException(keyfile, "解密证书未找到");
  85. }
  86. using (RSACryptoServiceProvider RSA = this.X509CertCreateDecryptRSA(keyfile, password))
  87. {
  88. Encoding encoder = Encoding.UTF8;
  89. byte[] _encryptedData = HexStringToBytes(encryptedData);
  90. byte[] decryptedData = RSA.Decrypt(_encryptedData, false);
  91. return encoder.GetString(decryptedData);
  92. }
  93. }

最后整理了一个简单的Demo:

![Image 1][]

Demo下载:RSACrypto.rar

参考资料:

http://dustin.iteye.com/blog/763931

http://baike.baidu.com/view/539299.htm

http://www.cnblogs.com/yjmyzz/archive/2008/08/20/1272098.html

转载于:https://www.cnblogs.com/chenyt/archive/2012/09/19/2691505.html

[Image 1]:

发表评论

表情:
评论列表 (有 0 条评论,454人围观)

还没有评论,来说两句吧...

相关阅读

    相关 RSA解密

    一:RSA加解密背景 RSA是目前使用最广泛的公钥密码体制之一。它是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦

    相关 RSA解密算法

    一、什么是RSA   RSA[公开密钥密码体制][Link 1]。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不