问题描述
我需要一些简单的字符串加密,所以我编写了以下代码(来自 这里):
I needed some simple string encryption, so I wrote the following code (with a great deal of "inspiration" from here):
// create and initialize a crypto algorithm
private static SymmetricAlgorithm getAlgorithm(string password) {
SymmetricAlgorithm algorithm = Rijndael.Create();
Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(
password, new byte[] {
0x53,0x6f,0x64,0x69,0x75,0x6d,0x20, // salty goodness
0x43,0x68,0x6c,0x6f,0x72,0x69,0x64,0x65
}
);
algorithm.Padding = PaddingMode.ISO10126;
algorithm.Key = rdb.GetBytes(32);
algorithm.IV = rdb.GetBytes(16);
return algorithm;
}
/*
* encryptString
* provides simple encryption of a string, with a given password
*/
public static string encryptString(string clearText, string password) {
SymmetricAlgorithm algorithm = getAlgorithm(password);
byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, algorithm.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
return Convert.ToBase64String(ms.ToArray());
}
/*
* decryptString
* provides simple decryption of a string, with a given password
*/
public static string decryptString(string cipherText, string password) {
SymmetricAlgorithm algorithm = getAlgorithm(password);
byte[] cipherBytes = Convert.FromBase64String(cipherText);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, algorithm.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
return System.Text.Encoding.Unicode.GetString(ms.ToArray());
}
代码似乎工作正常,除了当使用不正确的密钥解密数据时,我在解密字符串的 cs.Close() 行上收到 CryptographicException - 填充无效且无法删除".
The code appears to work fine, except that when decrypting data with an incorrect key, I get a CryptographicException - "Padding is invalid and cannot be removed" - on the cs.Close() line in decryptString.
示例代码:
string password1 = "password";
string password2 = "letmein";
string startClearText = "The quick brown fox jumps over the lazy dog";
string cipherText = encryptString(startClearText, password1);
string endClearText = decryptString(cipherText, password2); // exception thrown
我的问题是,这是意料之中的吗?我原以为用错误的密码解密只会导致无意义的输出,而不是异常.
My question is, is this to be expected? I would have thought that decrypting with the wrong password would just result in nonsense output, rather than an exception.
推荐答案
虽然已经回答了这个问题,但我认为最好解释一下为什么这是意料之中的.
Although this have been already answered I think it would be a good idea to explain why it is to be expected.
通常会应用填充方案,因为大多数加密过滤器在语义上并不安全,并且可以防止某些形式的加密攻击.例如,通常在 RSA 中使用 OAEP 填充方案来防止某些类型的攻击(例如选择的明文攻击或blinding).
A padding scheme is usually applied because most cryptographic filters are not semantically secure and to prevent some forms of cryptoatacks. For example, usually in RSA the OAEP padding scheme is used which prevents some sorts of attacks (such as a chosen plaintext attack or blinding).
在发送消息之前,填充方案会在消息 m 上附加一些(通常)随机垃圾.在OAEP方法中,例如使用了两个Oracle(这是一个简单的解释):
A padding scheme appends some (usually) random garbage to the message m before the message is sent. In the OAEP method, for example, two Oracles are used (this is a simplistic explanation):
- 给定模数的大小,您用 0 填充 k1 位,用随机数填充 k0 位.
- 然后通过对消息进行一些转换,您可以获得经过加密和发送的填充消息.
这为您提供了消息的随机化,并提供了一种测试消息是否垃圾的方法.由于填充方案是可逆的,当您解密消息时,虽然您无法说明消息本身的完整性,但实际上您可以对填充做出一些断言,因此您可以知道消息是否已正确解密或者您做错了什么(即有人篡改了消息或您使用了错误的密钥)
That provides you with a randomization for the messages and with a way to test if the message is garbage or not. As the padding scheme is reversible, when you decrypt the message whereas you can't say anything about the integrity of the message itself you can, in fact, make some assertion about the padding and thus you can know if the message has been correctly decrypted or you're doing something wrong (i.e someone has tampered with the message or you're using the wrong key)
这篇关于为什么密码错误会导致“填充无效且无法删除"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!