C# AES解密输出与输入不一样
C# AES decrypted output is not the same as input
我想做一个简单的消息加密器来尝试解决这个问题,但我做不到。问题是无论我从什么输入开始,有时它都会对其进行加密,但是当我尝试对其进行解密时,它不会 return 原始字符串。如果您能告诉我我做错了什么或指导正确的方向,那将非常有帮助。
这是负责加密和解密的部分。
void Decrypt()
{
using var crypt = Aes.Create();
string[] input = ClipboardService.GetText()?.Split(SEPARATOR) ?? Array.Empty<string>();
byte[] key = input[0].ToBytes();
byte[] IV = input[^1].ToBytes();
byte[] value = string.Join(string.Empty, input[1..^1]).ToBytes();
crypt.IV = IV;
crypt.Key = key;
var decryptedValue = crypt.DecryptCbc(value, IV, PaddingMode.Zeros);
string decryptedValueInText = decryptedValue.ToUnicodeString();
ClipboardService.SetText(decryptedValueInText);
LogInfoMessage($"{decryptedValueInText}: {decryptedValue.Length}");
crypt.Clear();
}
void Encrypt()
{
using var crypt = Aes.Create();
crypt.GenerateKey();
string value = ClipboardService.GetText() ?? string.Empty;
var encryptedValue = crypt.EncryptCbc(value.ToBytes(), crypt.IV, PaddingMode.Zeros);
string encryptedValueInText = $"{crypt.Key.ToUnicodeString()}{SEPARATOR}{encryptedValue.ToUnicodeString()}{SEPARATOR}{crypt.IV.ToUnicodeString()}";
ClipboardService.SetText(encryptedValueInText);
LogInfoMessage($"{encryptedValueInText}: {encryptedValue.Length}");
crypt.Clear();
}
有两种扩展方法:
public static string ToUnicodeString(this byte[] bytes) => Encoding.Unicode.GetString(bytes);
public static byte[] ToBytes(this string str) => Encoding.Unicode.GetBytes(str);
例子
输入链接是:
https://www.youtube.com/watch?v=bSA91XTzeuA
我认为这不重要,因为密钥和 IV 无论如何每次都会自动生成,但仍然如此。
根据我们的讨论...
由于无效的 UTF-16 代码点,使用剪贴板将二进制数据存储为 Unicode 文本将失败。 UTF-16 对某些 Unicode 字符使用一些 multi-word 编码,使用代理对中的 32 位来编码来自补充平面的 Unicode 代码点。有很多关于 UTF-16 编码的引物,但基本上你有一对 16 位值,其中第一个在 0xD800-0xDBFF 范围内,第二个必须在 0xDC00-0xDFFF 范围内。您的加密数据的赔率将违反此规则。
如前所述,如果您的加密二进制数据必须通过 text-only 传输方式发送,您应该使用 Base64 或类似方式对加密块中的字节进行编码。
我还想强调的是,编写可以使用参数调用的方法而不是直接访问 I/O 的剪贴板使得测试变得更加简单,包括 round-trip 上的测试问题的各个部分。证明编解码器在不参考剪贴板的情况下工作是一个很好的测试,关注点分离有助于在未来更容易地识别问题的根源。
我想做一个简单的消息加密器来尝试解决这个问题,但我做不到。问题是无论我从什么输入开始,有时它都会对其进行加密,但是当我尝试对其进行解密时,它不会 return 原始字符串。如果您能告诉我我做错了什么或指导正确的方向,那将非常有帮助。
这是负责加密和解密的部分。
void Decrypt()
{
using var crypt = Aes.Create();
string[] input = ClipboardService.GetText()?.Split(SEPARATOR) ?? Array.Empty<string>();
byte[] key = input[0].ToBytes();
byte[] IV = input[^1].ToBytes();
byte[] value = string.Join(string.Empty, input[1..^1]).ToBytes();
crypt.IV = IV;
crypt.Key = key;
var decryptedValue = crypt.DecryptCbc(value, IV, PaddingMode.Zeros);
string decryptedValueInText = decryptedValue.ToUnicodeString();
ClipboardService.SetText(decryptedValueInText);
LogInfoMessage($"{decryptedValueInText}: {decryptedValue.Length}");
crypt.Clear();
}
void Encrypt()
{
using var crypt = Aes.Create();
crypt.GenerateKey();
string value = ClipboardService.GetText() ?? string.Empty;
var encryptedValue = crypt.EncryptCbc(value.ToBytes(), crypt.IV, PaddingMode.Zeros);
string encryptedValueInText = $"{crypt.Key.ToUnicodeString()}{SEPARATOR}{encryptedValue.ToUnicodeString()}{SEPARATOR}{crypt.IV.ToUnicodeString()}";
ClipboardService.SetText(encryptedValueInText);
LogInfoMessage($"{encryptedValueInText}: {encryptedValue.Length}");
crypt.Clear();
}
有两种扩展方法:
public static string ToUnicodeString(this byte[] bytes) => Encoding.Unicode.GetString(bytes);
public static byte[] ToBytes(this string str) => Encoding.Unicode.GetBytes(str);
例子 输入链接是:
https://www.youtube.com/watch?v=bSA91XTzeuA
我认为这不重要,因为密钥和 IV 无论如何每次都会自动生成,但仍然如此。
根据我们的讨论...
由于无效的 UTF-16 代码点,使用剪贴板将二进制数据存储为 Unicode 文本将失败。 UTF-16 对某些 Unicode 字符使用一些 multi-word 编码,使用代理对中的 32 位来编码来自补充平面的 Unicode 代码点。有很多关于 UTF-16 编码的引物,但基本上你有一对 16 位值,其中第一个在 0xD800-0xDBFF 范围内,第二个必须在 0xDC00-0xDFFF 范围内。您的加密数据的赔率将违反此规则。
如前所述,如果您的加密二进制数据必须通过 text-only 传输方式发送,您应该使用 Base64 或类似方式对加密块中的字节进行编码。
我还想强调的是,编写可以使用参数调用的方法而不是直接访问 I/O 的剪贴板使得测试变得更加简单,包括 round-trip 上的测试问题的各个部分。证明编解码器在不参考剪贴板的情况下工作是一个很好的测试,关注点分离有助于在未来更容易地识别问题的根源。