获得使用AesCryptoServiceProvider不正确解密值 [英] Getting incorrect decryption value using AesCryptoServiceProvider

查看:233
本文介绍了获得使用AesCryptoServiceProvider不正确解密值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下使用 AesCryptoServiceProvider 用于加密和解密code。该 IV 的有相同的加密和解密。仍然从源字符串解密的值不同。

  1. 还有什么需要加以纠正,以获得原始值解密后?
  2. 这code在工作时 inputValue将= valid128BitString 。但是,当 inputString =测试我收到以下异常填充是无效的不能删除。。我们怎样才能纠正呢?

修订问题

根据@jbtule回答以下将这样的伎俩。

  encyptedValue.IV = result.IV;
 

从加密结果改变了 IV 值。假设加密是在一个单独的进程做了,我们怎么能知道四解密?有没有一种方法,使之不断的或已知的?

答:您的另一种选择是通过一个IV的加密和分配它,你开始你的密码变换,而不是让aesProvider生成一个随机给你,之前。 - @Scott张伯伦

  aesProvider.IV = Convert.FromBase64String(4uy34C9sqOC9rbV4GD8jrA ==);
 

更新:请参阅如何应用填充为Base64的。我们可以使用 UTF8 编码源输入和结果输出。该密钥和IV可以留在的Base64

使用的Base64源输入会导致问题的一些值,例如,MyTest的,其中的字符串长度不是4的倍数

相关要点:

  

要解密用的是SymmetricAlgorithm类之一加密的数据,则必须设置Key属性和四属性被用于加密相同的值。

     

