首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对称加密循环冗余校验

对称加密循环冗余校验
EN

Stack Overflow用户
提问于 2017-06-03 10:04:07
回答 1查看 365关注 0票数 0

在写入数据库之前,我需要加密一些数据,从DB读取数据时需要解密。

我使用了本指南中提供的代码:在通用Windows应用程序中加密和解密数据

每当我试图解密时,我就会得到错误:

数据错误(循环冗余检查)。(HRESULT例外: 0x80070017)

我认为这是因为密钥是不同的,因为我实例化了SymmetricEncryptionHelper对象一次用于加密,另一次用于解密。为了解决这一问题,我将类更改为单例,但仍然得到了相同的错误:

代码语言:javascript
复制
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中吗?

EN

回答 1

Stack Overflow用户

发布于 2017-06-03 10:42:29

不要信任互联网上的随机代码。你得知道你在做什么。欧洲央行模式加密对于文本消息来说是不安全的,而且大多数其他密码操作都是不安全的。

您的问题是直接依赖于加密方法中生成的密文的解码(使用Encoding.Unicode.GetString,微软的坏名称UTF-16 on )。现在,密文总是包含随机字节。这些字节对并不总是构成有效的UTF-16 of编码字符。因此,通常这些被忽略在严格的密文或他们被一个替代字符取代。

显然,如果引入了替代字符,那么这个特定的密文块将被解密成一个随机数据块,从而使您的CRC检查失败。

如果出于某种原因需要将密文显示为文本,则base64对其进行编码。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44342742

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档