Rijndael:相同的字符串,不同的结果

时间:2011-08-04 18:50:48

标签: c# encryption rijndaelmanaged

我们有一个小型桌面应用程序,现在需要作为Web功能提供(.Net)。这个应用程序包含一些加密代码,并使用.Net框架中的Rijndael类。代码接受输入字符串,对其进行加密并将结果写入文件。由于所有代码都包含在一个类中,我只是将该类复制到我的Web服务应用程序中。当我在原始应用程序和新应用程序中使用相同的密钥加密相同的字符串时,结果会有所不同。 原始应用程序给出的结果字符串是我的Web服务给出的结果字符串的子集。后者在加密字符串的末尾有其他字符。

以下是我正在使用的代码。请注意,我没有开发此代码,也不完全理解它。有关行为差异的任何想法?请帮忙!!

以下是获取用户输入并调用加密器的代码。

    public void EncryptDomain(string EncryptValue, string outputDomainFile)
    {
            if (EncryptValue.Length > 0)
            {
                if ((outputDomainFile != null) && (outputDomainFile.Length > 0))
                {
                    _outputDomainFile = outputDomainFile;
                }

                byte[] input = Encoding.UTF8.GetBytes(EncryptValue);

                Transform(input, TransformType.ENCRYPT);

            }

这是加密器代码:

    private byte[] Transform(byte[] input, TransformType transformType)
    {
        CryptoStream cryptoStream = null;      // Stream used to encrypt
        RijndaelManaged rijndael = null;        // Rijndael provider
        ICryptoTransform rijndaelTransform = null;// Encrypting object            
        FileStream fsIn = null;                 //input file
        FileStream fsOut = null;                //output file
        MemoryStream memStream = null;          // Stream to contain data
        try
        {
            // Create the crypto objects
            rijndael = new RijndaelManaged();
            rijndael.Key = this._Key;
            rijndael.IV = this._IV;
            rijndael.Padding = PaddingMode.Zeros;   

            if (transformType == TransformType.ENCRYPT)
            {
                rijndaelTransform = rijndael.CreateEncryptor();
            }
            else
            {
                rijndaelTransform = rijndael.CreateDecryptor();
            }

            if ((input != null) && (input.Length > 0))
            {
                //memStream = new MemoryStream();
                //string outputDomainFile = 
                FileStream fsOutDomain = new FileStream(_outputDomainFile,
                                            FileMode.OpenOrCreate, FileAccess.Write);

                cryptoStream = new CryptoStream(
                     fsOutDomain, rijndaelTransform, CryptoStreamMode.Write);

                cryptoStream.Write(input, 0, input.Length);

                cryptoStream.FlushFinalBlock();

                //return memStream.ToArray();
                return null;
            }
            return null;

        }
        catch (CryptographicException)
        {
            throw new CryptographicException("Password is invalid. Please verify once again.");
        }
        finally
        {
            if (rijndael != null) rijndael.Clear();
            if (rijndaelTransform != null) rijndaelTransform.Dispose();
            if (cryptoStream != null) cryptoStream.Close();
            if (memStream != null) memStream.Close();
            if (fsOut != null) fsOut.Close();
            if (fsIn != null) fsIn.Close();
        }
 }

设置IV值的代码:

    private void GenerateKey(string SecretPhrase)
    {
        // Initialize internal values
        this._Key = new byte[24];
        this._IV = new byte[16];

        // Perform a hash operation using the phrase.  This will 
        // generate a unique 32 character value to be used as the key.
        byte[] bytePhrase = Encoding.ASCII.GetBytes(SecretPhrase);
        SHA384Managed sha384 = new SHA384Managed();
        sha384.ComputeHash(bytePhrase);
        byte[] result = sha384.Hash;

        // Transfer the first 24 characters of the hashed value to the key
        // and the remaining 8 characters to the intialization vector.
        for (int loop = 0; loop < 24; loop++) this._Key[loop] = result[loop];
        for (int loop = 24; loop < 40; loop++) this._IV[loop - 24] = result[loop];
    }

2 个答案:

答案 0 :(得分:3)

我猜这是因为IV (Initialisation Vector)

答案 1 :(得分:3)

这是一个经典的错误。无论您是否自己生成IV,Rijndael(AES)都会为您提供。诀窍是始终保存IV(RijndaelManaged上有一个getter)。

  • 解密时,您需要传递两者 键和IV

如果要将数据保存到文件或数据库,则可以将IV存储为纯文本。您甚至可以将IV作为纯文本传递给网络(网络,互联网)。攻击者不能(据我所知)基于IV打破你的密码。传递或存储IV通常是通过在密文前添加前缀或在末尾附加它来完成的。 (连接两个字符串)

e.g。 CiphertextIV或IVCiphertext。 (记住IV是纯文本,它应该是固定的长度 - 在接收解密或插入数据库时​​很容易分开)

因此,如果您的密钥是ABCDEFABCDEFABCD ,而您的 IV是ABCDEF0123456789 这个明文:  '这是一些秘密文字'(让我们说)产生一个密码,例如: abcd1234abcd00

你会像这样发送(或存储): ABCDEF0123456789abcd1234abcd00