【问题标题】:Can't decrypt video using C# and Rijndael无法使用 C# 和 Rijndael 解密视频
【发布时间】:2013-02-15 01:16:55
【问题描述】:

我无法解密使用 Rijndael 加密的视频文件。看看我的加密程序:

  using (FileStream _streamInput = new FileStream(inputPath,FileMode.Open,FileAccess.Read)) {
            using (FileStream _streamOutput = new FileStream(outputPath,FileMode.Create,FileAccess.Write)) {
                RijndaelManaged _cryptoRM = new RijndaelManaged();
                UnicodeEncoding _encodingUnicode = new UnicodeEncoding();
                byte[] _key = _encodingUnicode.GetBytes(String.IsNullOrEmpty(customPassword)?_mediaPass:customPassword);
                using (CryptoStream _streamCrypto = new CryptoStream(_streamOutput,
                                                                     _cryptoRM.CreateEncryptor(_key,_key),
                                                                     CryptoStreamMode.Write)) {
                    long _bufferLength = _streamInput.Length;

                    if (_bufferLength>_encryptedBlock) {
                        byte[] _encryptedBuffer        = new byte[_encryptedBlock];
                        byte[] _unencryptedBufferBlock = new byte[_encryptedBlock];

                        // encrypted block
                        _streamInput.Read(_encryptedBuffer,0,(int)_encryptedBlock);
                        _streamCrypto.Write(_encryptedBuffer,0,(int)_encryptedBlock);

                        // rest
                        int _readBytesCount = 0;
                        while ((_readBytesCount=_streamInput.Read(_unencryptedBufferBlock,0,_encryptedBlock))!=0) {
                            _streamOutput.Write(_unencryptedBufferBlock,0,(int)_readBytesCount);
                        }
                    }
                    _streamCrypto.Dispose();
                }
                _cryptoRM.Dispose();
                _streamOutput.Dispose();
            }
            _streamInput.Dispose();
        }

这是我的解密程序:

        using (FileStream _streamInput = new FileStream(inputPath, FileMode.Open, FileAccess.Read))
        {
            using (FileStream _streamOutput = new FileStream(outputPath, FileMode.Create, FileAccess.Write))
            {
                 RijndaelManaged _cryptoRM = new RijndaelManaged();
                 UnicodeEncoding _encodingUnicode = new UnicodeEncoding();
                 byte[] _key = _encodingUnicode.GetBytes(PrepareEncryptionKey(String.IsNullOrEmpty(customPassword)?_mediaPass:customPassword,""));


                try
                {

                        using (CryptoStream _streamCrypto = new CryptoStream(_streamInput, _cryptoRM.CreateDecryptor(_key, _key), CryptoStreamMode.Read))
                        {
                            try
                            {
                                int _readBytesCount = 0;


                                //encrypted block
                                byte[] _buffer = new byte[_encryptedBlock];
                                byte[] _bufferUnencrypted = new byte[_encryptedBlock];

                                int decrypt_length = _streamCrypto.Read(_buffer, 0, _encryptedBlock);                                   
                                _streamOutput.Write(_buffer, 0, decrypt_length);

                                // rest
                                while ((_readBytesCount = _streamInput.Read(_bufferUnencrypted, 0, _encryptedBlock)) != 0)
                                {
                                    _streamOutput.Write(_bufferUnencrypted, 0, _readBytesCount);
                                }
                            }
                            catch { }
                            _streamCrypto.Dispose();
                        }

                }
                catch { }
                _cryptoRM.Dispose();
                _streamOutput.Dispose();
            }
            _streamInput.Dispose();
        }

其他要点: - 没有错误被抛出,但视频根本没有播放。 - 解密文件的大小与加密文件的大小相同。

编辑

 private static string PrepareEncryptionKey(string key, string part)
    {
        if (part == "")
        {
            if (key.Length != 8)
            {
                return key.PadRight(8, '~');
            }
            else
            {
                return key;
            }
        }
        else
        {
            if (key.Length != (8 - part.Length))
            {
                if (key.Length > (8 - part.Length))
                {
                    return key.Substring(0, (8 - part.Length)) + part;
                }
                else
                {
                    return key.PadRight((8 - part.Length), '~') + part;
                }
            }
            else
            {
                return key + part;
            }
        }
    }

【问题讨论】:

  • 你说大小一样,那内容呢?如果您将加密前的输入与解密后的结果进行比较?是一样的还是不一样的?
  • 尝试设置_streamInput.Position = 0;
  • 我还没有真正评估过内容。两个文件(加密和“解密”)都无法播放。
  • _streamInput.Position 没有帮助。如果您检查代码,您会在加密期间看到只有第一个块被加密。
  • 1) 您没有检查Read 的返回值。由于您的长度检查,它可能有效,但我不确定它是否保证有效。 2)您将密码直接用作密钥和IV 3)您没有加密文件,只有部分文件看起来不太安全。 4) 由于填充,密文比明文长。我认为您的代码没有考虑到这一点。您需要禁用填充

标签: c# video encryption rijndael rijndaelmanaged


【解决方案1】:

看来你的两种方法都需要修复:

1/ 加密部分 - 您不能将输出数据直接写入 _streamOutput,而是写入 _streamCrypto。否则,您将准确地写出您从输入文件中获取的内容。根据您的原始代码,您只需加密第一个数据块。

while ((_readBytesCount = _streamInput.Read(_unencryptedBufferBlock, 0, encryptedBlockSize)) != 0)
{
    _streamCrypto.Write(_unencryptedBufferBlock, 0, (int)_readBytesCount);
}

2/ 解密部分 - 您不能直接从输入流中读取,而是从 _streamCrypto 中读取

while ((_readBytesCount = _streamCrypto.Read(_bufferUnencrypted, 0, encryptedBlockSize)) != 0)
{
    _streamOutput.Write(_bufferUnencrypted, 0, _readBytesCount);
}

3/ PrepareEncryptionKey 方法应在加密和解密方法中使用。这将确保您在两种方法中都具有相同的效果。

【讨论】:

  • 1.这正是代码的意图:只加密第一个块。问题是我无法解密。尝试使用上面的加密方法对文件进行解密,然后尝试对其进行解密。我有一些文件已经用这种方法加密,但我需要解密它们。无论如何,谢谢你的帮助。
  • 好的,那我再尝试加密一个,检查加密后大小是否相同,你的解密方法是否正确解密。您可以比较原始文件和解密后收到的文件。如果它们不同,您要么使用不同的键/IV 组合,要么在您需要调试的代码中有错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 2012-11-18
  • 2010-11-03
  • 2012-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多