C# 如何从一个种子生成一个加密强随机字节序列?
如何从种子值生成加密强随机字节序列(以便可以再次从同一种子重新生成序列)?有没有好的CSPRNG算法可以用C#实现(最好有好的文档) 另外,or类将满足我的要求,因为C# 如何从一个种子生成一个加密强随机字节序列?,c#,random,cryptography,prng,C#,Random,Cryptography,Prng,如何从种子值生成加密强随机字节序列(以便可以再次从同一种子重新生成序列)?有没有好的CSPRNG算法可以用C#实现(最好有好的文档) 另外,or类将满足我的要求,因为Random在加密方面不强,RNGCryptoServiceProvider不允许您设置种子值。非常适合此工作,通常它用作密码哈希函数,但是,您可以从它请求任意多的字节,它将始终返回给定种子的相同字节序列(密码、salt和迭代计数的组合) 以下是MSDN中的示例,其中显示了Rfc2898DeriveBytes的两个实例,它们都返回相
Random
在加密方面不强,RNGCryptoServiceProvider
不允许您设置种子值。非常适合此工作,通常它用作密码哈希函数,但是,您可以从它请求任意多的字节,它将始终返回给定种子的相同字节序列(密码、salt和迭代计数的组合)
以下是MSDN中的示例,其中显示了Rfc2898DeriveBytes
的两个实例,它们都返回相同的序列(使用第一个序列对数据块进行对称加密,并使用第二个序列对其进行解密)
使用系统;
使用System.IO;
使用系统文本;
使用System.Security.Cryptography;
公共类RFC2898测试
{
//生成密码为pwd1和salt salt1的密钥k1。
//生成密码为pwd1和salt salt1的密钥k2。
//使用对称加密使用密钥k1加密数据1,创建edata1。
//使用对称解密使用密钥k2解密edata1,创建数据2。
//数据2应该等于数据1。
private const string usageText=“用法:RFC2898\n必须指定加密密码。\n”;
公共静态void Main(字符串[]passwordargs)
{
//如果未指定文件名,请写入用法文本。
if(passwordargs.Length==0)
{
控制台写入线(usageText);
}
其他的
{
字符串pwd1=passwordargs[0];
//创建一个字节数组来保存随机值。
字节[]salt1=新字节[8];
使用(RNGCryptoServiceProvider rngCsp=new RNGCryptoServiceProvider())
{
//用随机值填充数组。
rngCsp.GetBytes(salt1);
}
//数据1可以是字符串或文件内容。
string data1=“一些测试数据”;
//默认迭代计数为1000,因此这两个方法使用相同的迭代计数。
int=1000;
尝试
{
Rfc2898DeriveBytes k1=新的Rfc2898DeriveBytes(pwd1,salt1,myIterations);
Rfc2898DeriveBytes k2=新的Rfc2898DeriveBytes(pwd1,salt1);
//加密数据。
TripleDES encAlg=TripleDES.Create();
encAlg.Key=k1.GetBytes(16);
MemoryStream encryptionStream=新的MemoryStream();
CryptoStream encrypt=新加密流(encryptionStream,encAlg.CreateEncryptor(),CryptoStreamMode.Write);
byte[]utfD1=新系统.Text.UTF8Encoding(false).GetBytes(data1);
加密.Write(utfD1,0,utfD1.Length);
encrypt.FlushFinalBlock();
encrypt.Close();
字节[]edata1=encryptionStream.ToArray();
k1.Reset();
//尝试解密,从而显示它可能是往返的。
TripleDES贴花=TripleDES.Create();
贴花键=k2.GetBytes(16);
贴花IV=包装IV;
MemoryStream DecryptionStreamBack=新建MemoryStream();
CryptoStream DecryptoStream=新加密流(DecryptionStreamBack,贴花.createDecryptoctor(),CryptoStreamMode.Write);
解密.写入(edata1,0,edata1.Length);
decrypt.Flush();
decrypt.Close();
k2.Reset();
string data2=新的UTF8Encoding(false).GetString(DecryptionStreamBack.ToArray());
如果(!data1.Equals(data2))
{
WriteLine(“错误:两个值不相等。”);
}
其他的
{
WriteLine(“两个值相等”);
WriteLine(“k1迭代:{0}”,k1.IterationCount);
WriteLine(“k2迭代:{0}”,k2.IterationCount);
}
}
捕获(例外e)
{
Console.WriteLine(“错误:”,e);
}
}
}
}
假设它是用于测试的,为什么不使用只返回已知数字序列的特殊实现呢?(否则可重复序列的“加密强度”有多大?)@AlexeiLevenkov,因为我需要根据种子生成不同的序列。如果Random
类的加密能力很强,那么它就可以了。加密安全的随机生成器意味着数字无法预测。此外,数字(或字节)-生成器是。当迭代次数=1时,它非常慢,而当迭代次数为1000次时,它的速度非常慢。如果您在大量迭代的情况下从PBKDF2中消耗了超过20个字节,那么您可能做错了什么。
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
public class rfc2898test
{
// Generate a key k1 with password pwd1 and salt salt1.
// Generate a key k2 with password pwd1 and salt salt1.
// Encrypt data1 with key k1 using symmetric encryption, creating edata1.
// Decrypt edata1 with key k2 using symmetric decryption, creating data2.
// data2 should equal data1.
private const string usageText = "Usage: RFC2898 <password>\nYou must specify the password for encryption.\n";
public static void Main(string[] passwordargs)
{
//If no file name is specified, write usage text.
if (passwordargs.Length == 0)
{
Console.WriteLine(usageText);
}
else
{
string pwd1 = passwordargs[0];
// Create a byte array to hold the random value.
byte[] salt1 = new byte[8];
using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider())
{
// Fill the array with a random value.
rngCsp.GetBytes(salt1);
}
//data1 can be a string or contents of a file.
string data1 = "Some test data";
//The default iteration count is 1000 so the two methods use the same iteration count.
int myIterations = 1000;
try
{
Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pwd1, salt1, myIterations);
Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(pwd1, salt1);
// Encrypt the data.
TripleDES encAlg = TripleDES.Create();
encAlg.Key = k1.GetBytes(16);
MemoryStream encryptionStream = new MemoryStream();
CryptoStream encrypt = new CryptoStream(encryptionStream, encAlg.CreateEncryptor(), CryptoStreamMode.Write);
byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(data1);
encrypt.Write(utfD1, 0, utfD1.Length);
encrypt.FlushFinalBlock();
encrypt.Close();
byte[] edata1 = encryptionStream.ToArray();
k1.Reset();
// Try to decrypt, thus showing it can be round-tripped.
TripleDES decAlg = TripleDES.Create();
decAlg.Key = k2.GetBytes(16);
decAlg.IV = encAlg.IV;
MemoryStream decryptionStreamBacking = new MemoryStream();
CryptoStream decrypt = new CryptoStream(decryptionStreamBacking, decAlg.CreateDecryptor(), CryptoStreamMode.Write);
decrypt.Write(edata1, 0, edata1.Length);
decrypt.Flush();
decrypt.Close();
k2.Reset();
string data2 = new UTF8Encoding(false).GetString(decryptionStreamBacking.ToArray());
if (!data1.Equals(data2))
{
Console.WriteLine("Error: The two values are not equal.");
}
else
{
Console.WriteLine("The two values are equal.");
Console.WriteLine("k1 iterations: {0}", k1.IterationCount);
Console.WriteLine("k2 iterations: {0}", k2.IterationCount);
}
}
catch (Exception e)
{
Console.WriteLine("Error: ", e);
}
}
}
}