SymmetricAlgorithm.IV物业:从previous块的信息混合到加密下一个块的过程。因此,两个相同的明文块的输出是不同的。因为这种技术利用previous块到下一个块进行加密,初始化矢量是需要的数据的第一个块进行加密。 (按<一个href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.symmetricalgorithm.iv.aspx"相对=nofollow> SymmetricAlgorithm.IV物业的MSDN文章)

     

的有效密钥大小为:128,192,256位(根据<一个href="http://stackoverflow.com/questions/1056317/how-many-characters-to-create-a-byte-array-for-my-aes-method">How许多字符来创建一个字节数组我AES法?)

主要活动

 类节目
{
    静态无效的主要(字串[] args)
    {
        字符串valid128BitString =AAECAwQFBgcICQoLDA0ODw ==;
        字符串inputValue将= valid128BitString;
        字符串的keyValue = valid128BitString;
        串IV = valid128BitString;

        byte []的byteValForString = Convert.FromBase64String(inputValue将);
        EncryptResult结果= Aes128Utility.EncryptData(byteValForString,的keyValue);
        EncryptResult encyptedValue =新EncryptResult();
        四encyptedValue.IV =;
        encyptedValue.EncryptedMsg = result.EncryptedMsg;

        字符串finalResult = Convert.ToBase64String(Aes128Utility.DecryptData(encyptedValue,的keyValue));
        Console.WriteLine(finalResult);

        如果(String.Equals(inputValue将,finalResult))
        {
            Console.WriteLine(匹配);
        }
        其他
        {
            Console.WriteLine(不同);
        }

        到Console.ReadLine();
    }
}
 

AES工具

 公共静态类Aes128Utility
{
    私人静态字节[]键;

    公共静态EncryptResult EncryptData(byte []的RAWDATA,串strKey)
    {
        EncryptResult结果= NULL;
        如果(关键== NULL)
        {
            如果(!String.IsNullOrEmpty(strKey))
            {
                键= Convert.FromBase64String((strKey));
                结果=加密(RAWDATA);
            }
        }
        其他
        {
            结果=加密(RAWDATA);
        }

        返回结果;

    }

    公共静态的byte [] DecryptData(EncryptResult encryptResult,串strKey)
    {
        byte []的origData = NULL;
        如果(关键== NULL)
        {
            如果(!String.IsNullOrEmpty(strKey))
            {
                键= Convert.FromBase64String(strKey);
                origData =解密(Convert.FromBase64String(encryptResult.EncryptedMsg),Convert.FromBase64String(encryptResult.IV));
            }
        }
        其他
        {
            origData =解密(Convert.FromBase64String(encryptResult.EncryptedMsg),Convert.FromBase64String(encryptResult.IV));
        }

        返回origData;
    }

    私有静态EncryptResult加密(byte []的RAWDATA)
    {
        使用(AesCryptoServiceProvider aesProvider =新AesCryptoServiceProvider())
        {
            aesProvider.Key =键;
            aesProvider.Mode = CipherMode.CBC;
            aesProvider.Padding = PaddingMode.PKCS7;
            使用(MemoryStream的memStream =新的MemoryStream())
            {
                CryptoStream的encStream =新的CryptoStream(memStream,aesProvider.CreateEncryptor(),CryptoStreamMode.Write);
                encStream.Write(RAWDATA,0,rawData.Length);
                encStream.FlushFinalBlock();
                EncryptResult encResult =新EncryptResult();
                encResult.EncryptedMsg = Convert.ToBase64String(memStream.ToArray());
                encResult.IV = Convert.ToBase64String(aesProvider.IV);
                返回encResult;
            }
        }
    }

    私有静态的byte []解密(byte []的encryptedMsg,字节[] IV)
    {
        使用(AesCryptoServiceProvider aesProvider =新AesCryptoServiceProvider())
        {
            aesProvider.Key =键;
            aesProvider.IV = IV;
            aesProvider.Mode = CipherMode.CBC;
            aesProvider.Padding = PaddingMode.PKCS7;
            使用(MemoryStream的memStream =新的MemoryStream())
            {
                CryptoStream的decStream =新的CryptoStream(memStream,aesProvider.CreateDecryptor(),CryptoStreamMode.Write);
                decStream.Write(encryptedMsg,0,encryptedMsg.Length);
                decStream.FlushFinalBlock();
                返回memStream.ToArray();
            }
        }
    }

}
 

DTO类

 公共类EncryptResult
{
    公共字符串EncryptedMsg {获得;组; }
    公共字符串IV {获得;组; }
}
 

引用

  1. <一个href="http://stackoverflow.com/questions/1056317/how-many-characters-to-create-a-byte-array-for-my-aes-method">How许多字符来创建一个字节数组我AES法?
  2. <一个href="http://stackoverflow.com/questions/2919228/specified-key-is-not-a-valid-size-for-this-algorithm">Specified关键是不要对这种算法
  3. 一个有效大小
  4. <一个href="http://stackoverflow.com/questions/4504280/encryption-with-aes-256-and-the-initialization-vector">Encryption使用AES-256和初始化向量
  5. 无效的长度为一个base-64字符数组
  6. <一个href="http://stackoverflow.com/questions/3866316/whats-the-difference-between-utf8-utf16-and-base64-in-terms-of-encoding">What's在编码方面UTF8 / UTF16和Base64的之间的区别
解决方案

这很容易使用加密primatives执行错误,人们做这一切的时候,最好用的高水平库如果可以的话。

我有一个片段,我尽量保持审查和更新,那么近的作品pretty的到你做什么。它也不会在密文,这也是我建议,如果有反正对手可以发送选择密文到您解密实现身份验证,也有很多相关的修改密文侧信道攻击。

不过,你有没有什么东西做填充的问题,如果你的密文不对决你的密钥和IV,和你没有验证您的IV和密文,你通常会得到一个填充错误(如果这是向上冒泡一个客户端,它被称为填充甲骨文)。你需要改变你的主要语句:

 字符串valid128BitString =AAECAwQFBgcICQoLDA0ODw ==;
    字符串inputValue将=测试;
    字符串的keyValue = valid128BitString;


    byte []的byteValForString = Encoding.UTF8.GetBytes(inputValue将);
    EncryptResult结果= Aes128Utility.EncryptData(byteValForString,的keyValue);
    EncryptResult encyptedValue =新EncryptResult();
    encyptedValue.IV = result.IV; //&LT;  - 非常重要
    encyptedValue.EncryptedMsg = result.EncryptedMsg;

    字符串finalResult = Encoding.UTF8.GetString(Aes128Utility.DecryptData(encyptedValue,的keyValue));
 

所以,你使用相同的IV解密像你一样进行加密。

I have following code that uses AesCryptoServiceProvider for encrypting and decrypting. The iv and key used are same for both encryption and decryption. Still the decrypted value differ from the source string.

  1. What need to be corrected to get the original value after decrypt?
  2. This code is working when inputValue = valid128BitString. But when the inputString = "Test" I am getting the following exception Padding is invalid and cannot be removed.. How can we correct it?

UPDATED QUESTION

The following will do the trick based on @jbtule answer.

encyptedValue.IV = result.IV;

The IV value from encryption result changes. Suppose encryption is done in a separate process, how can we know the IV for decryption? Is there a way to make it constant or known?

Answer: Your other option is pass a IV in to Encrypt and assign it before you begin your crypto transform, instead of letting aesProvider generate a random one for you. – @Scott Chamberlain

 aesProvider.IV = Convert.FromBase64String("4uy34C9sqOC9rbV4GD8jrA==");

Update: Refer How to apply padding for Base64. We can use UTF8 for encoding the source input and result output. The key and IV may remain in Base64.

Using Base64 for source input will cause issues with some values, for example, "MyTest" where length of string is not a multiple of 4

Relevant points:

To decrypt data that was encrypted using one of the SymmetricAlgorithm classes, you must set the Key property and IV property to the same values that were used for encryption.

SymmetricAlgorithm.IV Property: Information from the previous block is mixed into the process of encrypting the next block. Thus, the output of two identical plain text blocks is different. Because this technique uses the previous block to encrypt the next block, an initialization vector is needed to encrypt the first block of data. (As per SymmetricAlgorithm.IV Property MSDN article)

The valid Key sizes are: 128, 192, 256 bits (as per How many characters to create a byte array for my AES method?)

Main Program

class Program
{
    static void Main(string[] args)
    {
        string valid128BitString = "AAECAwQFBgcICQoLDA0ODw==";
        string inputValue = valid128BitString;
        string keyValue = valid128BitString;
        string iv = valid128BitString;

        byte[] byteValForString = Convert.FromBase64String(inputValue);
        EncryptResult result = Aes128Utility.EncryptData(byteValForString, keyValue);
        EncryptResult encyptedValue = new EncryptResult();
        encyptedValue.IV = iv;
        encyptedValue.EncryptedMsg = result.EncryptedMsg;

        string finalResult = Convert.ToBase64String(Aes128Utility.DecryptData(encyptedValue, keyValue));
        Console.WriteLine(finalResult);

        if (String.Equals(inputValue, finalResult))
        {
            Console.WriteLine("Match");
        }
        else
        {
            Console.WriteLine("Differ");
        }

        Console.ReadLine();
    }
}

AES Utility

public static class Aes128Utility
{
    private static byte[] key;

    public static EncryptResult EncryptData(byte[] rawData, string strKey)
    {
        EncryptResult result = null;
        if (key == null)
        {
            if (!String.IsNullOrEmpty(strKey))
            {
                key = Convert.FromBase64String((strKey));
                result = Encrypt(rawData);
            }
        }
        else
        {
            result = Encrypt(rawData);
        }

        return result; 

    }

    public static byte[] DecryptData(EncryptResult encryptResult, string strKey)
    {
        byte[] origData = null;
        if (key == null)
        {
            if (!String.IsNullOrEmpty(strKey))
            {
                key = Convert.FromBase64String(strKey);
                origData = Decrypt(Convert.FromBase64String(encryptResult.EncryptedMsg), Convert.FromBase64String(encryptResult.IV));
            }
        }
        else
        {
            origData = Decrypt(Convert.FromBase64String(encryptResult.EncryptedMsg), Convert.FromBase64String(encryptResult.IV));
        }

        return origData; 
    }

    private static EncryptResult Encrypt(byte[] rawData)
    {
        using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
        {
            aesProvider.Key = key;
            aesProvider.Mode = CipherMode.CBC;
            aesProvider.Padding = PaddingMode.PKCS7;
            using (MemoryStream memStream = new MemoryStream())
            {
                CryptoStream encStream = new CryptoStream(memStream, aesProvider.CreateEncryptor(), CryptoStreamMode.Write);
                encStream.Write(rawData, 0, rawData.Length);
                encStream.FlushFinalBlock();
                EncryptResult encResult = new EncryptResult();
                encResult.EncryptedMsg = Convert.ToBase64String(memStream.ToArray());
                encResult.IV = Convert.ToBase64String(aesProvider.IV);
                return encResult;
            }
        }
    }

    private static byte[] Decrypt(byte[] encryptedMsg, byte[] iv)
    {
        using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
        {
            aesProvider.Key = key;
            aesProvider.IV = iv;
            aesProvider.Mode = CipherMode.CBC;
            aesProvider.Padding = PaddingMode.PKCS7;
            using (MemoryStream memStream = new MemoryStream())
            {
                CryptoStream decStream = new CryptoStream(memStream, aesProvider.CreateDecryptor(), CryptoStreamMode.Write);
                decStream.Write(encryptedMsg, 0, encryptedMsg.Length);
                decStream.FlushFinalBlock();
                return memStream.ToArray();
            }
        }
    }

}

DTO Class

public class EncryptResult
{
    public string EncryptedMsg { get; set; }
    public string IV { get; set; }
}

References

  1. How many characters to create a byte array for my AES method?
  2. Specified key is not a valid size for this algorithm
  3. Encryption with AES-256 and the Initialization Vector
  4. Invalid length for a Base-64 char array
  5. What's the difference between UTF8/UTF16 and Base64 in terms of encoding

解决方案

It is easy to make implementation mistakes with crypto primatives, people do it all the time, it's best to use a high level library if you can.

I have a snippet that I try to keep reviewed and up to date, that works pretty close to what your doing. It also does authentication on the cipher text, which i would recommend if there is anyway an adversary could send chosen ciphertext to your decryption implementation, there are a lot of side channel attacks related to modifying the ciphertext.

However, the problem your having does not have any thing to do with padding, if your ciphertext doesn't matchup to your key and iv, and you didn't authenticate your iv and ciphertext, you'll typically get a padding error (if this is bubbled up a client it's called a padding oracle). You need to change your main statement to:

    string valid128BitString = "AAECAwQFBgcICQoLDA0ODw==";
    string inputValue = "Test";
    string keyValue = valid128BitString;


    byte[] byteValForString = Encoding.UTF8.GetBytes(inputValue);
    EncryptResult result = Aes128Utility.EncryptData(byteValForString, keyValue);
    EncryptResult encyptedValue = new EncryptResult();
    encyptedValue.IV = result.IV; //<--Very Important
    encyptedValue.EncryptedMsg = result.EncryptedMsg;

    string finalResult =Encoding.UTF8.GetString(Aes128Utility.DecryptData(encyptedValue, keyValue));

So you use the same IV to decrypt as you did to encrypt.

这篇关于获得使用AesCryptoServiceProvider不正确解密值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