0

我一直在与链式 using 语句作斗争,并且无法解决一长串实施问题中的最新问题。我需要压缩,然后加密生成的 IV 并将其附加到选定的文件中。这一切似乎都正常工作,但是我无法解除这个过程。在查看了几个类似的堆栈帖子和文章后,我仍然无法让它工作,现在正在寻求更直接的帮助。

最新抛出的错误是System.IO.InvalidDataException: 'Found invalid data while decoding.'解密流似乎没有按预期运行,这使解压缩流变得异常。

byte[] key;
byte[] salt;
const int keySize = 256;
const int blockSize = keySize;
byte[] iv = new byte[blockSize / 8];//size to bits
RijndaelManaged rjndl;
RNGCryptoServiceProvider cRng;

void InitializeCryptor() {
    //Temporarily define the salt & key
    salt = Encoding.UTF8.GetBytes("SaltShouldBeAtLeast8Bytes");
    key = new Rfc2898DeriveBytes("MyL0ngPa$$phra$e", salt, 4).GetBytes(keySize / 8);

    //Initialize the crypto RNG generator
    cRng = new RNGCryptoServiceProvider();

    // Create instance of Rijndael (AES) for symetric encryption of the data.
    rjndl = new RijndaelManaged();
    rjndl.KeySize = keySize;
    rjndl.BlockSize = blockSize;
    rjndl.Mode = CipherMode.CBC;
}

void CompressAndEncryptFile(string relativeFilePath, string fileName) {
    //Create a unique IV each time
    cRng.GetBytes(iv);

    //Create encryptor
    rjndl.Key = key;
    rjndl.IV = iv;
    ICryptoTransform encryptor = rjndl.CreateEncryptor(rjndl.Key, rjndl.IV);

    //Create file specific output sub-directory
    Directory.CreateDirectory(Path.Combine(outputPath, relativeFilePath));

    //Read and compress file into memory stream
    using (FileStream readStream = File.OpenRead(Path.Combine(initialpath, relativeFilePath, fileName)))
            using (FileStream writeStream = new FileStream(Path.Combine(outputPath, relativeFilePath, fileName + ".dat"), FileMode.Create))
    using (CryptoStream encryptStream = new CryptoStream(writeStream, encryptor, CryptoStreamMode.Write))
    using (DeflateStream compStream = new DeflateStream(encryptStream, CompressionLevel.Optimal)) {
        //Write the following to the FileStream for the encrypted file:
        // - length of the IV
        // - the IV
        byte[] ivSize = BitConverter.GetBytes(rjndl.IV.Length);
        writeStream.Write(ivSize, 0, 4);
        writeStream.Write(rjndl.IV, 0, rjndl.BlockSize / 8);

        readStream.CopyTo(compStream);
    }
}

void DecryptAndDecompressFile(string relativeFilePath) {
    string outputPath = Path.Combine(initialpath, "Unpack");
    Directory.CreateDirectory(outputPath);

    using (FileStream readStream = new FileStream(Path.Combine(initialpath, manifestData.version, relativeFilePath + ".dat"), FileMode.Open)) {
        byte[] tmpLength = new byte[4];

        //Read length of IV
        readStream.Seek(0, SeekOrigin.Begin);
        readStream.Read(tmpLength, 0, 3);

        int ivLength = BitConverter.ToInt32(tmpLength, 0);

        byte[] readIv = new byte[ivLength];

        //Read IV
        readStream.Seek(4, SeekOrigin.Begin);
        readStream.Read(readIv, 0, ivLength);
        rjndl.IV = readIv;

        //Start at beginning of encrypted data
        readStream.Seek(4 + ivLength, SeekOrigin.Begin);

        //Create decryptor
        ICryptoTransform decryptor = rjndl.CreateEncryptor(key, readIv);
        using (CryptoStream decryptStream = new CryptoStream(readStream, decryptor, CryptoStreamMode.Read))
        using (DeflateStream decompStream = new DeflateStream(decryptStream, CompressionMode.Decompress))
        using (FileStream writeStream = new FileStream(Path.Combine(outputPath, relativeFilePath), FileMode.Create)) {
            decompStream.CopyTo(writeStream);
        }
    }
}

对于那些喜欢指出其他类似堆栈问题并在不提供支持的情况下投票关闭/复制的人,以下是我首先处理的线程和帖子,每个都没有成功。 https://docs.microsoft.com/en-us/dotnet/standard/security/walkthrough-creating-a-cryptographic-application https://docs.microsoft.com/en-us/dotnet/api/system.security .cryptography.rijndaelmanaged?redirectedfrom=MSDN&view=netcore-3.1 链接 GZipStream/DeflateStream 和 CryptoStream (AES) 在读取 DeflateStream/GZipStream 到 CryptoStream 时中断,反之亦然 https://docs.microsoft.com/en-us/dotnet/api/ system.io.compression.gzipstream?redirectedfrom=MSDN&view=netcore-3.1#code-snippet-2 如何修复“解码时发现无效数据”。 使用 C# 压缩/解压缩字符串

4

1 回答 1

0

经过大约 2 天的调查,我找到了我的错误。

我打电话rjndl.CreateEncryptor而不是rjndl.CreateDecryptor在解密部分...(请告诉我这种类型的 $#!t 也发生在其他人身上)

一旦我完成测试,我将更新我的问题代码,以作为未来通过谷歌登陆这里的任何人的一个很好的例子。

于 2020-07-02T16:30:59.977 回答