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

如果您对这两个值进行 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):

Ensure you're encrypting Unicode version of the text (UTF16-LE or UTF-8). Converting string to ansiString goes via OS system locale and can result in data loss (the famous '????')

于 2012-08-11T15:12:04.013 回答