c# Rijndael加密将额外的字节放在解密文件的前面

本文关键字:解密 文件 前面 字节 加密 Rijndael | 更新日期: 2023-09-27 18:08:41

我正试图使用Rijndael加密加密图像文件,我必须做错了什么,因为解密的文件在文件的前面出现了额外的数据,任何可能在最后有一点额外的数据。我对这个加密算法相当陌生,所以我很确定我只是错过了一些简单的东西。

使用文本文件的例子

输入文件

"the quick brown fox jumped over the lazy yellow dog"

当我尝试将生成的IV放在文件的前面时的输出文件('0=null)

"ÚñjÐæƒÊW®ï¡_Ü&ßthe'0 quick brown fox jumped over the lazy yellow dog"

输出文件,当我试图把一个IV等于我的键在前面

"'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0the'0'0'0'0'0'0 quick brown fox jumped over the lazy yellow dog"

当我使用等于我的Key的IV并且在文件

前面没有任何内容时的输出文件
"'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0the'0'0'0'0'0'0 quick brown fox jumped over the lazy yellow dog"

private RijndaelManaged GetCipher(byte[] key, bool forEncrypt)
{
    RijndaelManaged rijndaelCipher;
    rijndaelCipher = new RijndaelManaged();
    rijndaelCipher.Mode = CipherMode.CBC;
    rijndaelCipher.Padding = PaddingMode.PKCS7;
    rijndaelCipher.KeySize = 0x80;
    rijndaelCipher.BlockSize = 0x80;
    rijndaelCipher.Key = key;
   /* if (forEncrypt)
        rijndaelCipher.GenerateIV();
    else
    rijndaelCipher.IV = new byte[16];*/
    rijndaelCipher.IV = _imageKey;
    return rijndaelCipher;
}
public void DecryptStamp(Stamp stampToDecrypt, string decrpytedStampFilePath)
{
    RijndaelManaged rijndaelCipher;
    FileStream inputStream = null;
    FileStream outputStream = null;
    CryptoStream encryptSteam = null;
    byte[] block;
    int numberRead;
    ICryptoTransform transform;
    if (!File.Exists(stampToDecrypt.Path))
        throw new FileNotFoundException(stampToDecrypt.Path + " does not exist");
    rijndaelCipher = this.GetCipher(_imageKey, false);
    block = new byte[16];
    try
    {
        inputStream = File.Open(stampToDecrypt.Path, FileMode.Open, FileAccess.Read);
        outputStream = File.Open(decrpytedStampFilePath, FileMode.Create, FileAccess.Write);
        //inputStream.Read(rijndaelCipher.IV, 0, rijndaelCipher.IV.Length);
        transform = rijndaelCipher.CreateDecryptor();                     
        encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
        while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
        {
            Console.WriteLine(numberRead.ToString());
            encryptSteam.Write(block, 0, numberRead);
        }
    }
    finally
    {
        rijndaelCipher.Clear();
        rijndaelCipher.Dispose();
        if (encryptSteam != null)
            encryptSteam.Dispose();
        if (outputStream != null)
            outputStream.Dispose();
        if (inputStream != null)
            inputStream.Dispose();
    }
}
public Stamp EncryptStampToStampFolder(string stampFileToEncrpyt)
{
    Configuration config;
    Stamp stampToEncrypt;
    RijndaelManaged rijndaelCipher;
    string encryptedFilePath;
    if (!File.Exists(stampFileToEncrpyt))
        throw new FileNotFoundException(stampFileToEncrpyt + " does not exist");
    config = Configuration.GetProgramInstance();
    encryptedFilePath = Path.Combine(config.StampFolder, Path.GetFileNameWithoutExtension(stampFileToEncrpyt) + ".stmp");
    stampToEncrypt = new Stamp(Path.GetFileNameWithoutExtension(stampFileToEncrpyt), encryptedFilePath);
    rijndaelCipher = this.GetCipher(_imageKey, true);
    ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
    FileStream inputStream = null;
    FileStream outputStream = null;
    CryptoStream encryptSteam = null;
    byte[] block = new byte[16];
    int numberRead;
    try
    {
        inputStream = File.Open(stampFileToEncrpyt, FileMode.Open, FileAccess.Read);
        outputStream = File.Open(encryptedFilePath, FileMode.Create, FileAccess.Write);
        //outputStream.Write(rijndaelCipher.IV, 0, 16);
        encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
        encryptSteam.Write(block, 0, block.Length);
        while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
        {
            encryptSteam.Write(block, 0, numberRead);
        }
    }
    finally
    {
        rijndaelCipher.Clear();
        rijndaelCipher.Dispose();
        if (encryptSteam != null)
            encryptSteam.Dispose();
        if (outputStream != null)
            outputStream.Dispose();
        if (inputStream != null)
            inputStream.Dispose();
    }
    return stampToEncrypt;
}
public struct Stamp
{
    public string Name,
        Path;
    public Stamp(string StampName, string StampPath)
    {
        Name = StampName;
        Path = StampPath;
    }
}

CODE post fix

private RijndaelManaged GetCipher(byte[] key, bool forEncrypt)
{
    RijndaelManaged rijndaelCipher;
    rijndaelCipher = new RijndaelManaged();
    rijndaelCipher.Mode = CipherMode.CBC;
    rijndaelCipher.Padding = PaddingMode.PKCS7;
    rijndaelCipher.KeySize = 0x80;
    rijndaelCipher.BlockSize = 0x80;
    rijndaelCipher.Key = key;
    if (forEncrypt)
        rijndaelCipher.GenerateIV();
    else
        rijndaelCipher.IV = new byte[16];
    //rijndaelCipher.IV = _imageKey;
    return rijndaelCipher;
}
public void DecryptStamp(Stamp stampToDecrypt, string decrpytedStampFilePath)
{
    RijndaelManaged rijndaelCipher;
    FileStream inputStream = null;
    FileStream outputStream = null;
    CryptoStream encryptSteam = null;
    byte[] block;
    int numberRead;
    ICryptoTransform transform;
    if (!File.Exists(stampToDecrypt.Path))
        throw new FileNotFoundException(stampToDecrypt.Path + " does not exist");
    rijndaelCipher = this.GetCipher(_imageKey, false);
    block = new byte[16];
    try
    {
        inputStream = File.Open(stampToDecrypt.Path, FileMode.Open, FileAccess.Read);
        outputStream = File.Open(decrpytedStampFilePath, FileMode.Create, FileAccess.Write);
        inputStream.Read(rijndaelCipher.IV, 0, rijndaelCipher.IV.Length);
        transform = rijndaelCipher.CreateDecryptor();                     
        encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
        while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
        {                
            encryptSteam.Write(block, 0, numberRead);
        }
    }
    finally
    {
        rijndaelCipher.Clear();
        rijndaelCipher.Dispose();
        if (encryptSteam != null)
            encryptSteam.Dispose();
        if (outputStream != null)
            outputStream.Dispose();
        if (inputStream != null)
            inputStream.Dispose();
    }
}
public Stamp EncryptStampToStampFolder(string stampFileToEncrpyt)
{
    Configuration config;
    Stamp stampToEncrypt;
    RijndaelManaged rijndaelCipher;
    string encryptedFilePath;
    if (!File.Exists(stampFileToEncrpyt))
        throw new FileNotFoundException(stampFileToEncrpyt + " does not exist");
    config = Configuration.GetProgramInstance();
    encryptedFilePath = Path.Combine(config.StampFolder, Path.GetFileNameWithoutExtension(stampFileToEncrpyt) + ".stmp");
    stampToEncrypt = new Stamp(Path.GetFileNameWithoutExtension(stampFileToEncrpyt), encryptedFilePath);
    rijndaelCipher = this.GetCipher(_imageKey, true);
    ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
    FileStream inputStream = null;
    FileStream outputStream = null;
    CryptoStream encryptSteam = null;
    byte[] block = new byte[16];
    int numberRead;
    try
    {
        inputStream = File.Open(stampFileToEncrpyt, FileMode.Open, FileAccess.Read);
        outputStream = File.Open(encryptedFilePath, FileMode.Create, FileAccess.Write);
        outputStream.Write(rijndaelCipher.IV, 0, 16);
        encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
        //encryptSteam.Write(block, 0, block.Length); this line was the problem in the orginal code
        while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
        {
            encryptSteam.Write(block, 0, numberRead);
        }
    }
    finally
    {
        rijndaelCipher.Clear();
        rijndaelCipher.Dispose();
        if (encryptSteam != null)
            encryptSteam.Dispose();
        if (outputStream != null)
            outputStream.Dispose();
        if (inputStream != null)
            inputStream.Dispose();
    }
    return stampToEncrypt;
}
public struct Stamp
{
    public string Name,
        Path;
    public Stamp(string StampName, string StampPath)
    {
        Name = StampName;
        Path = StampPath;
    }
}

新代码的输出

"7p¶¼oò¾½G€¢9±hfox'0'0跳过懒惰的黄狗"

c# Rijndael加密将额外的字节放在解密文件的前面

问题有三个方面。1)在加密过程中写入额外数据2)文件开头的IV被覆盖3)解密时IV没有被正确读取

