RSA加密超出117字节的数据出错的解决方案(zt)

文章来源:http://www.cnblogs.com/zhenyulu

前一阵给公安局做项目,用到了公钥加密技术及对称密钥加密技术。信息通过3DES进行加密,而密钥通过RSA公钥体系传送。客户端使用CPU卡eKey进行解密。但是在系统编写过程中发现,.net中的RSA加密算法为了提高安全性,在待加密数据前要添加一些随机数,因此,使用.NET中的RSA加密算法一次最多加密117字节数据(多于117字节需要拆分成多段分别加密再连接起来),经过加密后得到一个长度为128字节的加密数据。但这对于需要进行收发双方身份确认的公钥体系来说会带来不少麻烦。在我的系统中,我需要通过以下步骤实现对用户会话密钥的网上加密传递:

加密过程:
1、对会话密钥添加随机数,补充到128位,
2、使用CA私钥解密,结果为128位数据,
3、对数据使用用户公钥加密,得到128位数据,通过网络传送。


解密过程:
1、使用用户私钥解密网上传送的128位数据;
2、将结果使用CA公钥加密;
3、去掉用来混淆的随机数,提取出会话密钥

但.net中的RSA加密最多只能对117字节数据进行操作,导致128位数据不得不分两部分进行处理,于是加密数据不断膨胀。为了解决这个问题,并使得RSA加密、解密过程与eKey上的过程相一致,我只好编写自己的RSA加密算法。

经过查找了大量资料后,我决定利用现成的 BigInteger 类。可以参考http://www.codeproject.com/csharp/biginteger.asp 得到更多的信息。利用 BigInteger,我添加了两个方法RSAEncrypt和RSADecrypt,实现RSA加密解密。这样就再也不用受117字节的限制了。

下面给出了两段程序,程序一是使用.Net自带RSA加密算法实现加密解密,不过 TextLength 属性一旦超过 117,系统将无法加密; 程序二是经过改造的系统,可以对128位的数据进行加密,没有了117的限制。程序二省略了BigInteger类,需要的话可以从http://www.codeproject.com/csharp/biginteger.asp下载,不要忘了注释其中的Main方法,否则在编译时会有一个编译错误,说有两个入口点(当然也可以在项目属性中指定一个入口点)。

程序一:

using  System;
using
 System.Security.Cryptography;
using
 System.Text;

class
 OldRSA
{
   
static void
 Main()
   
{
      
int TextLength = 117
;
      
byte
[] encryptedData;
      
byte
[] decryptedData;
      
string Key1 = "<RSAKeyValue><Modulus>4n6EJsx4qNFpp6h+wcPdJz8sSMMRJEVJaBQEGsOOBHKNePo/v3M94Nf89+zL5lLH7/LuRgcUfnizVIETH/z9+H/yDuM0F3fjImN3UtK1TK0ioFf0cVC9lnErbEoEjmkeQIVUJUC4c+BmqtTN6UrhFCY3R3zGp3feeGqORLjeKVc=</Modulus><Exponent>AQAB</Exponent><P>7w2qsVRBn168Ehc4V/fiPML+7WUkORRIJ9I8i21Fs5GlvYrja2CzBzPLKrAHumLOCLgd/qKj0iApF17471nfKw==</P><Q>8oztAlInRK1VDuVLHnPPcNQsehbP9IF5p+kwRu07sFGwAHnyeWuRG0EpebvbGOE/1KzpKqb/WU8vSN4OeauohQ==</Q><DP>DIh+5oUwW5av7ZLiFVqdtenTS8b9uzBhCBVxry2vddaxBdr+SWbse/gvMrG/9fmwK6zbhbopNJ8TCHKmQoZHuQ==</DP><DQ>6g96q/GxeUG3Qk+dBP8HIL9vSEX5Wd8UEigicV9/aS/7IwqLJgbama1xI8tXrBO6MDbIL2PGKF4UqEG5QEqZrQ==</DQ><InverseQ>nyx28u1fREiIgXgx2S5+PXbB8wq0xVxnE2G2Mt0vq9xQDHbaXEFpfznjNaga8AhVluNahqG5uRGRY3OgQONO4g==</InverseQ><D>PVKj1R1nTc3lHU+xgiTVq9qe0tR9v6RCy7sfoV9xBCM/ypF20Q8Sod3Y0Ad87U9ccssDWFJyagukAi0wUGjfGfalF8/4PFwqzrGBLsN96klmKLMy7C6oihlriW+MyxmvagGsp3/r4sE6wGk5ISchjKIKyv/PyWoobDRe6orDzIE=</D></RSAKeyValue>"
;

      
try

      
{
         RSACryptoServiceProvider RSA 
= new
 RSACryptoServiceProvider();
         RSA.FromXmlString(Key1);

         
byte[] dataToEncrypt =
 GenerateBytes(TextLength);
         Console.WriteLine(
"Original buff:  " + Convert.ToBase64String(dataToEncrypt) + " "
);

         encryptedData 
= RSA.Encrypt(dataToEncrypt, false
);
         Console.WriteLine(
"Encrypted buff:  " + Convert.ToBase64String(encryptedData) + " "
);

         decryptedData 
= RSA.Decrypt(encryptedData,false
);
         Console.WriteLine(
"Decrypted buff:  " + Convert.ToBase64String(decryptedData) + " "
);
      }

      
catch
      
{
         Console.WriteLine(
"Encryption failed."
);
      }

   }


   
//***********************************************************************
   
//
 随机生成一指定长度的字节数组
   
//***********************************************************************

   public static byte[] GenerateBytes(int byteLength)
   
{
      
byte[] buff = new
 Byte[byteLength];
      RNGCryptoServiceProvider rng 
= new
 RNGCryptoServiceProvider();

      
// 该数组已使用密码增强的随机字节进行填充

      rng.GetBytes(buff);
      
return
 buff;
   }

}

