joe*_*our 0 c# encryption aes .net-core
我在创建在 URL 中传递的加密字符串时遇到问题。我在解密后得到不正确的字符或错误。“输入数据不是一个完整的块”
这是我的类来加密和解密我的字符串:
public static class StringCipher
{
public static string Encrypt(string s)
{
return AesProvider(s, (aes, raw) =>
{
using var ms = new MemoryStream();
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(raw, 0, raw.Length);
}
return Encoding.UTF8.GetString(ms.ToArray());
});
}
public static string Decrypt(string s)
{
return AesProvider(s, (aes, raw) =>
{
using var ms = new MemoryStream();
using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(raw, 0, raw.Length);
}
return Encoding.UTF8.GetString(ms.ToArray());
});
}
private static string AesProvider(string s, Func<Aes, byte[], string> fn)
{
var raw = Encoding.UTF8.GetBytes(s);
using var aes = Aes.Create();
aes.Padding = PaddingMode.Zeros;
aes.KeySize = 128; // in bits
aes.Key = new byte[128 / 8]; // 16 bytes for 128 bit encryption
aes.IV = new byte[128 / 8]; // AES needs a 16-byte IV
aes.Mode = CipherMode.CBC;
return fn.Invoke(aes, raw);
}
}
Run Code Online (Sandbox Code Playgroud)
示例用法如下:
var encrypted = StringCipher.Encrypt("my payload");
Run Code Online (Sandbox Code Playgroud)
然后我使用Base64UrlEncoder我理解的 URL 安全的 base64 编码。
var url = $"https://example.com?code={Base64UrlEncoder.Encode(encrypted)}"
Run Code Online (Sandbox Code Playgroud)
当我想解密它时,我尝试执行以下操作:
// https://example.com?code=a5e52f...
var decoded = Base64UrlEncoder.Decode(code);
var plainText = StringCipher.Decrypt(decoded); // expect "my payload"
Run Code Online (Sandbox Code Playgroud)
我知道我一定犯了一个愚蠢的错误。
问题:
简而言之:因为并非每个字节序列都是有效的 UTF-8 字符序列,并且由于 \xc2\xa0Encoding.UTF8默认情况下只是忽略无效序列,因此当您使用 将这些字节转换为字符串时GetString,最终会丢失一些数据。
使用 Base64 是正确的方法,但你做错了:你想将字节数组传递给Base64UrlEncoder.Encode,而不是字符串。不做这GetString一步,直接把结果传过去ms.ToArray()。Base64 的全部意义是将任意二进制数据转换为文本,不需要中间转换为字符串。
同样,解密时,您应该Base64UrlEncoder.DecodeBytes将该字符串转换为字节,然后解密这些字节。
最终结果如下所示。首先,我修改了AesProvider方法以Aes直接返回对象:
private static Aes CreateProvider()\n{\n var aes = Aes.Create();\n\n // etc.\n\n return aes;\n}\nRun Code Online (Sandbox Code Playgroud)\n然后,这里是Encrypt:
public static string Encrypt(string s)\n{\n using var aes = CreateProvider();\n \n using var ms = new MemoryStream();\n using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))\n {\n var raw = Encoding.UTF8.GetBytes(s);\n cs.Write(raw, 0, raw.Length);\n }\n\n return Base64UrlEncoder.Encode(ms.ToArray());\n}\nRun Code Online (Sandbox Code Playgroud)\n这是解密:
\npublic static string Decrypt(string s)\n{\n using var aes = CreateProvider();\n\n using var ms = new MemoryStream();\n using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))\n {\n var raw = Base64UrlEncoder.DecodeBytes(s);\n cs.Write(raw, 0, raw.Length);\n }\n return Encoding.UTF8.GetString(ms.ToArray());\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
751 次 |
| 最近记录: |