AesEncryption 似乎没有解密,对吗?
AesEncryption doesn't appear to decrypt right?
我写这个 class 是为了允许我加密和解密对象的 json 表示,但它似乎不像 MSDN 文档那样工作(此处:https://msdn.microsoft.com/en-us/library/system.security.cryptography.aesmanaged%28v=vs.95%29.aspx?f=255&MSPPError=-2147217396)建议应该...
using Newtonsoft.Json;
using System;
using System.Configuration;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Web.Configuration;
namespace Core.Data
{
public class AesCrypto<T> : ICrypto<T>
{
string DecryptionKey { get { return ((MachineKeySection)ConfigurationManager.GetSection("system.web/machineKey")).DecryptionKey; } }
public string Encrypt(T source, string salt)
{
var sourceString = JsonConvert.SerializeObject(source);
using (var aes = new AesManaged())
{
aes.Padding = PaddingMode.PKCS7;
aes.GenerateIV();
using (var stream = new MemoryStream())
{
var deriveBytes = new Rfc2898DeriveBytes(DecryptionKey, Encoding.Unicode.GetBytes(salt));
aes.Key = deriveBytes.GetBytes(128 / 8);
stream.Write(BitConverter.GetBytes(aes.IV.Length), 0, sizeof(int));
stream.Write(aes.IV, 0, aes.IV.Length);
using (var cs = new CryptoStream(stream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
byte[] rawPlaintext = Encoding.Unicode.GetBytes(sourceString);
cs.Write(rawPlaintext, 0, rawPlaintext.Length);
cs.FlushFinalBlock();
stream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(stream, Encoding.Unicode))
return reader.ReadToEnd();
}
}
}
}
public T Decrypt(string sourceString, string salt)
{
using (Aes aes = new AesManaged())
{
aes.Padding = PaddingMode.PKCS7;
var deriveBytes = new Rfc2898DeriveBytes(DecryptionKey, Encoding.Unicode.GetBytes(salt));
aes.Key = deriveBytes.GetBytes(128 / 8);
using (var stream = new MemoryStream(Encoding.Unicode.GetBytes(sourceString)))
{
stream.Seek(0, SeekOrigin.Begin);
// Get the initialization vector from the encrypted stream
aes.IV = ReadIV(stream);
using (var reader = new StreamReader(new CryptoStream(stream, aes.CreateDecryptor(aes.Key, aes.IV), CryptoStreamMode.Read), Encoding.Unicode))
{
var resultString = reader.ReadToEnd();
return JsonConvert.DeserializeObject<T>(resultString);
}
}
}
}
byte[] ReadIV(Stream s)
{
byte[] rawLength = new byte[sizeof(int)];
if (s.Read(rawLength, 0, rawLength.Length) != rawLength.Length)
{
throw new SystemException("Stream did not contain properly formatted byte array");
}
byte[] buffer = new byte[BitConverter.ToInt32(rawLength, 0)];
if (s.Read(buffer, 0, buffer.Length) != buffer.Length)
{
throw new SystemException("Did not read byte array properly");
}
return buffer;
}
}
}
我编写了以下单元测试来测试此功能...
using Core.Data;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace Core.Tests
{
[TestClass]
public class CryptoTests
{
class EncryptableObject
{
public int Id { get; set; }
public string Name { get; set; }
public DateTimeOffset When { get; set; }
}
[TestMethod]
public void TestAesCrypto()
{
var testInput = new EncryptableObject { Id = 123, Name = "Victim", When = DateTimeOffset.UtcNow };
var crypto = new AesCrypto<EncryptableObject>();
var testSalt = "testtest";
var magicString = crypto.Encrypt(testInput, testSalt);
var testOutput = crypto.Decrypt(magicString, testSalt);
Assert.AreEqual(testInput.Id, testOutput.Id);
Assert.AreEqual(testInput.Name, testOutput.Name);
Assert.AreEqual(testInput.When, testOutput.When);
}
}
}
问题好像层出不穷...
- 出于某种原因,我的 json 输出中的解密方法在 "var resultString = reader.ReadToEnd();"
行中得到了似乎是中文的字符
- 每次我 运行 输出都不一样。
- 当我不附加
调试器,但是当我这样做时抛出一个关于未能反序列化 json 的异常。
- 不确定为什么它似乎在读取错误的配置值(但这可能与加密不起作用无关)
我做错了什么?
好的,我发现我的问题基本上是编码问题,所以更进一步,我通过@https://gist.github.com/jbtule/4336842#file-aesthenhmac-cs[=12 从@jbtule(感谢 James)的示例中获取了代码=]
抓住 "AESThenHMAC" class 然后我就可以写这个了...
public class AesCrypto<T> : ICrypto<T>
{
public string Encrypt(T source, string key)
{
var e = Encoding.UTF8;
var rawData = e.GetBytes(JsonConvert.SerializeObject(source));
var cipherData = AESThenHMAC.SimpleEncryptWithPassword(rawData, key);
return Convert.ToBase64String(cipherData);
}
public T Decrypt(string source, string key)
{
var e = Encoding.UTF8;
var decryptedBytes = AESThenHMAC.SimpleDecryptWithPassword(Convert.FromBase64String(source), key);
return JsonConvert.DeserializeObject<T>(e.GetString(decryptedBytes));
}
}
...完美通过了上述单元测试:)
我写这个 class 是为了允许我加密和解密对象的 json 表示,但它似乎不像 MSDN 文档那样工作(此处:https://msdn.microsoft.com/en-us/library/system.security.cryptography.aesmanaged%28v=vs.95%29.aspx?f=255&MSPPError=-2147217396)建议应该...
using Newtonsoft.Json;
using System;
using System.Configuration;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Web.Configuration;
namespace Core.Data
{
public class AesCrypto<T> : ICrypto<T>
{
string DecryptionKey { get { return ((MachineKeySection)ConfigurationManager.GetSection("system.web/machineKey")).DecryptionKey; } }
public string Encrypt(T source, string salt)
{
var sourceString = JsonConvert.SerializeObject(source);
using (var aes = new AesManaged())
{
aes.Padding = PaddingMode.PKCS7;
aes.GenerateIV();
using (var stream = new MemoryStream())
{
var deriveBytes = new Rfc2898DeriveBytes(DecryptionKey, Encoding.Unicode.GetBytes(salt));
aes.Key = deriveBytes.GetBytes(128 / 8);
stream.Write(BitConverter.GetBytes(aes.IV.Length), 0, sizeof(int));
stream.Write(aes.IV, 0, aes.IV.Length);
using (var cs = new CryptoStream(stream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
byte[] rawPlaintext = Encoding.Unicode.GetBytes(sourceString);
cs.Write(rawPlaintext, 0, rawPlaintext.Length);
cs.FlushFinalBlock();
stream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(stream, Encoding.Unicode))
return reader.ReadToEnd();
}
}
}
}
public T Decrypt(string sourceString, string salt)
{
using (Aes aes = new AesManaged())
{
aes.Padding = PaddingMode.PKCS7;
var deriveBytes = new Rfc2898DeriveBytes(DecryptionKey, Encoding.Unicode.GetBytes(salt));
aes.Key = deriveBytes.GetBytes(128 / 8);
using (var stream = new MemoryStream(Encoding.Unicode.GetBytes(sourceString)))
{
stream.Seek(0, SeekOrigin.Begin);
// Get the initialization vector from the encrypted stream
aes.IV = ReadIV(stream);
using (var reader = new StreamReader(new CryptoStream(stream, aes.CreateDecryptor(aes.Key, aes.IV), CryptoStreamMode.Read), Encoding.Unicode))
{
var resultString = reader.ReadToEnd();
return JsonConvert.DeserializeObject<T>(resultString);
}
}
}
}
byte[] ReadIV(Stream s)
{
byte[] rawLength = new byte[sizeof(int)];
if (s.Read(rawLength, 0, rawLength.Length) != rawLength.Length)
{
throw new SystemException("Stream did not contain properly formatted byte array");
}
byte[] buffer = new byte[BitConverter.ToInt32(rawLength, 0)];
if (s.Read(buffer, 0, buffer.Length) != buffer.Length)
{
throw new SystemException("Did not read byte array properly");
}
return buffer;
}
}
}
我编写了以下单元测试来测试此功能...
using Core.Data;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace Core.Tests
{
[TestClass]
public class CryptoTests
{
class EncryptableObject
{
public int Id { get; set; }
public string Name { get; set; }
public DateTimeOffset When { get; set; }
}
[TestMethod]
public void TestAesCrypto()
{
var testInput = new EncryptableObject { Id = 123, Name = "Victim", When = DateTimeOffset.UtcNow };
var crypto = new AesCrypto<EncryptableObject>();
var testSalt = "testtest";
var magicString = crypto.Encrypt(testInput, testSalt);
var testOutput = crypto.Decrypt(magicString, testSalt);
Assert.AreEqual(testInput.Id, testOutput.Id);
Assert.AreEqual(testInput.Name, testOutput.Name);
Assert.AreEqual(testInput.When, testOutput.When);
}
}
}
问题好像层出不穷...
- 出于某种原因,我的 json 输出中的解密方法在 "var resultString = reader.ReadToEnd();" 行中得到了似乎是中文的字符
- 每次我 运行 输出都不一样。
- 当我不附加 调试器,但是当我这样做时抛出一个关于未能反序列化 json 的异常。
- 不确定为什么它似乎在读取错误的配置值(但这可能与加密不起作用无关)
我做错了什么?
好的,我发现我的问题基本上是编码问题,所以更进一步,我通过@https://gist.github.com/jbtule/4336842#file-aesthenhmac-cs[=12 从@jbtule(感谢 James)的示例中获取了代码=]
抓住 "AESThenHMAC" class 然后我就可以写这个了...
public class AesCrypto<T> : ICrypto<T>
{
public string Encrypt(T source, string key)
{
var e = Encoding.UTF8;
var rawData = e.GetBytes(JsonConvert.SerializeObject(source));
var cipherData = AESThenHMAC.SimpleEncryptWithPassword(rawData, key);
return Convert.ToBase64String(cipherData);
}
public T Decrypt(string source, string key)
{
var e = Encoding.UTF8;
var decryptedBytes = AESThenHMAC.SimpleDecryptWithPassword(Convert.FromBase64String(source), key);
return JsonConvert.DeserializeObject<T>(e.GetString(decryptedBytes));
}
}
...完美通过了上述单元测试:)