在youtube上观看视频后,我在C#中使用Rijndael制作了加密程序。这很简单。
Interface picture 我可以输入64位和128位密钥。但是不允许使用192位密钥(为什么?)。
如果我使用64位密钥,当我加密一个字并尝试解密它时,它只解密字符数为< = 16的字。它的字符数大于16,抛出的错误信息称“填充是无效且无法删除“。
128位密钥也是如此。只有具有字符数< = 32的字才被解密。否则会显示相同的错误消息。
以下是对问题进行清晰认识的总结
Problem Summery picture 这是加密的代码
// need using System.Security.Cryptography;
// using System.IO;
public Form1()
{
InitializeComponent();
desObj = Rijndael.Create();
}
string cipherData;
byte[] chipherbytes;
byte[] plainbyte;
byte[] plainbyte2;
byte[] plainkey;
SymmetricAlgorithm desObj;
private void button2_Click(object sender, EventArgs e)
{
try
{
cipherData = textBox1.Text;
plainbyte = Encoding.ASCII.GetBytes(cipherData);
plainkey = Encoding.ASCII.GetBytes(textBox4.Text);
desObj.Key = plainkey;
//choose any method
desObj.Mode = CipherMode.CBC;
desObj.Padding = PaddingMode.PKCS7;
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, desObj.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(plainbyte, 0, plainbyte.Length);
cs.Close();
chipherbytes = ms.ToArray();
ms.Close();
textBox2.Text = Encoding.ASCII.GetString(chipherbytes);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
和解密代码是
private void button3_Click(object sender, EventArgs e)
{
try
{
MemoryStream ms1 = new MemoryStream(chipherbytes);
CryptoStream cs1 = new CryptoStream(ms1, desObj.CreateDecryptor(), CryptoStreamMode.Read);
cs1.Read(chipherbytes, 0, chipherbytes.Length);
plainbyte2 = ms1.ToArray();
cs1.Close();
ms1.Close();
textBox3.Text = Encoding.ASCII.GetString(plainbyte2);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
答案 0 :(得分:0)
密文由任意字节组成,不必构成有效的ASCII编码。如果存在一些不可打印的ASCII字符,则以这种方式使用时不会打印它们:Encoding.ASCII.GetString(chipherbytes)
。
您需要使用Base64或Hex之类的密码对密文进行编码,这样可以使编码密文更大,但可以完美地表示为打印字符串。
其他考虑因素:
CBC模式需要初始化向量(IV),因为您没有设置任何IV,所以它将为您生成。问题是你在解密过程中需要相同的IV。此代码有效,因为您使用相同的desObj
进行加密和解密,并且它包含相同的IV,但是当您开始复制密文时,这不会起作用。
IV不应该是秘密的。一种常见的方法是将密码与密文一起传递,然后在解密之前将其切掉。
您没有进行任何完整性检查。最好对您的密文进行身份验证,以便像padding oracle attack这样的攻击是不可能的,您可以检测密文是否被(恶意)篡改或密钥输入错误。这可以使用经过验证的模式(如GCM或EAX)或encrypt-then-MAC方案来完成。
Rijndael通常支持128,192和256位的密钥大小。一个字节通常有8位,因此相当于16,24和32字节键。
用户不输入密钥,因为它们通常需要与随机噪声和特定长度无法区分。最好让用户输入密码,并使用高迭代次数/成本因子从PBKDF2,bcrypt,scrypt或Argon2中获取密钥。