You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell加密文件后.NET解密报错:输入数据不是完整块

AES解密时抛出“输入数据不是完整块”异常分析

使用PowerShell的AES加密脚本生成加密文件后,.NET 4.8解密函数在关闭CryptoStream时抛出异常:

System.Security.Cryptography.CryptographicException: 'The input data is not a complete block.'

加密脚本(PowerShell)

function Protect-File {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [string]$FileName,
        [Parameter(Mandatory=$true, Position=2)]
        [string]$KeyAsPlainText
    )

    $Algorithm = 'AES'
    $CipherMode = 'CBC'
    $PaddingMode = 'PKCS7'

    try {
        $Crypto = [System.Security.Cryptography.SymmetricAlgorithm]::Create($Algorithm)
        $Crypto.Key = [System.Convert]::FromBase64String($KeyAsPlainText)
        $Crypto.GenerateIV() 
   
        $Crypto.Mode = $CipherMode
        $Crypto.Padding = $PaddingMode

        $DestinationFile = $FileName + ".encrypted"

        $Transform = $Crypto.CreateEncryptor()
        $CryptoStream = New-Object System.Security.Cryptography.CryptoStream(
            [System.IO.File]::OpenWrite($DestinationFile),
            $Transform,
            [System.Security.Cryptography.CryptoStreamMode]::Write
        )

        try {
            try {
                $FileStreamReader = [System.IO.File]::OpenRead($FileName)
                $FileStreamReader.CopyTo($CryptoStream)
            } finally {
                $FileStreamReader.Close()
            }
        } finally {
            $CryptoStream.Close()
        }

        # Write IV to the beginning of the encrypted file
        $FileStreamWriter = [System.IO.File]::OpenWrite($DestinationFile)
        $FileStreamWriter.Seek(0, [System.IO.SeekOrigin]::Begin)
        $FileStreamWriter.Write($Crypto.IV, 0, $Crypto.IV.Length)
        $FileStreamWriter.Close()

        Write-Output "File encrypted successfully: $DestinationFile"
    } catch {
        Write-Error $_
    }
}

Protect-File -Filename "D:\Temp\temp.txt" -KeyAsPlainText "r4EoMu6hxWHlsFgizGf3L2WIEJwwVFIUrADdCU4U9xA="

原解密函数(.NET 4.8)

public static bool UnprotectFile(string sourceFile, string destinationFile, string keyAsPlainText)
{
    try
    {
        byte[] encryptionKey = Convert.FromBase64String(keyAsPlainText);

        // Read IV from the beginning of the encrypted file
        using (FileStream fileStream = File.OpenRead(sourceFile))
        {
            byte[] iv = new byte[16];
            fileStream.Read(iv, 0, iv.Length);

            // Configure encryption algorithm
            Aes crypto = Aes.Create();
            crypto.Key = encryptionKey;
            crypto.IV = iv;
            crypto.Mode = CipherMode.CBC;
            crypto.Padding = PaddingMode.PKCS7;

            // Decrypt the file
            using (ICryptoTransform transform = crypto.CreateDecryptor())
            {
                using (CryptoStream cryptoStream = new CryptoStream(
                    File.OpenWrite(destinationFile),
                    transform,
                    CryptoStreamMode.Write
                ))
                {
                    using (FileStream fileStreamReader = File.OpenRead(sourceFile))
                    {
                        fileStreamReader.CopyTo(cryptoStream);
                    }
                }
            }

            return true;
        } 
        // catch block removed
    }
    catch(Exception ex)
    {
        // 异常处理
        return false;
    }
}

异常成因

  1. 加密文件结构:PowerShell脚本先写入加密后的文件内容,再将16字节的IV写入文件开头,最终加密文件结构为:[IV(16字节)] + [实际加密数据]。
  2. 解密代码逻辑错误:解密时,代码先读取了开头的16字节IV,但随后重新打开整个加密文件(包含IV),将全部内容传入CryptoStream进行解密。这相当于把IV也当成了加密数据的一部分处理,导致解密输入的总长度比实际加密数据多了16字节,破坏了AES CBC模式的块对齐要求(AES块大小为16字节),最终抛出“输入数据不是完整块”的异常。

修复后的解密函数

修正读取文件的逻辑,跳过开头的IV部分,只读取实际加密数据:

public static bool UnprotectFile(string sourceFile, string destinationFile, string keyAsPlainText)
{
    try
    {
        byte[] encryptionKey = Convert.FromBase64String(keyAsPlainText);

        using (FileStream fileStream = File.OpenRead(sourceFile))
        {
            byte[] iv = new byte[16];
            // 读取IV
            int bytesRead = fileStream.Read(iv, 0, iv.Length);
            if (bytesRead != iv.Length)
            {
                // IV读取失败,处理异常
                return false;
            }

            Aes crypto = Aes.Create();
            crypto.Key = encryptionKey;
            crypto.IV = iv;
            crypto.Mode = CipherMode.CBC;
            crypto.Padding = PaddingMode.PKCS7;

            using (ICryptoTransform transform = crypto.CreateDecryptor())
            {
                using (CryptoStream cryptoStream = new CryptoStream(
                    File.OpenWrite(destinationFile),
                    transform,
                    CryptoStreamMode.Write
                ))
                {
                    // 跳过IV,复制剩余的加密数据到CryptoStream
                    fileStream.CopyTo(cryptoStream);
                }
            }

            return true;
        }
    }
    catch (Exception ex)
    {
        // 添加异常处理逻辑
        return false;
    }
}

内容的提问来源于stack exchange,提问作者Optimum8

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 00:57:09