AES解密仅产生部分答案C#
我正在努力学习网络安全,这是我做的第一件事。我正在使用这个MSDN文档(),它部分有效。我假设它加密得很好,就像解密一样,一些原始数据在那里,但一些丢失了。正在加密的数据是一个已格式化为JSON字符串的类(我认为这与此无关,因为它仍然是一个正在加密的字符串)。 但一旦它被加密和解密,结果是这样的: 我已经运行了这段代码并比较了5次以上的结果,结果总是:开始是错误的,用户名部分正确,密码总是正确,loginkey部分正确。因此,错误是反复出现的,并且总是在同一点上 您应该知道的信息是,数据经过加密并保存到.txt文件中。程序将再次运行,并尝试对其进行解密。Salt和密码保存在另一个文件中,并在解密过程中读取和使用 关于stackoverflow也有一个类似的问题,但答案只是说使用Rijndael(所以不是真正的答案),这段代码是供我学习的,我想要的答案不是4行 代码(但基本上与MSDN文档相同): 加密:AES解密仅产生部分答案C#,c#,security,encryption,aes,C#,Security,Encryption,Aes,我正在努力学习网络安全,这是我做的第一件事。我正在使用这个MSDN文档(),它部分有效。我假设它加密得很好,就像解密一样,一些原始数据在那里,但一些丢失了。正在加密的数据是一个已格式化为JSON字符串的类(我认为这与此无关,因为它仍然是一个正在加密的字符串)。 但一旦它被加密和解密,结果是这样的: 我已经运行了这段代码并比较了5次以上的结果,结果总是:开始是错误的,用户名部分正确,密码总是正确,loginkey部分正确。因此,错误是反复出现的,并且总是在同一点上 您应该知道的信息是,数据经过
static void EncryptFile()
{
string pwd1 = SteamID;//steamID is referring to account ID on Valve Steam
using (RNGCryptoServiceProvider rngCsp = new
RNGCryptoServiceProvider())
{
rngCsp.GetBytes(salt1); //salt1 is a programme variable and will get saved to a file
}
SecureData File = new SecureData(_UserName,_PassWord,_LoginKey);
string JsonFile = JsonConvert.SerializeObject(File); //puts the class into Json format
int myIterations = 1000; //not needed
try
{
Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pwd1, salt1,
myIterations);
Aes encAlg = Aes.Create(); // This might be the issue as AES will be different when you decrypt
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(
JsonFile); //encrypt Data
encrypt.Write(utfD1, 0, utfD1.Length);
encrypt.FlushFinalBlock();
encrypt.Close();
byte[] edata1 = encryptionStream.ToArray();
k1.Reset();
System.IO.File.WriteAllBytes(SecureFile, edata1); //writes encrypted data to file
}
catch (Exception e)
{
Console.WriteLine("Error: ", e);
}
}
解密:
static void DecryptFile()
{
string pwd1 = SteamID;
byte[] edata1;
try
{
edata1 = System.IO.File.ReadAllBytes(SecureFile); //reads the file with encrypted data on it
Aes encAlg = Aes.Create(); //I think this is the problem as the keyvalue changes when you create a new programme
Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(pwd1, salt1); //inputs from last time carry over
Aes decAlg = Aes.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());//decrypted data
SecureData items = JsonConvert.DeserializeObject<SecureData>(data2); //reformat it out of JSon(Crashes as format isn't accepted)
_UserName = items.S_UserName;
_PassWord = items.S_Password;
_LoginKey = items.S_LoginKey;
}
catch (Exception e)
{
Console.WriteLine("Error: ", e);
NewLogin();
}
}
该问题是由用于加密和解密的不同IVs引起的。要成功解密,必须使用加密中的IV 为什么应用不同的IVs?创建
AES
实例时,将隐式生成随机IV。因此,两个不同的AES
实例意味着两个不同的IVs。在发布的代码中,不同的AES
实例用于加密和解密。尽管解密中使用的引用encAlg
与加密中使用的引用具有相同的名称,但引用的实例是不同的实例(即解密期间新创建的实例)。这在Microsoft示例中是不同的。在这里,加密的IV用于解密:detag.IV=encAlg.IV
,其中encAlg
是执行加密的AES
实例
解决方案是将加密中的IV存储在文件中,以便在解密中使用。IV不是秘密的,通常放在密文之前:
加密文件中的必要更改
:
...
byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(JsonFile);
encryptionStream.Write(encAlg.IV, 0, encAlg.IV.Length); // Write the IV
encryptionStream.Flush();
encrypt.Write(utfD1, 0, utfD1.Length);
...
...
edata1 = System.IO.File.ReadAllBytes(SecureFile);
byte[] iv = new byte[16]; // Separate IV and ciphertext
byte[] ciphertext = new byte[edata1.Length - iv.Length];
Array.Copy(edata1, 0, iv, 0, iv.Length);
Array.Copy(edata1, iv.Length, ciphertext, 0, ciphertext.Length);
...
Aes encAlg = Aes.Create(); // Remove this line
...
decAlg.IV = iv; // Use the separated IV
...
decrypt.Write(ciphertext, 0, ciphertext.Length); // Use the separated ciphertext
解密文件中的必要更改
:
...
byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(JsonFile);
encryptionStream.Write(encAlg.IV, 0, encAlg.IV.Length); // Write the IV
encryptionStream.Flush();
encrypt.Write(utfD1, 0, utfD1.Length);
...
...
edata1 = System.IO.File.ReadAllBytes(SecureFile);
byte[] iv = new byte[16]; // Separate IV and ciphertext
byte[] ciphertext = new byte[edata1.Length - iv.Length];
Array.Copy(edata1, 0, iv, 0, iv.Length);
Array.Copy(edata1, iv.Length, ciphertext, 0, ciphertext.Length);
...
Aes encAlg = Aes.Create(); // Remove this line
...
decAlg.IV = iv; // Use the separated IV
...
decrypt.Write(ciphertext, 0, ciphertext.Length); // Use the separated ciphertext
几句话:
-
对于每一个加密,都应该生成一个新的随机盐,并与类似于IV的密文串接。在解密期间,盐可以被确定为类似于IV。另外考虑。
- 迭代计数会减慢密钥的推导速度,这会使通过重复尝试进行攻击变得更加困难。因此,该值应尽可能大。另外考虑。
- 身份验证数据(即密码)不是加密的,而是散列的