C# 4.0 填充无效,无法从解密值中删除
你好,我想加密和解密文本。我的加密代码工作正常,与我想要的值匹配。但当我想要解密时,这是一个错误C# 4.0 填充无效,无法从解密值中删除,c#-4.0,encryption,cryptography,C# 4.0,Encryption,Cryptography,你好,我想加密和解密文本。我的加密代码工作正常,与我想要的值匹配。但当我想要解密时,这是一个错误填充无效,无法删除。在下面的代码中,我首先给出加密和解密这两个代码。我还必须修复这个错误,但不能修复它 string getHashKey1 = EncryptText("10002:1486703720424", "hpIw4SgN)TxJdoQj=GKo)p83$uHePgoF"); 结果=1ltQFLRGNif73uCNzi0YEvBqLKiRgx6fWsk5e/GcTQc= string
填充无效,无法删除。在下面的代码中,我首先给出加密和解密这两个代码。我还必须修复这个错误,但不能修复它
string getHashKey1 = EncryptText("10002:1486703720424", "hpIw4SgN)TxJdoQj=GKo)p83$uHePgoF");
结果=1ltQFLRGNif73uCNzi0YEvBqLKiRgx6fWsk5e/GcTQc=
string reverseKey = DecryptText('1ltQFLRGNif73uCNzi0YEvBqLKiRgx6fWsk5e/GcTQc=', "hpIw4SgN)TxJdoQj=GKo)p83$uHePgoF");
当我加入AES时,解密AES.Padding=PaddingMode.Zeros;我得到了低于预期的结果。
结果:-����Y�7.�T���Ij���,���� Z��$�代码>
public string EncryptText(string input, string password)
{
string result = "";
try
{
// Get the bytes of the string
byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(input);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);
result = Convert.ToBase64String(bytesEncrypted);
return result;
}
catch (Exception ex)
{
}
return result;
}
public byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
try
{
using (MemoryStream ms = new MemoryStream())
{
using (Aes aes = Aes.Create())
{
aes.Key = passwordBytes;
aes.Mode = CipherMode.ECB;
// "zero" IV
aes.IV = new byte[16];
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
}
catch (Exception ex)
{
}
return encryptedBytes;
}
上面的代码对于加密来说运行良好。
下面的代码出现错误
填充无效,无法删除
public string DecryptText(string input, string password)
{
// Get the bytes of the string
byte[] bytesToBeDecrypted = Convert.FromBase64String(input);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesDecrypted = AES_Decrypt(bytesToBeDecrypted, passwordBytes);
string result = Encoding.UTF8.GetString(bytesDecrypted);
return result;
}
public byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
using (MemoryStream ms = new MemoryStream())
{
using (Aes aes = Aes.Create())
{
aes.Key = passwordBytes;
aes.Mode = CipherMode.ECB;
aes.IV = new byte[16];
using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close(); // here i am getting error
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
解密时正在对密码进行哈希运算
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
但不是在加密时。这意味着您正在使用不同的密码解密时您正在对密码进行哈希运算
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
但不是在加密时。这意味着您正在使用不同的密码您有两个问题:
1) (佩德罗夫已经指出):在加密中使用UTF8.GetBytes
,而在解密中使用SHA256(UTF8.GetBytes())
您不应该使用这两种方法中的任何一种,而是应该使用正确的基于密码的密钥派生函数,例如PBKDF2。在.NET中,PBKDF2可通过Rfc2898DeriveBytes
类获得
byte[] salt = 8 or more bytes that you always pass in as the same.
// (salt could be fixed for your application,
// but if you have users it should be unique per user and stored along with the output value)
int iterations = 100000;
// Or bigger. If you were making a user management system you
// should write this number down, too, so you can increase it over time;
// it should be whatever number makes it take 100ms or more on the fastest relevant computer)
Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations);
passwordBytes = pbkdf2.GetBytes(16); // 16 = AES128, 24 = AES192, 32 = AES256.
2) 在加密中使用Base64编码,但在解密中使用UTF8.GetBytes
奖金问题:
3) 您正在使用电子码本(ECB)链接。建议在ECB上使用密码块链接(CBC)
要正确使用CBC,请在encrypt中生成一个随机初始化向量(IV)(当您创建一个新的Aes
对象时,会自动生成该向量,或者如果您重新使用该对象,可以在encrypt中调用GenerateIV()
)。然后,您可以将IV(对于AES,它将始终是16字节)前置到密文。在decrypt中,您可以a)切掉前16个字节并将其指定为IV(然后解密其余数据),或者b)解密整个blob并忽略解密输出的前16个字节。您有两个问题:
1) (佩德罗夫已经指出):在加密中使用UTF8.GetBytes
,而在解密中使用SHA256(UTF8.GetBytes())
您不应该使用这两种方法中的任何一种,而是应该使用正确的基于密码的密钥派生函数,例如PBKDF2。在.NET中,PBKDF2可通过Rfc2898DeriveBytes
类获得
byte[] salt = 8 or more bytes that you always pass in as the same.
// (salt could be fixed for your application,
// but if you have users it should be unique per user and stored along with the output value)
int iterations = 100000;
// Or bigger. If you were making a user management system you
// should write this number down, too, so you can increase it over time;
// it should be whatever number makes it take 100ms or more on the fastest relevant computer)
Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations);
passwordBytes = pbkdf2.GetBytes(16); // 16 = AES128, 24 = AES192, 32 = AES256.
2) 在加密中使用Base64编码,但在解密中使用UTF8.GetBytes
奖金问题:
3) 您正在使用电子码本(ECB)链接。建议在ECB上使用密码块链接(CBC)
要正确使用CBC,请在encrypt中生成一个随机初始化向量(IV)(当您创建一个新的Aes
对象时,会自动生成该向量,或者如果您重新使用该对象,可以在encrypt中调用GenerateIV()
)。然后,您可以将IV(对于AES,它将始终是16字节)前置到密文。在decrypt中,您可以a)切掉前16个字节并将其指定为IV(然后解密其余的数据),或者b)解密整个blob并忽略解密输出的前16个字节。解密passwordBytes=SHA256.Create().ComputeHash(passwordBytes)时,您正在对密码进行哈希运算代码>,但不是在encrypt@pedrofb我需要做什么当我Decrypt@pedrofb谢谢,我删除了那条线,现在它工作了。谢天谢地,仅仅使用散列函数是不够的,仅仅添加一个salt对提高安全性几乎没有什么作用。取而代之的是,在HMAC上随机添加盐,持续约100毫秒,并将盐与散列一起保存。使用诸如PBKDF2
、password\u hash
、Bcrypt
等函数和类似函数。关键是让攻击者花费大量时间用暴力寻找密码。永远不要使用。它是确定性的,因此在语义上不安全。您至少应该使用随机模式,如或。最好是对密文进行身份验证,这样就不可能进行类似的攻击。这可以通过身份验证模式(如GCM或EAX)或方案来完成。解密passwordBytes=SHA256.Create().ComputeHash(passwordBytes)时,您正在散列密码代码>,但不是在encrypt@pedrofb我需要做什么当我Decrypt@pedrofb谢谢,我删除了那条线,现在它工作了。谢天谢地,仅仅使用散列函数是不够的,仅仅添加一个salt对提高安全性几乎没有什么作用。取而代之的是,在HMAC上随机添加盐,持续约100毫秒,并将盐与散列一起保存。使用诸如PBKDF2
、password\u hash
、Bcrypt
等函数和类似函数。关键是让攻击者花费大量时间用暴力寻找密码。永远不要使用。它是确定性的,因此在语义上不安全。您至少应该使用随机模式,如或。最好是对密文进行身份验证,这样就不可能进行类似的攻击。这可以通过认证模式(如GCM或EAX)完成,也可以通过方案完成。谢谢投票给您的答案。我已经用了3个小时来找出错误,谢谢投票给你的答案。我已经用了3个小时来找出错误