请先阅读此内容:
- 为对称算法生成随机密钥
- 使用对称算法和随机密钥
加密数据- 使用您的公钥加密随机密钥,并在数据的下一个(或之前)以加密形式存储。
醇>
但我必须通过各种方式完成给定的任务 。 感谢您的理解 。
我非常抽象和简化了这个例子,以便清楚地说明我正在努力解决的问题。
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);
}
P.S。我还尝试将数据(文本),编码加密到 ASCII , UTF8 。这也无济于事。
任何想法?(除了使用对称密钥切换到加密。如上所述,我不允许这样做。)
答案 0 :(得分:1)
我稍微修改了(查找更改后的注释)你的代码,它可以工作:
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);
}