c# - Rijndael 加密器:获取空字节 []。不加密任何东西
问题描述
晚上好!
我正在尝试在 c# 中使用 Rijndael 算法和 Rijndael 类来实现加密器。我试图遵循(不做完全相同的代码)下面的链接,但问题是给出了一个要加密的字符串我没有得到任何结果。我也没有收到任何错误消息。
CryptDecrypt.cs
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace RijndaelAlgorithm {
public class CryptDecrypt {
private Byte[] iv;
private Byte[] key;
public CryptDecrypt(String key) {
iv = new Byte[] {21, 10, 21, 251, 132, 76, 121, 27, 210, 81, 215, 99, 14, 235, 11, 75};
this.key = Encoding.ASCII.GetBytes(key);
}
public String encryptMsg(String originalMsg) {
byte[] encryptedMsg;
Rijndael rijAlg = Rijndael.Create();
rijAlg.Key = formatKey();
rijAlg.IV = iv;
MemoryStream msEncrypt = new MemoryStream();
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
StreamWriter swEncrypt = new StreamWriter(csEncrypt);
swEncrypt.Write(originalMsg);
encryptedMsg = msEncrypt.ToArray();
Console.WriteLine("encryptedMsg.Length: " + encryptedMsg.Length);
return Convert.ToBase64String(encryptedMsg, 0, encryptedMsg.Length);
}
private Byte[] formatKey() {
int len = key.Length;
String strKey = System.Text.Encoding.UTF8.GetString(key);
String fillKey = "";
String strFormatedKey = "";
Byte[] formatedKeyByte;
if (len < 16)
fillKey = new String('X',(16 - len));
strFormatedKey = String.Concat(strKey, fillKey);
formatedKeyByte = Encoding.ASCII.GetBytes(strFormatedKey);
return formatedKeyByte;
}
}
}
菜单.cs
using System;
namespace RijndaelAlgorithm {
public class Menu {
private CryptDecrypt r;
public Menu() {
r = new CryptDecrypt("123654");
}
public void showMenu() {
Console.WriteLine("the encrypted message is: " + r.encryptMsg("isjustatest"));
}
}
}
解决方案
您似乎想用您的 .NET 应用程序加密一条消息,并希望获得与您在评论中提到的特定在线服务相同的加密字节。
范围
加密的一个参数是初始化向量 (IV)。它应该是随机的并且只使用一次。因此,如果正确实现了两个应用程序(具有不同的随机 IV),则加密的字节是不同的。
即使您使用相同的输入,每次您按下该键时,此服务都会返回不同的结果。
但是,如果您通常采用不同的加密结果并使用相同的密钥对其进行解密,您将获得原始字节。
使用此特定服务进行测试的下一个问题是,它们始终提供相同的前缀 base64 序列“U2FsdGVkX1”。这不是标准的 AES 输出(如果你解码这个 base64 序列,你会得到'Salted_P')。因此,使用不同的在线服务进行测试是有意义的。
因此,如果两个 AES-256 编码实现使用相同的参数,我们将得到相同的编码结果。我们需要它:
- 密钥(32 个字节,而不是 AES-256 的 16 个字节)
- 四(16字节)
说到密钥长度:正如其他人在评论中提到的那样,您不应该简单地添加“X”或类似的东西,而是使用标准的加密机制来派生一个好的密钥。
方便测试的方法是将十六进制字符串转换为字节数组并返回,例如,请参阅这个很酷的答案中的 StringToByteArray 和 ByteArrayToString 方法: https ://stackoverflow.com/a/311179
试一试吧。如果我们收到您的消息“isjustatest”,其中包含十六进制字符串“69736a7573746174657374374”,我们需要 AES-256 的 32 字节密钥和 16 字节 IV。
正如评论中提到的其他人一样,您需要刷新和关闭流(或者更好的是,使用“使用”语句)。
获取您的代码并更改密钥和 iv 分配并将加密消息输出到控制台:
rijAlg.Key = StringToByteArray("519C7C3402A943D8AF83746C1548E475319EBDA6A38046059F83B21709BD6A5B"); //32 bytes
rijAlg.IV = StringToByteArray("0D024CF947CE4C288880D0B34D29BFA5"); // 16 bytes
...
swEncrypt.Write(originalMsg);
swEncrypt.Flush();
swEncrypt.Close();
...
Console.WriteLine("encrypted bytes: '" + ByteArrayToString(encryptedMsg) + "'");
这会在调试控制台中输出“419536f27da3406625b2d07f43833aab”。
所以现在我们可以使用在线服务,例如https://cryptii.com/pipes/aes-encryption,我们可以在其中输入输入数据,选择加密算法,提供密钥和 IV 字节,然后我们会得到与您的相同的结果程序,请参见此处的屏幕截图:
如上所述,在实际应用中使用时不要忘记使用不同的随机 IV。
推荐阅读
- r - 如何在r中获取数据框中重复值的下一个元素?
- firefox - 之前设置的“Samesite: Strict”cookie 在 document.cookie Firefox 和 Safari 中不可用
- r - 如何根据特定变量的变化删除观察结果?
- sql-server - 搜索以确定一个表中的键值是否永远不会与另一表中的键值匹配
- css - Joomla Jform 单选按钮未与其标签水平对齐
- javascript - 为什么你不能 Array.prototype.pop.call() 一个字符串?
- c++ - 如何在二维数组的末尾添加列和行?
- java - 我可以在短时间内找到合适的 MirrorAnnotation 吗?
- scala - 有没有办法将文件加载到目录中并能够在处理后将其删除
- sql-server - SSIS 无法获取连接。连接可能未正确配置,或者您可能对此连接没有正确的权限