【问题标题】:How to implement AES Encrypt (AesManaged Rfc2898DeriveBytes) in Windows Runtime如何在 Windows 运行时实现 AES 加密(AesManaged Rfc2898DeriveBytes)
【发布时间】:2015-04-07 16:53:14
【问题描述】:

当我尝试将我的项目从 Windows Phone Silverlight 8.1 迁移到 Windows 运行时时遇到了阻塞问题。 在 Windows 运行时,AES 加密的字符串与 Silverlight 之前的不同。

在 Silverlight 中:

    public static string EncryptAES(string encryptString)
    {
        AesManaged aes = null;
        MemoryStream ms = null;
        CryptoStream cs = null;

        string encryptKey = "testtest123";
        string salt = "abcabcabcd";
        try
        {
            Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(encryptKey, Encoding.UTF8.GetBytes(salt));

            aes = new AesManaged();
            aes.Key = rfc2898.GetBytes(aes.KeySize / 8);
            aes.IV = rfc2898.GetBytes(aes.BlockSize / 8);

            ms = new MemoryStream();
            cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write);

            byte[] data = Encoding.UTF8.GetBytes(encryptString);
            cs.Write(data, 0, data.Length);
            cs.FlushFinalBlock();

            return Convert.ToBase64String(ms.ToArray());
        }
        catch
        {
            return encryptString;
        }
        finally
        {
            if (cs != null)
                cs.Close();

            if (ms != null)
                ms.Close();

            if (aes != null)
                aes.Clear();
        }
    }

在 Windows 运行时:

    public static string EncryptAES(string plainText)
    {
        string pw = "testtest123";
        string salt = "abcabcabcd";
        IBuffer plainBuffer = CryptographicBuffer.ConvertStringToBinary(plainText, BinaryStringEncoding.Utf8);

        IBuffer saltBuffer = CryptographicBuffer.ConvertStringToBinary(salt, BinaryStringEncoding.Utf8);
        IBuffer pwBuffer = CryptographicBuffer.ConvertStringToBinary(pw, BinaryStringEncoding.Utf8);

        KeyDerivationAlgorithmProvider keyDerivationProvider = Windows.Security.Cryptography.Core.KeyDerivationAlgorithmProvider.OpenAlgorithm(KeyDerivationAlgorithmNames.Pbkdf2Sha256);
        // using salt and 1000 iterations
        KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(saltBuffer, 1000);

        // create a key based on original key and derivation parmaters
        CryptographicKey keyOriginal = keyDerivationProvider.CreateKey(pwBuffer);
        IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, 32);
        CryptographicKey derivedPwKey = keyDerivationProvider.CreateKey(pwBuffer);

        // derive buffer to be used for encryption salt from derived password key 
        IBuffer saltMaterial = CryptographicEngine.DeriveKeyMaterial(derivedPwKey, pbkdf2Parms, 16);

        // display the buffers - because KeyDerivationProvider always gets cleared after each use, they are very similar unforunately
        string keyMaterialString = CryptographicBuffer.EncodeToBase64String(keyMaterial);
        string saltMaterialString = CryptographicBuffer.EncodeToBase64String(saltMaterial);
        //AES_CBC_PKCS7
        SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
        // create symmetric key from derived password key
        CryptographicKey symmKey = symProvider.CreateSymmetricKey(keyMaterial);

        // encrypt data buffer using symmetric key and derived salt material
        IBuffer resultBuffer = CryptographicEngine.Encrypt(symmKey, plainBuffer, saltMaterial);
        string result = CryptographicBuffer.EncodeToBase64String(resultBuffer);
        return result;
    }

在 Silverlight Project 中,AES 加密的字符串“123456”为“4UfdhC/0MFQlMhl7N7gqLg==”; 在 Windows 运行时项目中,AES 加密的字符串是“jxsR5EuhPXgRsHLs4N3EGQ=="

那么如何在 WinRT 上获得与 Silverlight 上相同的字符串?

【问题讨论】:

    标签: windows-runtime cryptography windows-store-apps windows-phone-8.1 win-universal-app


    【解决方案1】:

    AES 类在 Microsoft 运行时默认为随机 IV。要获得相同的密文,您需要使用静态 IV。然而,这并不安全。相反,您应该只检查是否获得相同的密钥字节,并让每次运行的密文不同。否则你可以清楚地区分相同的明文。

    您似乎也使用了错误的哈希算法,Rfc2898DeriveBytes 使用 SHA-1 而不是 SHA-256 作为底层哈希函数。

    【讨论】:

    • 随时将我删除的答案包含在您的答案中。我希望有一个单一的正确答案,而不是我不完整的答案。
    • @vcsjones 完成 - 答案的 Rfc2898DeriveBytes 部分由 vcsjones 贡献:)
    • 我假设如果 OP 正在尝试生成哈希(因此 想要 相同的明文来生成相同的密文),他应该使用完全不同的算法?
    【解决方案2】:

    我创建了对我有用的类作为System.Security.Cryptography.Rfc2898DeriveBytes的替代品:

    public class Rfc2898DeriveBytes
    {
        private readonly string _password;
        private readonly byte[] _salt;
    
        public Rfc2898DeriveBytes(string password, byte[] salt)
        {
            _password = password;
            _salt = salt;
    
            IterationCount = 1000;
        }
    
        public uint IterationCount { get; set; }
    
        public byte[] GetBytes(uint cb)
        {
            var provider = KeyDerivationAlgorithmProvider.OpenAlgorithm(KeyDerivationAlgorithmNames.Pbkdf2Sha1);
    
            var buffSecret = CryptographicBuffer.ConvertStringToBinary(_password, BinaryStringEncoding.Utf8);
            var buffsalt = CryptographicBuffer.CreateFromByteArray(_salt);
    
            var keyOriginal = provider.CreateKey(buffSecret);
    
            var par = KeyDerivationParameters.BuildForPbkdf2(buffsalt, IterationCount);
            var keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, par, cb);
    
            byte[] result;
            CryptographicBuffer.CopyToByteArray(keyMaterial, out result);
    
            return result;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-29
      • 1970-01-01
      • 2015-01-29
      相关资源
      最近更新 更多