代码之家  ›  专栏  ›  技术社区  ›  Nil Pun

什么是AES 256错误意味着填充无效且无法删除?

  •  -1
  • Nil Pun  · 技术社区  · 6 年前

    首先,我看到了一些关于“填充无效且不能删除”的问题。我看了他们所有人,我的问题是安静的不同。

    我使用下面的代码,我可以从PS脚本加密数据和从.NET应用程序解密。

    但是,当我尝试在.NET/PS脚本上加密文本并尝试在下面的站点上解密时,它不起作用。

    https://aesencryption.net/

    当我尝试将此站点上的加密数据解密到PS或.NET代码(使用相同的密钥)时,我不断遇到以下错误: “填充无效,无法删除。”

    /// <summary>
        /// AES wrapper implementation by Yovav Gad using the AesManaged algorithm.
        /// <para>http://en.wikipedia.org/wiki/Advanced_Encryption_Standard</para>
        /// </summary>
        public sealed class AesWrapper
        {
            /// <summary>
            /// Create a SymmetricAlgorithm using AesManaged
            /// </summary>
            /// <param name="key">Byte array representing the key values, please note, 
            /// for better performance, use Convert.FromBase64String() outside of this method.</param>
            /// <param name="blockSize">BlockSize, default is 128</param>
            /// <param name="paddingMode">PaddingMode, default is PaddingMode.PKCS7</param>
            /// <param name="cipherMode">CipherMode, default is CipherMode.CBC</param>
            /// <returns></returns>
            private static SymmetricAlgorithm CreateCrypto(
                byte[] key,
                int blockSize = 128,
                PaddingMode paddingMode = PaddingMode.PKCS7,
                CipherMode cipherMode = CipherMode.CBC
                )
            {
                SymmetricAlgorithm crypto = new AesManaged
                {
                    Key = key,
                    Mode = cipherMode,
                    Padding = paddingMode,
                    BlockSize = blockSize
                };
    
                crypto.IV = new byte[crypto.IV.Length];
    
                return (crypto);
            }
    
            /// <summary>
            /// Decrypt an encrypted string using a specific key.
            /// </summary>
            /// <param name="str">String to decrypt</param>
            /// <param name="key">Byte array representing the key values, please note, 
            /// for better performance, use Convert.FromBase64String() outside of this method.</param>
            /// <param name="blockSize">BlockSize, default is 128</param>
            /// <param name="paddingMode">PaddingMode, default is PaddingMode.Zeros</param>
            /// <param name="cipherMode">CipherMode, default is CipherMode.CBC</param>
            /// <returns></returns>
            [DebuggerStepThrough()]
            public static string Decrypt(
                string str,
                byte[] key,
                int blockSize = 128,
                PaddingMode paddingMode = PaddingMode.PKCS7,
                CipherMode cipherMode = CipherMode.CBC
                )
            {
                if (str == null || str.Length < 1 ||
                    key == null || key.Length < 1)
                {
                    return null;
                }
    
                var result = string.Empty;
    
                using (var crypto = CreateCrypto(key, blockSize, paddingMode, cipherMode))
                {
                    var strCombined = Convert.FromBase64String(str);
                    var iv = new byte[crypto.BlockSize / 8];
                    var cipherText = new byte[strCombined.Length - iv.Length];
                    Array.Copy(strCombined, iv, iv.Length);
                    Array.Copy(strCombined, iv.Length, cipherText, 0, cipherText.Length);
    
                    crypto.IV = iv;
                    ICryptoTransform decryptor = crypto.CreateDecryptor(key, iv);
    
                    using (var msDecrypt = new MemoryStream(cipherText))
                    {
                        using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                        {
                            using (var srDecrypt = new StreamReader(csDecrypt))
                            {
                                result = srDecrypt.ReadToEnd();
                            }
                        }
                    }
    
                    if (paddingMode == PaddingMode.PKCS7)
                    {
                        // This is required when using PaddingMode.Zeros for values shorted than the block size.
                        // Note: using .TrimEnd('\0') to remove nulls and not .TrimEnd("\0") to allow the string values.
                        result = result.TrimEnd('\0');
                    }
    
                    return (result);
                }
            }
    
            /// <summary>
            /// Encrypt a string using a specific key.
            /// </summary>
            /// <param name="str">String to encrypt</param>
            /// <param name="key">Byte array representing the key values, please note, 
            /// for better performance, use Convert.FromBase64String() outside of this method.</param>
            /// <param name="blockSize">BlockSize, default is 128</param>
            /// <param name="paddingMode">PaddingMode, default is PaddingMode.Zeros</param>
            /// <param name="cipherMode">CipherMode, default is CipherMode.CBC</param>
            /// <returns></returns>
            [DebuggerStepThrough()]
            public static string Encrypt(
                string str,
                byte[] key,
                int blockSize = 128,
                PaddingMode paddingMode = PaddingMode.PKCS7,
                CipherMode cipherMode = CipherMode.CBC
                )
            {
                if (str == null || str.Length < 1 ||
                    key == null || key.Length < 1)
                {
                    return null;
                }
    
                byte[] encryptedData;
    
                using (SymmetricAlgorithm crypto = CreateCrypto(key, blockSize, paddingMode, cipherMode))
                {
                    byte[] data;
                    crypto.GenerateIV();
                    var iv = crypto.IV;
                    var encryptor = crypto.CreateEncryptor(key, iv);
    
                    using (MemoryStream ms = new MemoryStream())
                    {
                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            using (StreamWriter sw = new StreamWriter(cs))
                            {
                                sw.Write(str);
                            }
    
                            data = ms.ToArray();
                        }
                    }
    
                    // Combine the iv (salt) and the encrypted data
                    encryptedData = new byte[iv.Length + data.Length];
                    Array.Copy(iv, 0, encryptedData, 0, iv.Length);
                    Array.Copy(data, 0, encryptedData, iv.Length, data.Length);
                }
    
                return Convert.ToBase64String(encryptedData);
            }
        }
    
    
    void Main()
    {
        var keyString = "8CBaNtMYwAuu2K/xleoRfgPkURaLK82QidlIyg+nFY4=";
        var keyBytes = Convert.FromBase64String(keyString); 
        var plainText = "aes test";
        
        var testEncrypted = AesWrapper.Encrypt(plainText, keyBytes);
        Console.WriteLine(testEncrypted);
        var testDecrypted = AesWrapper.Decrypt("gM+oae1MZlj42b9UtCw2dw==", keyBytes);
        Console.WriteLine(testDecrypted);
        var testReEncrypted = AesWrapper.Encrypt(testEncrypted, keyBytes);
    }
    

    PS脚本

        function Create-AesManagedObject($key, $IV) {
        $aesManaged = New-Object "System.Security.Cryptography.AesManaged"
        $aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
        $aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
        $aesManaged.BlockSize = 128
        $aesManaged.KeySize = 256
        if ($IV) {
            if ($IV.getType().Name -eq "String") {
                $aesManaged.IV = [System.Convert]::FromBase64String($IV)
            }
            else {
                $aesManaged.IV = $IV
            }
        }
        if ($key) {
            if ($key.getType().Name -eq "String") {
                $aesManaged.Key = [System.Convert]::FromBase64String($key)
            }
            else {
                $aesManaged.Key = $key
            }
        }
        $aesManaged
    }
    
    function Create-AesKey() {
        $aesManaged = Create-AesManagedObject
        $aesManaged.GenerateKey()
        [System.Convert]::ToBase64String($aesManaged.Key)
    }
    
    function Encrypt-String($key, $unencryptedString) {
        $bytes = [System.Text.Encoding]::UTF8.GetBytes($unencryptedString)
        $aesManaged = Create-AesManagedObject $key
        $encryptor = $aesManaged.CreateEncryptor()
        $encryptedData = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length);
        [byte[]] $fullData = $aesManaged.IV + $encryptedData
        $aesManaged.Dispose()
        [System.Convert]::ToBase64String($fullData)
    }
    
    function Decrypt-String($key, $encryptedStringWithIV) {
        $bytes = [System.Convert]::FromBase64String($encryptedStringWithIV)
        $IV = $bytes[0..15]
        $aesManaged = Create-AesManagedObject $key $IV
        $decryptor = $aesManaged.CreateDecryptor();
        $unencryptedData = $decryptor.TransformFinalBlock($bytes, 16, $bytes.Length - 16);
        $aesManaged.Dispose()
        [System.Text.Encoding]::UTF8.GetString($unencryptedData).Trim([char]0)
    }
    
    
    cls
    
    <#
    # This will generate a new valid AES 256 key if needed:
    # $key = Create-AesKey
    #>
    
    <# 
    # This is the hard coded key
    #>
    $key = Create-AesKey
    #$key = "8CBaNtMYwAuu2K/xleoRfgPkURaLK82Q"
    Write-Host "key = $key"
    
    $unencryptedString = "dil pun"
    Write-Host "unencryptedString = $unencryptedString"
    
    $encryptedString = Encrypt-String $key $unencryptedString
    Write-Host "encryptedString  = $encryptedString "
    
    $backToPlainText = Decrypt-String $key $encryptedString
    Write-Host "backToPlainText = $backToPlainText"
    
    
    <#
    # To run this PowerShell script:
    #
    # In Windows PowerShell:
    # .\PowerShell_AES_Encryption_Example.ps1
    # C:\Test\PowerShell_AES_Encryption_Example.ps1
    # 
    # In Command Prompt:
    # powershell -noexit "& ""C:\Test\PowerShell_AES_Encryption_Example.ps1"""
    #>
    

    你知道为什么这段代码不能解密被加密的数据吗 https://aesencryption.net/ 使用相同的键,反之亦然?

    双方到底需要匹配什么呢?例如键大小、键值、填充和模式。

    静脉注射等是否需要匹配?

    谢谢。

    0 回复  |  直到 6 年前
        1
  •  1
  •   Robert    6 年前

    双方到底需要匹配什么

    对于AES,您必须使用完全相同的值进行加密和解密:

    • 键(打印为十六进制键并进行比较)
    • IV(用于加密的16字节随机数据,用于解密的使用与用于加密的相同的字节)。通常的方法是在加密数据前加上IV,并在执行实际解密之前读取它。
    • 加密模式(这里是CBC)
    • 衬垫
    推荐文章