程序二:

using  System;
using
 System.Security.Cryptography;
using
 System.Text;

class
 NewRSA
{
   
public static void
 Main()
   
{
      
int TextLength = 128
;
      
byte
[] encryptedData;
      
byte
[] decryptedData;
      
string Key1 = "<RSAKeyValue><Modulus>4n6EJsx4qNFpp6h+wcPdJz8sSMMRJEVJaBQEGsOOBHKNePo/v3M94Nf89+zL5lLH7/LuRgcUfnizVIETH/z9+H/yDuM0F3fjImN3UtK1TK0ioFf0cVC9lnErbEoEjmkeQIVUJUC4c+BmqtTN6UrhFCY3R3zGp3feeGqORLjeKVc=</Modulus><Exponent>AQAB</Exponent><P>7w2qsVRBn168Ehc4V/fiPML+7WUkORRIJ9I8i21Fs5GlvYrja2CzBzPLKrAHumLOCLgd/qKj0iApF17471nfKw==</P><Q>8oztAlInRK1VDuVLHnPPcNQsehbP9IF5p+kwRu07sFGwAHnyeWuRG0EpebvbGOE/1KzpKqb/WU8vSN4OeauohQ==</Q><DP>DIh+5oUwW5av7ZLiFVqdtenTS8b9uzBhCBVxry2vddaxBdr+SWbse/gvMrG/9fmwK6zbhbopNJ8TCHKmQoZHuQ==</DP><DQ>6g96q/GxeUG3Qk+dBP8HIL9vSEX5Wd8UEigicV9/aS/7IwqLJgbama1xI8tXrBO6MDbIL2PGKF4UqEG5QEqZrQ==</DQ><InverseQ>nyx28u1fREiIgXgx2S5+PXbB8wq0xVxnE2G2Mt0vq9xQDHbaXEFpfznjNaga8AhVluNahqG5uRGRY3OgQONO4g==</InverseQ><D>PVKj1R1nTc3lHU+xgiTVq9qe0tR9v6RCy7sfoV9xBCM/ypF20Q8Sod3Y0Ad87U9ccssDWFJyagukAi0wUGjfGfalF8/4PFwqzrGBLsN96klmKLMy7C6oihlriW+MyxmvagGsp3/r4sE6wGk5ISchjKIKyv/PyWoobDRe6orDzIE=</D></RSAKeyValue>"
;

      
try
      
{
         RSACryptoServiceProvider RSA 
= new
 RSACryptoServiceProvider();
         RSA.FromXmlString(Key1);
         RSAParameters RSAKeyInfo 
= RSA.ExportParameters(true
);

         
byte[] dataToEncrypt =
 GenerateBytes(TextLength);
         Console.WriteLine(
"Original buff:  " + Convert.ToBase64String(dataToEncrypt) + " "
);

         encryptedData 
=
 RSAEncrypt(dataToEncrypt, RSAKeyInfo.Exponent, RSAKeyInfo.Modulus);
         Console.WriteLine(
"Encrypted buff:  " + Convert.ToBase64String(encryptedData) + " "
);

         decryptedData 
=
 RSADecrypt(encryptedData, RSAKeyInfo.D, RSAKeyInfo.Modulus);
         Console.WriteLine(
"Decrypted buff:  " + Convert.ToBase64String(decryptedData) + " "
);
      }

      
catch
      
{
         Console.WriteLine(
"Encryption failed."
);
      }

   }


   
//***********************************************************************
   
//
 RSA Encrypt
   
//***********************************************************************

   static public byte[] RSAEncrypt(byte[] dataToEncrypt, byte[] Exponent, byte[] Modulus)
   
{
      BigInteger original 
= new
 BigInteger(dataToEncrypt);
      BigInteger e 
= new
 BigInteger(Exponent);
      BigInteger n 
= new
 BigInteger(Modulus);

      BigInteger encrypted 
=
 original.modPow(e,n);
      
return
 HexStringToByte(encrypted.ToHexString());
   }


   
//***********************************************************************
   
//
 RSA Decrypt
   
//***********************************************************************

   static public byte[] RSADecrypt(byte[] encryptedData, byte[] D, byte[] Modulus)
   
{
      BigInteger encrypted 
= new
 BigInteger(encryptedData);
      BigInteger d 
= new
 BigInteger(D);
      BigInteger n 
= new
 BigInteger(Modulus);

      BigInteger decrypted 
=
 encrypted.modPow(d,n);
      
return
 HexStringToByte(decrypted.ToHexString());
   }


   
//***********************************************************************
   
//
 将 HexString 转换为 byte[] 数组
   
//***********************************************************************

   static public byte[] HexStringToByte(string hexString)
   
{
      
byte[] byteResult = new byte[hexString.Length/2
];

      
for(int i = 0; i < hexString.Length/2; i++

         byteResult[i] 
= Convert.ToByte(hexString.Substring(i*2,2),16
);

      
return
 byteResult;
   }


   
//***********************************************************************
   
//
 随机生成一指定长度的字节数组
   
//***********************************************************************

   public static byte[] GenerateBytes(int byteLength)
   
{
      
byte[] buff = new
 Byte[byteLength];
      RNGCryptoServiceProvider rng 
= new
 RNGCryptoServiceProvider();

      
// 该数组已使用密码增强的随机字节进行填充

      rng.GetBytes(buff);
      
return
 buff;
   }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值