4

現在、Web 機能として提供する必要がある小さなデスクトップ アプリ (.Net) がありました。このアプリには暗号化用のコードが含まれており、.Net フレームワークの Rijndael クラスを使用しています。コードは入力文字列を受け取り、それを暗号化し、結果をファイルに書き込みます。すべてのコードが 1 つのクラスに含まれているため、そのクラスを 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];
    }
4

2 に答える 2

3

これは典型的な間違いです。自分で IV を生成するかどうかにかかわらず、Rijndael (AES) が提供します。秘訣は、常に IV を保存することです (RijndaelManaged にはゲッターがあります)。

  • 復号化するときは、Key と IVの両方を渡す必要があります。

データをファイルまたはデータベースに保存する場合は、IV をプレーン テキストとして保存できます。IV を有線 (ネットワーク、インターネット) でプレーンテキストとして渡すこともできます。攻撃者は、(私の知る限り) IV だけに基づいて暗号を解読することはできません。IV の受け渡しまたは保存は、通常、暗号文の前にプレフィックスを付けるか、末尾に追加することによって行われます。(2 つの文字列を連結)

たとえば、CiphertextIV または IVCiphertext です。(IV はプレーンテキストであることを思い出してください。固定長にする必要があります。これにより、受信時に復号化またはデータベース挿入のために簡単に分離できます)

したがって、キーが ABCDEFABCDEFABCDで、IV が ABCDEF0123456789 で、平文 が「これは秘密のテキストです」 (たとえば) の場合、次のような暗号が生成されます: abcd1234abcd00

次のように送信 (または保存) します: ABCDEF0123456789abcd1234abcd00

于 2011-10-31T18:55:52.263 に答える