1

私は IV (初期化ベクトル) とキーを持っています。文字列を暗号化する必要があります。これはコードです:

function TForm1.CipherAES (key: AnsiString; Vector: AnsiString;
  InStream: TMemoryStream) : TMemoryStream;
var
  cipher: TDCP_rijndael;
  i: integer;
  toEnc, toSnd : array of byte;
  outStream, AStream :TMemoryStream;
  StreamR, Stream2 : AnsiString;
begin
  outStream := TMemoryStream.Create;
  SetLength(toEnc, InStream.Size);

  cipher := TDCP_rijndael.Create(nil);
  cipher.Init(key[1], 128, nil);
  cipher.SetIV(vector[1]);
  cipher.BlockSize := 16;
  InStream.Position := 0;

  for I := 0 to InStream.Size-1 do
    InStream.Read(ToEnc[i], 1);

  for I := 0 to inStream.size-1 do
    StreamR := StreamR + ByteToHex(toEnc[i]) + ' ';
  Memo1.Lines.Add(StreamR);
  inStream.Position := 0;

  cipher.CipherMode := cmCBC;
  cipher.EncryptStream(inStream, outStream, InStream.Size);
  Base64Encode(outStream.Memory, @StreamR[1], outStream.Size);

  Stream2 := Copy(StreamR, 1, outStream.Size + 8);
  Memo1.Lines.Add(Stream2);
  Memo1.Lines.Add(StreamR);

  outStream.Position := 0;

  SetLength(toSnd, outStream.Size);
  for I := 0 to outStream.Size-1 do
    outStream.Read(toSnd[i], 1);

  StreamR := '';
  for I := 0 to outStream.size-1 do
    StreamR := StreamR + ByteToHex(toSnd[i]) + ' ';
  Memo1.Lines.Add(StreamR);

  cipher.burn;
  cipher.free;

  Result := outStream;
end;

ストリームを base64 に渡すと、次の答えが得られます。

ub/JkCsCZwbAnyqjo+miIw==

ただし、次のようにする必要があります。

ub/JkCsCZwbAnyqjo+miI2XNZwNrJo31YBNTwQuHkq0=

誰かが私を助けることができますか?なぜこのようなことが起こっているのですか?

前もって感謝します

4

1 に答える 1

1

これら 2 つの値を base64 でデコードすると、次のようになります。

ub/JkCsCZwbAnyqjo+miIw== デコードすると:

B9 BF C9 90 2B 02 67 06-C0 9F 2A A3 A3 E9 A2 23 (in hex) 

=> 16 バイト

ub/JkCsCZwbAnyqjo+miI2XNZwNrJo31YBNTwQuHkq0= にデコード:

B9 BF C9 90 2B 02 67 06-C0 9F 2A A3 A3 E9 A2 23
65 CD 67 03 6B 26 8D F5-60 13 53 C1 0B 87 92 AD (in hex) 

=> 32 バイト

これは、TForm1.CipherAES() に 16 バイトしか渡していないと思わせます。私が言っているのは、cipher.EncryptStream を呼び出した後、outStream.size は inStream.size と等しくなるはずだからです。

ブレークポイントを使用してテストする場合は、InStream.Size の値を明確にしてください。

コードに関する注意事項:

  1. Base64Encode は、出力バッファーに含まれるバイト数を返します。この値を使用して StreamR のサイズを設定することはありません。

    base64encode への呼び出しは次のようになります。

    // Allocate buffer for base64 decoded data
    setLength(StreamR, ((inStrem.size + 2) div 3) * 4); 
    size := Base64Encode(outStream.Memory, @StreamR[1], outStream.Size);
    setLength(StreamR, size);
    
  2. 私は本当にこれの意味を理解していません:

    Stream2 := Copy(StreamR, 1, outStream.Size + 8);

    なぜ outStream.Size + 8 なのですか? StreamR の実際のサイズを無視して、他のバッファーのサイズに基づいて、StreamR から何かをコピーしていますか? また、「Copy()」は最大で LENGTH(StreamR) 文字しか取得しません。

  3. ToEnc をバイトごとに埋める代わりに、次の使用を検討してください。

    InStream.ReadBuffer(ToEnc[0], InStream.size);

    toSnd についても同じ (ただし .writeBuffer())


文字列の暗号化に関する注意(InStream のフィード方法がわからないため):

テキストの Unicode バージョン (UTF16-LE または UTF-8) を暗号化していることを確認します。文字列から ansiString への変換は OS システム ロケールを経由するため、データが失われる可能性があります (有名な「????」)。

于 2012-08-11T15:12:04.013 に答える