1

TripleDES 暗号化の IV 初期化ベクトルを作成しようとすると、次のエラーが発生します。

コード例を参照してください。

TripleDESCryptoServiceProvider tripDES = new TripleDESCryptoServiceProvider();

byte[] key = Encoding.ASCII.GetBytes("SomeKey132123ABC");
byte[] v4 = key;
byte[] connectionString = Encoding.ASCII.GetBytes("SomeConnectionStringValue");
byte[] encryptedConnectionString = Encoding.ASCII.GetBytes("");

// Read the key and convert it to byte stream
tripDES.Key = key; 
tripDES.IV = v4;

これは、VS から得られる例外です。

指定された初期化ベクトル (IV) が、このアルゴリズムのブロック サイズと一致しません。

どこが間違っていますか?

ありがとうございました

4

6 に答える 6

10

MSDNは、次のように明示的に述べています。

... IVプロパティのサイズは、BlockSizeプロパティと同じである必要があります。

Triple DESの場合、64ビットです。

于 2010-07-05T12:06:26.357 に答える
6

初期化ベクトルのサイズは、ブロックサイズ(TripleDESの場合は64ビット)と一致する必要があります。初期化ベクトルは8バイトよりはるかに長いです。

さらに、 PBKDF2のような鍵導出関数を実際に使用して、パスワードフレーズから強力な鍵と初期化ベクトルを作成する必要があります。

于 2010-07-05T12:08:17.740 に答える
5

IVは、と同じ長さ(ビット単位)である必要がありますtripDES.BlockSize。TripleDESの場合、これは8バイト(64ビット)になります。

于 2010-07-05T12:06:03.197 に答える
5

キーは24バイト、IVは8バイトである必要があります。

tripDES.Key = Encoding.ASCII.GetBytes("123456789012345678901234");
tripDES.IV = Encoding.ASCII.GetBytes("12345678");
于 2010-07-05T12:07:37.133 に答える
4

すべて正しいので、ここですべての回答に賛成票を投じました(私の前にここにあるものも!)。

ただし、あなたが犯している大きな間違いがあります(私も早い段階で犯したものです)-IVまたはキーをシードするために文字列を使用しないでください!!!

コンパイル時の文字列リテラルは Unicode 文字列であり、バイト値のランダムまたは十分な広がりを取得しないという事実にもかかわらず (ランダムな文字列でさえ、バイト範囲が狭いために多くの繰り返しバイトが含まれるため)印刷可能な文字)、実際には 1 バイトではなく 2 バイトを必要とする文字を取得するのは非常に簡単です。キーボードでよりエキゾチックな文字を 8 つ使ってみると、私の言いたいことがわかります。バイトに変換すると、 8バイト以上。

わかりました-ASCIIエンコーディングを使用しています-しかし、それは非ランダムな問題を解決しません。

代わりに、RNGCryptoServiceProvider を使用して IV とキーを初期化する必要があります。将来の使用のために定数値を取得する必要がある場合は、引き続きそのクラスを使用する必要がありますが、結果は16 進文字列または Base-64 でエンコードされた値 (ただし、16進数の方が好きです)。

これを簡単に実現するために、.Net PRNG を使用して 16 進文字列を生成するVS で使用するマクロ (キーボード ショートカットCTRL+SHIFT+G、CTRL+SHIFT+Hにバインド) を作成しました。

Public Sub GenerateHexKey()
  Dim result As String = InputBox("How many bits?", "Key Generator", 128)

  Dim len As Int32 = 128

  If String.IsNullOrEmpty(result) Then Return

  If System.Int32.TryParse(result, len) = False Then
      Return
  End If

  Dim oldCursor As Cursor = Cursor.Current

  Cursor.Current = Cursors.WaitCursor

  Dim buff((len / 8) - 1) As Byte
  Dim rng As New System.Security.Cryptography.RNGCryptoServiceProvider()

  rng.GetBytes(buff)

  Dim sb As New StringBuilder(CType((len / 8) * 2, Integer))
  For Each b In buff
      sb.AppendFormat("{0:X2}", b)
  Next

  Dim selection As EnvDTE.TextSelection = DTE.ActiveDocument.Selection
  Dim editPoint As EnvDTE.EditPoint

  selection.Insert(sb.ToString())
  Cursor.Current = oldCursor
End Sub

あとは、16 進文字列リテラルをバイト配列に変換するだけです。便利な拡張メソッドを使用してこれを行います。

public static byte[] FromHexString(this string str)
{
  //null check a good idea
  int NumberChars = str.Length;
  byte[] bytes = new byte[NumberChars / 2];
  for (int i = 0; i < NumberChars; i += 2)
    bytes[i / 2] = Convert.ToByte(str.Substring(i, 2), 16);
  return bytes;
}

おそらくそれを行うにはもっと良い方法がありますが、私にとってはうまくいきます。

于 2010-07-05T12:25:44.433 に答える
0

私はこのようにします:

var derivedForIv = new Rfc2898DeriveBytes(passwordBytes, _saltBytes, 3);
_encryptionAlgorithm.IV = derivedForIv.GetBytes(_encryptionAlgorithm.LegalBlockSizes[0].MaxSize / 8);

IV は、LegalBlockSizes プロパティを介してアルゴリズム自体によって記述されたブロック サイズを使用して、派生バイト 'smusher' からバイトを取得します。

于 2012-03-22T22:38:15.317 に答える