2

我在使用 DCP Crypt 库加密和解密某些信息时遇到问题。我正在使用 Delphi XE 和在PHP 上发布的函数到 Delphi 并使用 Rijndael 返回 Encryption-Decryption,但它不起作用。

我认为我的问题是因为我使用的密钥是十六进制模式而不是二进制。

var 
  Key, IV: ansiString;
  Data: ansiString;
begin
  Key := '09CB0785F13CD0D557C0940E72E0DCDC86CDC89769044E95DB51A782E7D996FFF3';
  Iv  := '09CB0785F13CD0D557C0940E72E0DCDC';

  Data := <?xml version="1.0" encoding="UTF-8"?><MyNode><Head><CustNo>...';

当我使用该EncryptData功能时,我必须以二进制还是十六进制传递公钥?

 asCryptBody := EncryptData(asXMLBody, Public_Key, Init_vector);

或者

 asCryptBody := EncryptData(asXMLBody, HexToStrBin(Public_Key), HexToStrBin(Init_vector));

在哪里

function StrBinToHex(const s: AnsiString): AnsiString;
var
  i:integer;
begin
  result := '';
  for i := 1 to length(s) do
    result := result + inttohex(Ord(s[i]),1);
end;

function HexToStrBin(const s: AnsiString): AnsiString;
var
  i:integer;
begin
  result := '';
  for i := 1 to (length(s) div 2) do
    result := result + char( strtoint('$'+ copy(s,(i*2)-1,2)) );
end;

我尝试了两种方法,但加密仍然不同于 PHP 加密。

也许函数 HexToStrBin 和 StrBinToHex 是问题所在?

4

1 回答 1

1

非常感谢大家的回答。现在解决了。问题是: - 我的密钥和 ini.vector 是一个具有十六进制值的字符串 - 然后我必须使用我自己的函数将密钥和初始化向量从具有密钥的十六进制值的 ansistring 转换为 TByte:StrHexToTBytes - 在加密之前,不要添加填充。- 不要对加密的 TBytes 结果进行 base64decode 并将其放入带有 TEncoding.Default.GetString 的字符串中 - 然后为了我的使用,我将此字符串结果传递给具有十六进制值的字符串。

正如我在标题中发布的那样,Delphi 版本是 XE。

function StrHexToTBytes(const Hexstr: AnsiString): TBytes;
var
  i: Integer;
begin
  SetLength(Result, Length(Hexstr) div 2);
  for i:=0 to (Length(Hexstr) div 2 - 1) do
     Result[i]:= StrToInt('$' + Copy(Hexstr, (i * 2) + 1, 2));
end;

function EncryptData(const Data, AHexKey, AHexIv: AnsiString): Ansistring;
var
  cipher: TDCP_rijndael;
  key, iv, src, dest : TBytes;
  slen: integer;
begin

  /// La clau pública és una cadena de valors Hexadecimals, i s'ha de convertir a un array de Bytes.
  /// The Key and IV are an Hex ansistring, and must converted to TBytes
  key  := StrHexToTBytes(AHexKey);
  iv   := StrHexToTBytes(AHexIv);

  /// Les dades estan en una cadena de caracters i s'ha de passar directament a un array de bytes
  /// The Data is plain text in a string and must converted to TBytes
  src := TEncoding.UTF8.GetBytes(Data);

  cipher := TDCP_rijndael.Create(nil);
  try
    cipher.CipherMode := cmCBC;
    slen := Length(src);

    /// Ull No s'ha de fer cap padding del text rebut!!!
    /// Attention, the pading is not necessary!!!
{
    // Add padding.
    // Resize the Value array to make it a multiple of the block length.
    // If it's already an exact multiple then add a full block of padding.
    slen := Length(src);
    bsize := (cipher.BlockSize div 8);
    pad := bsize - (slen mod bsize);
    Inc(slen, pad);
    SetLength(src, slen);
    for index := pad downto 1 do
    begin
      src[slen - index] := pad;
    end;
}
    SetLength(dest, slen);
    cipher.Init(key[0], 256, @iv[0]); // DCP uses key size in BITS not BYTES
    cipher.Encrypt(src[0], dest[0], slen);

    /// El resultat no s'ha de codificar en base 64, es un binary que només s'ha de passar a Hexadecimal
    ///  The result does'nt must be converted to based 64, is a binary that must be puttd into a string.
//    b64 := Base64EncodeBytes(dest);
//    result := TEncoding.Default.GetString(b64);
    result := TEncoding.Default.GetString(dest);
  finally
    cipher.Free;
  end;
end;

现在我必须调整 DecryptData 函数。

于 2013-06-13T10:50:27.910 回答