php mcrypt和Delphi组件之间的AES加密差异

时间:2015-06-09 14:01:49

标签: php delphi encryption

我正在使用来自chillkat的Delphi组件,它为我做了AES加密。它就像一个魅力,服务器接受我的加密请求。所以我尝试使用mcrypt创建一个php pendant。但是PHP mcypt结果与Delphi Chillcat结果相比有所不同 - 即使所有参数都相同。因此服务器拒绝php请求。

所有加密设置都相同:

  • 密码名称:AES 128
  • 密码模式:ECB
  • 填充方案:填充NULL
  • 密钥长度:128
  • Key:1234567890ABE1234567890ABE1234DB
  • 要加密的字符串:这是一个非常酷的测试字符串

这是一个小PHP脚本:

<?php 
    $key = '1234567890ABE1234567890ABE1234DB';
    function string_encrypt($string, $key) {
        $crypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_ECB);
        return $crypted_text;
    }

    function string_decrypt($encrypted_string, $key) {
        $decrypted_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted_string, MCRYPT_MODE_ECB);
        return trim($decrypted_text);
    }

    echo $test_str = 'This is a really cool teststring';   echo '<br />';
    $enc_str = string_encrypt($test_str, $key);
    echo bin2hex($enc_str);                                     echo '<br />';
    echo string_decrypt($enc_str, $key);                        echo '<br />';

    ?>

php输出是: 的 e355fbcd91ada4b835e1b030cc9741759219f59fe441ba62e628eca2e8289eb3

这是德尔福法典:

function encrypt(s:PWideChar;mode,padding:integer;algo,cipher,keylength:string):string;
var
crypt: HCkCrypt2;
success: Boolean;
ivHex: PWideChar;
keyHex: PWideChar;
encStr: PWideChar;
decStr: PWideChar;

begin
crypt := CkCrypt2_Create();

//  AES is also known as Rijndael.
CkCrypt2_putCryptAlgorithm('aes');
// "pki", "aes", "blowfish", "blowfish2", "des", "3des", "rc2", "arc4", "twofish", "pbes1" and "pbes2"

//  CipherMode may be "ecb" or "cbc"
CkCrypt2_putCipherMode(crypt,'ecb');

//  KeyLength may be 128, 192, 256
try
  CkCrypt2_putKeyLength(crypt,128);
Except
  showmessage('The encryption key you have used seems to be invalid');
end;


//  The padding scheme determines the contents of the bytes
//  that are added to pad the result to a multiple of the
//  encryption algorithm's block size.  AES has a block
//  size of 16 bytes, so encrypted output is always
//  a multiple of 16.

{
Possible values are:

0 = RFC 1423 padding scheme: Each padding byte is set to the number of padding bytes.
If the data is already a multiple of algorithm's block size bytes, an extra block is
appended each having a value equal to the block size. (for example, if the algorithm's
block size is 16, then 16 bytes having the value 0x10 are added.). (This is also known as
PKCS5 padding: PKCS #5 padding string consists of a sequence of bytes, each of which
is equal to the total number of padding bytes added. )

1 = FIPS81 (Federal Information Processing Standards 81) where the last byte contains
the number of padding bytes, including itself, and the other padding bytes are set to random values.

2 = Each padding byte is set to a random value. The decryptor must know
how many bytes are in the original unencrypted data.

3 = Pad with NULLs. (If already a multiple of the algorithm's block size,
no padding is added).

4 = Pad with SPACE chars(0x20). (If already a multiple of algorithm's block size, no padding is added).
}
CkCrypt2_putPaddingScheme(crypt,3);

//  EncodingMode specifies the encoding of the output for
//  encryption, and the input for decryption.
//  It may be "hex", "url", "base64", or "quoted-printable".
CkCrypt2_putEncodingMode(crypt,'hex');

//  An initialization vector is required if using CBC mode.
//  ECB mode does not use an IV.
//  The length of the IV is equal to the algorithm's block size.
//  It is NOT equal to the length of the key.
ivHex := '';
CkCrypt2_SetEncodedIV(crypt,ivHex,'hex');

//  The secret key must equal the size of the key.  For
//  256-bit encryption, the binary secret key is 32 bytes.
//  For 128-bit encryption, the binary secret key is 16 bytes.

keyHex := '1234567890ABE1234567890ABE1234DB';
CkCrypt2_SetEncodedKey(crypt,keyHex,'hex');

//  Encrypt a string...
//  The input string is 44 ANSI characters (i.e. 44 bytes), so
//  the output should be 48 bytes (a multiple of 16).
//  Because the output is a hex string, it should
//  be 96 characters long (2 chars per byte).


 //encryption
 if mode = 0 then
 begin
   encStr := CkCrypt2__encryptStringENC(crypt,s);
   result := encStr;
 end
 else
 begin
  result := CkCrypt2__decryptStringENC(crypt,s);
 end;


CkCrypt2_Dispose(crypt);
End;

chillkat Delphi组件的输出是: 的 780F849AB30690433409D4FB7B3357735296A6E76D3AA6B6D6C769BE99F32041

我认为两个输出应该产生相同的值,因为所有输入参数都相等,对吗?

2 个答案:

答案 0 :(得分:2)

MCrypt希望密钥是二进制字符串,但是将十六进制编码的字符串传递给它。

使用

$key = hex2bin($key);

$key = pack('H*', $key);

取决于PHP支持。这必须在调用mcrypt_encrypt()之前完成。

安全

不要使用ECB模式。它没有语义安全性。攻击者可以从密文中获得很多内容而无需对其进行解密。您需要使用随机IV至少使用CBC模式。您还应该拥有密文的身份验证标记。

This answer为您提供了您需要了解的所有内容。剩下的一件事是,不要使用MCrypt。它是一个古老的未维护的图书馆。

在这方面,

This answer在实现同样的目标方面也非常有用。

答案 1 :(得分:0)

感谢您的良好输入,我能够从服务器收到以下4行代码的正面答案:

$key = pack('H*', "*5DB");
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,$mytxt, MCRYPT_MODE_ECB);
$hex2 = bin2hex($ciphertext);
echo strtoupper($hex2);

但是,我已经了解了

  • ECB不安全
  • mcrypt陈旧且无需维护

我会检查备选方案并相应地更新我的代码。再次感谢!