在写入数据库之前,我需要加密一些数据,从DB读取数据时需要解密。
我使用了本指南中提供的代码:在通用Windows应用程序中加密和解密数据
每当我试图解密时,我就会得到错误:
数据错误(循环冗余检查)。(HRESULT例外: 0x80070017)
我认为这是因为密钥是不同的,因为我实例化了SymmetricEncryptionHelper对象一次用于加密,另一次用于解密。为了解决这一问题,我将类更改为单例,但仍然得到了相同的错误:
public class SymmetricEncryptionHelper
{
private readonly IBuffer randomBuffer;
private readonly IBuffer randomBufferCBC;
private readonly CryptographicKey cryptographicKey;
private readonly string algorithmName;
private readonly SymmetricKeyAlgorithmProvider cryptingProvider;
private static SymmetricEncryptionHelper _instance;
public static SymmetricEncryptionHelper Instance
{
get
{
if (_instance == null)
{
_instance = new SymmetricEncryptionHelper();
}
return _instance;
}
}
/// <summary>
/// Instantiate with a random generated buffer (not an option if
/// you want to persist the encryption to disk)
/// </summary>
private SymmetricEncryptionHelper()
{
algorithmName = SymmetricAlgorithmNames.AesEcbPkcs7;
cryptingProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(algorithmName);
randomBuffer = CryptographicBuffer.GenerateRandom(cryptingProvider.BlockLength);
randomBufferCBC = null;
cryptographicKey = cryptingProvider.CreateSymmetricKey(randomBuffer);
}
/// <summary>
/// Instantiate with a custom generated buffer (good for
/// persisting the encryption to disk)
/// </summary>
/// <param name="randomBuffer">The custom generated buffer</param>
private SymmetricEncryptionHelper(IBuffer randomBuffer)
: this()
{
this.randomBuffer = randomBuffer;
cryptographicKey = cryptingProvider.CreateSymmetricKey(randomBuffer);
}
/// <summary>
/// Instantiate with a custom generated buffer (good for
/// persisting the encryption to disk) and with a custom
/// generated CBC buffer (is using CBC algorithms)
/// </summary>
/// <param name="randomBuffer">The custom generated buffer</param>
/// <param name="randomBufferCBC">The custom generated CBC buffer</param>
private SymmetricEncryptionHelper(IBuffer randomBuffer, IBuffer randomBufferCBC)
: this(randomBuffer)
{
this.randomBufferCBC = randomBufferCBC;
}
private bool IsMultipleOfBlockLength(IBuffer binaryData)
{
return (binaryData.Length % cryptingProvider.BlockLength) != 0;
}
/// <summary>
/// Encrypts a given string
/// </summary>
/// <param name="data">Data to be encrypted</param>
/// <returns>An encrypted string in Unicode</returns>
public string Encrypt(string data)
{
if (string.IsNullOrEmpty(data))
{
return data;
}
var binaryData = Encoding.Unicode.GetBytes(data).AsBuffer();
if (!algorithmName.Contains("PKCS7") && IsMultipleOfBlockLength(binaryData))
throw new Exception("Message buffer length must be multiple of block length !!");
var encryptedBinaryData = CryptographicEngine.Encrypt(cryptographicKey, binaryData, randomBufferCBC);
return Encoding.Unicode.GetString(encryptedBinaryData.ToArray());
}
/// <summary>
/// Decrypts a string in Unicode
/// </summary>
/// <param name="encryptedData">An encrypted string in Unicode</param>
/// <returns>The decrypted string in Unicode</returns>
public string Decrypt(string encryptedData)
{
if (string.IsNullOrEmpty(encryptedData))
{
return encryptedData;
}
try
{
var encryptedBinaryData = Encoding.Unicode.GetBytes(encryptedData).AsBuffer();
var decryptedData = CryptographicEngine.Decrypt(cryptographicKey, encryptedBinaryData, randomBufferCBC);
return Encoding.Unicode.GetString(decryptedData.ToArray());
}
catch (Exception ex)
{
return null;
}
}
}有人能看到我哪里出错了吗?我在谷歌上搜索了错误,但似乎找不到对我有用的答案。
此外,一旦应用程序关闭,我将失去钥匙,那么这里的最佳实践是什么?我应该把密钥保存在PasswordVault中吗?
发布于 2017-06-03 10:42:29
不要信任互联网上的随机代码。你得知道你在做什么。欧洲央行模式加密对于文本消息来说是不安全的,而且大多数其他密码操作都是不安全的。
您的问题是直接依赖于加密方法中生成的密文的解码(使用Encoding.Unicode.GetString,微软的坏名称UTF-16 on )。现在,密文总是包含随机字节。这些字节对并不总是构成有效的UTF-16 of编码字符。因此,通常这些被忽略在严格的密文或他们被一个替代字符取代。
显然,如果引入了替代字符,那么这个特定的密文块将被解密成一个随机数据块,从而使您的CRC检查失败。
如果出于某种原因需要将密文显示为文本,则base64对其进行编码。
https://stackoverflow.com/questions/44342742
复制相似问题