代码固定

private RijndaelManaged GetCipher(byte[] key, bool forEncrypt)
{
    RijndaelManaged rijndaelCipher;
    rijndaelCipher = new RijndaelManaged();
    rijndaelCipher.Mode = CipherMode.CBC;
    rijndaelCipher.Padding = PaddingMode.PKCS7;
    rijndaelCipher.KeySize = 0x80;
    rijndaelCipher.BlockSize = 0x80;
    rijndaelCipher.Key = key;
    if (forEncrypt)
        rijndaelCipher.GenerateIV();
    else
        rijndaelCipher.IV = new byte[16];
    //rijndaelCipher.IV = _imageKey;
    return rijndaelCipher;
}
public void DecryptStamp(Stamp stampToDecrypt, string decrpytedStampFilePath)
{
    RijndaelManaged rijndaelCipher;
    FileStream inputStream = null;
    FileStream outputStream = null;
    CryptoStream encryptSteam = null;
    byte[] block;
    int numberRead;
    ICryptoTransform transform;
    if (!File.Exists(stampToDecrypt.Path))
        throw new FileNotFoundException(stampToDecrypt.Path + " does not exist");
    rijndaelCipher = this.GetCipher(_imageKey, false);
    block = new byte[16];
    try
    {
        inputStream = File.Open(stampToDecrypt.Path, FileMode.Open, FileAccess.Read);
        outputStream = File.Open(decrpytedStampFilePath, FileMode.Create, FileAccess.Write);
        //This line was wrong because rijndaelCipher.IV never filled
        //inputStream.Read(rijndaelCipher.IV, 0, rijndaelCipher.IV.Length); 
        inputStream.Read(block, 0, block.Length);
        rijndaelCipher.IV = block;
        block = new byte[16];
        transform = rijndaelCipher.CreateDecryptor();                     
        encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write);
        while ((numberRead = inputStream.Read(block, 0, block.Length)) > 0)
        {                
            encryptSteam.Write(block, 0, numberRead);
        }
    }
    finally
    {
        rijndaelCipher.Clear();
        rijndaelCipher.Dispose();
        if (encryptSteam != null)
            encryptSteam.Dispose();
        if (outputStream != null)
            outputStream.Dispose();
        if (inputStream != null)
            inputStream.Dispose();
    }
}
public Stamp EncryptStampToStampFolder(string stampFileToEncrpyt)
{
    Configuration config;
    Stamp stampToEncrypt;
    RijndaelManaged rijndaelCipher;
    string encryptedFilePath;
    if (!File.Exists(stampFileToEncrpyt))
        throw new FileNotFoundException(stampFileToEncrpyt + " does not exist");
    config = Configuration.GetProgramInstance();
    encryptedFilePath = Path.Combine(config.StampFolder, Path.GetFileNameWithoutExtension(stampFileToEncrpyt) + ".stmp");
    stampToEncrypt = new Stamp(Path.GetFileNameWithoutExtension(stampFileToEncrpyt), encryptedFilePath);
    rijndaelCipher = this.GetCipher(_imageKey, true);
    ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
    FileStream inputStream = null;
    FileStream outputStream = null;
    CryptoStream encryptSteam = null;
    byte[] block = new byte[16];
    int numberRead;
    try
    {
        inputStream = File.Open(stampFileToEncrpyt, FileMode.Open, FileAccess.Read);
        outputStream = File.Open(encryptedFilePath, FileMode.Create, FileAccess.Write);
        outputStream.Write(rijndaelCipher.IV, 0, IV.Length);
        //This had to be changed so that the IV was not overwitten
        //encryptSteam = new CryptoStream(outputStream, transform, CryptoStreamMode.Write); 
        encryptSteam = new CryptoStream(inputStream, transform, CryptoStreamMode.Read);
        //this line was a problem in the orginal code that caused extra data to be added to the encrypted file
        //encryptSteam.Write(block, 0, block.Length); 
        while ((numberRead = encryptSteam.Read(block, 0, block.Length)) > 0)
        {
            outputStream.Write(block, 0, numberRead);
        }
    }
    finally
    {
        rijndaelCipher.Clear();
        rijndaelCipher.Dispose();
        if (encryptSteam != null)
            encryptSteam.Dispose();
        if (outputStream != null)
            outputStream.Dispose();
        if (inputStream != null)
            inputStream.Dispose();
    }
    return stampToEncrypt;
}
public struct Stamp
{
    public string Name,
        Path;
    public Stamp(string StampName, string StampPath)
    {
        Name = StampName;
        Path = StampPath;
    }
}

我是这样解密的:

    private RijndaelManaged GetAesProvider(Stream stm, bool isEncryption)
    {
        byte[] finalKey = GetFinalKey();
        // GetIV either gets salt on encryption and writes it into stm
        // or reads it from stm if it's decryption
        byte[] iv = GetIV(stm, isEncryption);
        RijndaelManaged aes = new RijndaelManaged();
        aes.BlockSize = kAesBlockSizeInBytes * 8;
        aes.IV = iv;
        aes.Key = finalKey;
        aes.Mode = CipherMode.CBC;
        return aes;
    }
    public override Stream GetDecryptionStream(Stream source)
    {
        if (source.Length <= kIVSize)
        {
            return new EmptyStream();
        }
        RijndaelManaged aes = GetAesProvider(source, false);
        ICryptoTransform xform = aes.CreateDecryptor(aes.Key, aes.IV);
        return new CryptoStream(source, xform, CryptoStreamMode.Read);
    }