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

加密|解决|数据

前一阵给公安局做项目,用到了公钥加密技术及对称密钥加密技术。信息通过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;
   }
}

 

时间: 2024-10-07 03:12:06

RSA加密超出117字节的数据出错的解决方案的相关文章

c#如何删除文件中多个字节的数据

问题描述 我有一个数据文件,在c#中怎么删除这个文件中10个字节的数据啊,急! 解决方案 解决方案二:正则表达式的replace解决方案三:只能把文件读出来...然后再写回去.

pcap包用wireshark打开为什么丢了前四个字节的数据导致wireshark解析出错

问题描述 pcap包用wireshark打开为什么丢了前四个字节的数据导致wireshark解析出错 导致后面的数据也读不到,数据包被截断,请问这是怎么回事,用UE打开查看之后没有错啊?如图: 解决方案 已解决,都是由于数据包写入时,pcap文件格式掌握错误,但是根据结构体以及相关数据没有办法进行查到,所以后来放弃自己造文件结构,而改用了pcap库自己的函数完成pcap文件的生成.详情参考: http://ask.csdn.net/questions/199693 解决方案二: 应该是编码格式的

Android使用RSA加密和解密的示例代码

一.公钥加密和私钥解密 /**RSA算法*/ public static final String RSA = "RSA"; /**加密方式,android的*/ // public static final String TRANSFORMATION = "RSA/None/NoPadding"; /**加密方式,标准jdk的*/ public static final String TRANSFORMATION = "RSA/None/PKCS1Pad

Android数据加密之Rsa加密的简单实现_Android

最近无意中和同事交流数据安全传输的问题,想起自己曾经使用过的Rsa非对称加密算法,闲下来总结一下. 什么是Rsa加密? RSA算法是最流行的公钥密码算法,使用长度可以变化的密钥.RSA是第一个既能用于数据加密也能用于数字签名的算法. RSA算法原理如下: 1.随机选择两个大质数p和q,p不等于q,计算N=pq: 2.选择一个大于1小于N的自然数e,e必须与(p-1)(q-1)互素. 3.用公式计算出d:d×e = 1 (mod (p-1)(q-1)) . 4.销毁p和q. 最终得到的N和e就是"

Android数据加密之Rsa加密

前言: 最近无意中和同事交流数据安全传输的问题,想起自己曾经使用过的Rsa非对称加密算法,闲下来总结一下. 其他几种加密方式: •Android数据加密之Rsa加密  •Android数据加密之Aes加密  •Android数据加密之Des加密  •Android数据加密之MD5加密  •Android数据加密之Base64编码算法  •Android数据加密之SHA安全散列算法 什么是Rsa加密? RSA算法是最流行的公钥密码算法,使用长度可以变化的密钥.RSA是第一个既能用于数据加密也能用于

php实现RSA加密类实例

 这篇文章主要介绍了php实现RSA加密类,实例分析了php自定义RSA类实现加密与解密的技巧,非常具有实用价值,需要的朋友可以参考下     本文实例讲述了php实现RSA加密类.分享给大家供大家参考.具体分析如下: 通过openssl实现的签名.验签.非对称加解密,需要配合x.509证书(如crt和pem)文件使用. 由于各种原因,该类并不十分完善,欢迎各种测试! ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

C# Java间进行RSA加密解密交互

原文:C# Java间进行RSA加密解密交互 这里,讲一下RSA算法加解密在C#和Java之间交互的问题,这两天纠结了很久,也看了很多其他人写的文章,颇受裨益,但没能解决我的实际问题,终于,还是被我捣鼓出来了. 首先,介绍一下写这代码的目的:完成webService验证问题,服务器端采用C#开发,客户端采用Java开发.服务器端给客户端提供公钥,已进行数据加密,客户端加密后提数据提交给服务器,服务器用私钥对数据解密,进行验证.  这里遇到的主要问题是C# RSACryptoServiceProv

php实现RSA加密类实例_php技巧

本文实例讲述了php实现RSA加密类.分享给大家供大家参考.具体分析如下: 通过openssl实现的签名.验签.非对称加解密,需要配合x.509证书(如crt和pem)文件使用. 由于各种原因,该类并不十分完善,欢迎各种测试! <?php /** * RSA算法类 * 签名及密文编码:base64字符串/十六进制字符串/二进制字符串流 * 填充方式: PKCS1Padding(加解密)/NOPadding(解密) * * Notice:Only accepts a single block. B

java实现RSA加密与SHA签名的例子

看到这篇文章的同学可幸福了,当时在做RSA加密与签名的时候网上的资料简直不要太老,做完后实在是忍受不下去了,这篇文章我会详细讲解iOS如何实现RSA加密与签名,并且与Java完全同步,这是我的第二篇博客,若有什么不足之处还请大家指教. 什么是RSA? 答:RSA是一种非对称加密算法,常用来对传输数据进行加密,配合上数字摘要算法,也可以进行文字签名. RSA加密中padding? 答:padding即填充方式,由于RSA加密算法中要加密的明文是要比模数小的,padding就是通过一些填充方式来限制