RSA .net

这两天在捣鼓 RSA 加密的问题.

WebService 一直使用的是明文传递账号密码.. 实在是受不了. 于是觉得还是加密一下.

 

由于一直没有使用过RSA,所以我提议用了RSA做。 然后就做了.

首先RSA是非对称加密.

会生成 密钥a 和 密钥b.

 

用a 加密 用b解密,反之亦然. 这样就解决了安全性问题.

至于RSA算法的原理。 可以去阮一峰的博客上看. 深入浅出。很是厉害.

 

.net 自己有RSA加密的库,使用起来也比较简单.

生成公钥和私钥.

//声明一个RSA算法的实例,由RSACryptoServiceProvider类型的构造函数指定了密钥长度为1024位
//实例化RSACryptoServiceProvider后,RSACryptoServiceProvider会自动生成密钥信息。
rsaProvider = new RSACryptoServiceProvider(1024);
//将RSA算法的公钥导出到字符串PublicKey中,参数为false表示不导出私钥
PublicKey = rsaProvider.ToXmlString(false);
//将RSA算法的私钥导出到字符串PrivateKey中,参数为true表示导出私钥
PrivateKey = rsaProvider.ToXmlString(true);

 

接下来就是加密和解密

 1  public static byte[] EncryptData(byte[] data)
 2  {
 3      RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
 4      //将公钥导入到RSA对象中,准备加密;
 5      //rsa.FromXmlString(PublicKey);
 6      rsa.FromXmlString(PrivateKey);
 7      //对数据data进行加密,并返回加密结果;
 8      //第二个参数用来选择Padding的格式
 9      return rsa.Encrypt(data, false);
10  }
11 
12  public static byte[] DecryptData(byte[] data)
13  {
14      RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
15      //将私钥导入RSA中,准备解密;
16      //rsa.FromXmlString(PrivateKey);
17      rsa.FromXmlString(PublicKey);
18      //对数据进行解密,并返回解密结果;
19      return rsa.Decrypt(data, false);
20  }

其实到这里。第一个需求就已经搞定了。

 

公钥发给发送者.

然后这边用私钥解密. 就OK了.

至于传递会将 byte[]  转成Base64.

 

其中遇到了一个问题。 

Base64在传递时, + 号变空格。 

我这里比较偷懒,replace即可.

 

由于是非对称解密,有时候验证也可以用RSA来做.

 

私钥加密公钥解密。

私钥只有我一个人有。 所以能确定只要你用公钥能解开就相当于一次验证.

可是在用 .net 自带测试的时候报错了

技术分享

说好的非对称呢.. 为什么会这样.

网上说是 .net 算法问题.

于是就反编译了一下源码看了下.

 

公钥

1 <?xml version="1.0"?>
2 <RSAKeyValue>
3     <Modulus>0Avy88U8M1rLqrO/Vk9eIbGUDLQZ1jPk5EvbA4IHTrp+5OnRzvwd8CV0YDroDLcw6J1P0Cw2gjjyIGuRqKw9ws/0vhDaNliJUsO/i6eTzcRVgBXHWtJ996dO6CgoCgIw/SOJCFv3oY9SzJXmMwbEjYeWKKOC8OX4uwxpGw30gqc=</Modulus>
4     <Exponent>AQAB</Exponent>
5 </RSAKeyValue>

 

私钥

 1 <?xml version="1.0"?>
 2 <RSAKeyValue>
 3     <Modulus>0Avy88U8M1rLqrO/Vk9eIbGUDLQZ1jPk5EvbA4IHTrp+5OnRzvwd8CV0YDroDLcw6J1P0Cw2gjjyIGuRqKw9ws/0vhDaNliJUsO/i6eTzcRVgBXHWtJ996dO6CgoCgIw/SOJCFv3oY9SzJXmMwbEjYeWKKOC8OX4uwxpGw30gqc=</Modulus>
 4     <Exponent>AQAB</Exponent>
 5     <P>6HD3+ubvGyvE3Ech+OO6/ZMjkkt82S06h3Dk6YfL1eXkHcakPf+U3oUutYx/NxvZyg/e9Mp+KZgmsflM1rVA0w==</P>
 6     <Q>5SIGvkG6KW9OOgkLZcdjEnXTFHSMiMzaJy3FJ3gyGuAiJLsa0CX0HRWulEUaV/u3OpeDQouIyXIjmIMHlQpyXQ==</Q>
 7     <DP>KKjaOAF9gfs+DGpE/wyXARRj/ItH45WNz3NoF5GxjlEQfkTpJg83M1WIvik9d55fkoEENz3Uo+IBotBBKK28EQ==</DP>
 8     <DQ>AFtLM2Say5G2x3RYJjJnPxIb3/5GcbgP5tu1YNhZC52pr/Dym7xTYvAzs1tgLR7hLCAsPiBFeDrLP2OE0YCQqQ==</DQ>
 9     <InverseQ>uYX674j70WN2r5f3+aj7chyijctpNuSv4JZF2zApKxF3yPw3fTTrOeePZoubtt6AydB5oKflkvdTol8Ml7ag2A==</InverseQ>
