密码rijndael delphi 2010 dcp

时间:2012-08-10 23:56:05

标签: delphi delphi-2010 rijndael

我有一个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=
有人可以帮帮我吗?为什么这样的事情会发生?

提前谢谢 Vauli

1 个答案:

答案 0 :(得分: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字节

这让我觉得你只传递16个字节到TForm1.CipherAES()。 我这样说,因为在调用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:=复制(StreamR,1,     outStream.Size + 8);

    为什么选择outStream.Size + 8?你正在从StreamR复制一些东西, 基于其他缓冲区的大小,无视您的实际大小 StreamR? “Copy()”也只能获得最多LENGTH(StreamR)字符。

  3. 考虑使用:

    ,而不是逐字节填充ToEnc

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

    toSnd(但.writeBuffer())

  4. 也是如此

    关于加密字符串的注意事项(因为我不知道你如何提供InStream):

    确保您正在加密文本的Unicode版本(UTF16-LE或UTF-8)。将字符串转换为ansiString是通过OS系统区域设置进行的,可能导致数据丢失(着名的'????')