加密大于 RSA 密钥(模数)大小的数据。将拆分的数据加密成块,似乎不起作用。有任何想法吗?
Posted
技术标签:
【中文标题】加密大于 RSA 密钥(模数)大小的数据。将拆分的数据加密成块,似乎不起作用。有任何想法吗?【英文标题】:Encrypting data larger than the RSA key (modulus) size. Encryption of splitted data into chunks, seems not to be working. Any ideas? 【发布时间】:2017-11-04 09:52:49 【问题描述】:请先阅读:
我知道 RSA 不是为数据块加密而设计的。但这仍然是可能的。 我知道使用 RSA 加密数据块时的安全性和性能损失。 我不允许使用混合加密。因此,在我的情况下,以下步骤是不可接受的:为对称算法生成随机密钥 使用对称算法和随机密钥加密数据 使用您的公钥加密随机密钥,并将其以加密形式存储在数据的旁边(或之前)。
但我必须通过各种方式完成指定的任务。 感谢您的理解。
我对示例进行了极大的抽象和简化,以明确我正在努力解决的问题。
string data = "message 700-1300 letters long";
byte[] bytes = data.ToUtf8EncodedByteArray();
// I'm splitting utf8 encoded bytes into chunks of 32 bytes each.
IEnumerable<IEnumerable<byte>> batches = bytes.ChunkBy(32);
LinkedList<byte[]> encryptedChunks = new LinkedList<byte[]>();
LinkedList<byte[]> decryptedChunks = new LinkedList<byte[]>();
using (var rsa = new RSACryptoServiceProvider(2048))
rsa.PersistKeyInCsp = false;
_publicKey = rsa.ExportParameters(false);
_privateKey = rsa.ExportParameters(true);
rsa.ImportParameters(_publicKey);
byte[] encryptedBatch = null;
foreach (IEnumerable<byte> batch in batches)
encryptedBatch = rsa.Encrypt(batch.ToArray(), true);
encryptedChunks.AddLast(encryptedBatch);
// Then encryptedChunks.ToArray() will be send over the network
// When encrypted bytes are received at another endpoint, they have to be decrypted.
rsa.ImportParameters(_privateKey);
byte[] decryptedBatch = null;
foreach (byte[] chunk in encryptedChunks)
decryptedBatch = rsa.Decrypt(chunk, true);
decryptedChunks.AddLast(chunk);
// After decryption of each encrypted chunk of data, I project it back into an array of bytes.
byte[] decrypted = decryptedChunks.SelectMany(chunk => chunk).ToArray();
// When trying to display decoded bytes as a string (as it was initially), instead of original message I get hieroglyphs.
Console.Out.WriteLine($"Decrypted message: decrypted.ToUtf8String()");
如果需要,这里是扩展方法(在我的代码中使用):
public static IEnumerable<IEnumerable<TElement>> ChunkBy<TElement>(
this IEnumerable<TElement> source, int chunkSize)
return source
.Select((x, i) => new Index = i, Value = x )
.GroupBy(x => x.Index / chunkSize)
.Select(x => x.Select(v => v.Value).ToArray())
.ToArray();
public static byte[] ToUtf8EncodedByteArray(this string source)
return Encoding.UTF8.GetBytes(source.ToCharArray());
public static string ToUtf8String(this byte[] sourceBytes)
return Encoding.UTF8.GetString(sourceBytes);
附:在加密数据(文本)之前,我也尝试过将其编码为ASCII,而不是 UTF8。这也没有帮助。
有什么想法吗?(除了切换到使用对称密钥加密。如上所述,我不允许这样做。)
【问题讨论】:
【参考方案1】:我对您的代码稍作修改(查找更改的 cmets),它可以工作:
public static IEnumerable<IEnumerable<TElement>> ChunkBy<TElement>(this IEnumerable<TElement> source, int chunkSize)
return source
.Select((x, i) => new Index = i, Value = x )
.GroupBy(x => x.Index / chunkSize)
.Select(x => x.Select(v => v.Value).ToArray())
.ToArray();
public static byte[] ToUtf8EncodedByteArray(this string source)
// Changed: instead of source.ToCharArray() use source directly
return Encoding.UTF8.GetBytes(source);
public static string ToUtf8String(this byte[] sourceBytes)
return Encoding.UTF8.GetString(sourceBytes);
[STAThread]
public static void Main()
// Changed: Generate some sample data...
string data = string.Join(string.Empty, Enumerable.Repeat<string>("abcdefghijklmnopqrstuvwxyz0123456789<>!?", 100));
byte[] bytes = data.ToUtf8EncodedByteArray();
// I'm splitting utf8 encoded bytes into chunks of 32 bytes each.
IEnumerable<IEnumerable<byte>> batches = bytes.ChunkBy(32);
LinkedList<byte[]> encryptedChunks = new LinkedList<byte[]>();
LinkedList<byte[]> decryptedChunks = new LinkedList<byte[]>();
using (var rsa = new RSACryptoServiceProvider(2048))
rsa.PersistKeyInCsp = false;
var _publicKey = rsa.ExportParameters(false);
var _privateKey = rsa.ExportParameters(true);
rsa.ImportParameters(_publicKey);
byte[] encryptedBatch = null;
foreach (IEnumerable<byte> batch in batches)
encryptedBatch = rsa.Encrypt(batch.ToArray(), true);
encryptedChunks.AddLast(encryptedBatch);
rsa.ImportParameters(_privateKey);
byte[] decryptedBatch = null;
foreach (byte[] chunk in encryptedChunks)
decryptedBatch = rsa.Decrypt(chunk, true);
// Changed (critical): instead of chunk (the encrypted data) use the decrypted data
decryptedChunks.AddLast(decryptedBatch);
// After decryption of each encrypted chunk of data, I project it back into an array of bytes.
byte[] decrypted = decryptedChunks.SelectMany(chunk => chunk).ToArray();
var data2 = decrypted.ToUtf8String();
// Changed: Verify that input and output are the same
var equals = data.Equals(data2);
【讨论】:
非常感谢!注意力不集中是问题的根源。我很高兴它正在工作。以上是关于加密大于 RSA 密钥(模数)大小的数据。将拆分的数据加密成块,似乎不起作用。有任何想法吗?的主要内容,如果未能解决你的问题,请参考以下文章