我的密钥的二进制和十六进制字符串表示之间的区别是DCPCrypt意外输出的原因吗?

时间:2013-06-12 09:52:17

标签: delphi binary hex delphi-xe rijndael

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

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

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是问题?

1 个答案:

答案 0 :(得分:1)

非常感谢大家的回答。 现在解决了。 问题是: - 我的key和ini.vector是一个带有十六进制值的字符串 - 然后我必须将密钥和初始化向量从带有十六进制值key的ansistring转换为TByte和我自己的函数:StrHexToTBytes - 在crypt之前,不要添加填充。 - 不要对加密的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函数。