10     <D>INFht7ZrMqal7f2Atzq53JLIieB3GuUAvEqC9+CxCmg80BtaL05x4onl+7APHsJfArKd/naa+pvFBfwx8+uHqkSX6rkIlvqH4J+ZK8RQgDbuw9cxzlTzWQBlvMWmWZD90IfawGN4OsxCfYsAzNyl+wckZ0R1KUpa9oqAsSyxK/E=</D>
11 </RSAKeyValue>

 

以下是C#源码

首先

rsaProvider = new RSACryptoServiceProvider(1024);

 

 

是来源于密封类 RSACryptoServiceProvider 

[ComVisible(true)]
public sealed class RSACryptoServiceProvider : RSA, ICspAsymmetricAlgorithm
{
   [SecuritySafeCritical]
   public RSACryptoServiceProvider(int dwKeySize) : this(dwKeySize,   new CspParameters(0x18, null, null, s_UseMachineKeyStore), false)
   {

   }
}

 

 

生成公钥密钥 ToXmlString

1 //将RSA算法的公钥导出到字符串PublicKey中,参数为false表示不导出私钥
2 PublicKey = rsaProvider.ToXmlString(false);
3 //将RSA算法的私钥导出到字符串PrivateKey中,参数为true表示导出私钥
4 PrivateKey = rsaProvider.ToXmlString(true);
 1  public override string ToXmlString(bool includePrivateParameters)
 2         {
 3             RSAParameters parameters = this.ExportParameters(includePrivateParameters);
 4             StringBuilder builder = new StringBuilder();
 5             builder.Append("<RSAKeyValue>");
 6             builder.Append("<Modulus>" + Convert.ToBase64String(parameters.Modulus) + "</Modulus>");
 7             builder.Append("<Exponent>" + Convert.ToBase64String(parameters.Exponent) + "</Exponent>");
 8             if (includePrivateParameters)
 9             {
10                 builder.Append("<P>" + Convert.ToBase64String(parameters.P) + "</P>");
11                 builder.Append("<Q>" + Convert.ToBase64String(parameters.Q) + "</Q>");
12                 builder.Append("<DP>" + Convert.ToBase64String(parameters.DP) + "</DP>");
13                 builder.Append("<DQ>" + Convert.ToBase64String(parameters.DQ) + "</DQ>");
14                 builder.Append("<InverseQ>" + Convert.ToBase64String(parameters.InverseQ) + "</InverseQ>");
15                 builder.Append("<D>" + Convert.ToBase64String(parameters.D) + "</D>");
16             }
17             builder.Append("</RSAKeyValue>");
18             return builder.ToString();
19 }
 1 [SecuritySafeCritical]
 2 public override RSAParameters ExportParameters(bool includePrivateParameters)
 3 {
 4     this.GetKeyPair();
 5     if (includePrivateParameters && !CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
 6     {
 7         KeyContainerPermission permission = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
 8         KeyContainerPermissionAccessEntry accessEntry = new KeyContainerPermissionAccessEntry(this._parameters, KeyContainerPermissionFlags.Export);
 9         permission.AccessEntries.Add(accessEntry);
10         permission.Demand();
11     }
12     RSACspObject cspObject = new RSACspObject();
13     int blobType = includePrivateParameters ? 7 : 6;
14     Utils._ExportKey(this._safeKeyHandle, blobType, cspObject);
15     return RSAObjectToStruct(cspObject);
16 }
1 [MethodImpl(MethodImplOptions.InternalCall), SecurityCritical]
2 internal static extern void _ExportKey(SafeKeyHandle hKey, int blobType, object cspObject);

 

找到这里就卡住了。

具网上说。是由于.net 算法问题导致。

网上有很多自己学的RSA算法类,基本使用时没有问题。

可是当位数上去. .net 最长Int64. 超出只能使用 biginteger。

biginteger 以前在项目中使用过,性能实在是不敢恭维.

 

而且目测在客户端调用的时候也会出问题。

比如JAVA 默认应该是无填充模式。 .net 是随机填充。

到时候和JAVA的同事一起测试一下吧.

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。