I have written a Python version of DES3 encryption method to encrypt the data send to the server, but the server side said that it could not decrypt the requested data.
So I have to check the source code. And found that the encryption result of PHP version are different from Python and C#.
The algorithm used is DES3, Mode: ECB, in such mode, IV is unnecessary. And the padding used in Python and C# is Zeros (that is the padding string consists of bytes set to zero). I do not know how PHP dealing with padding.
The key used is 1234567887654321 , the plain is hello , IV is eight empty space (non-used).
The hex dump of PHP encryption result is
77 2c fe 6e c1 df 71 94
The hex dump of Python and C# are
BC 17 0C 67 7D 06 5C AA
Anybody could tell me what's wrong with the PHP code?
The following are the source code
PHP
function encrypt($plain, $key, $iv) {
/* Open module, and create IV */
$td = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_ECB, '');
/* Initialize encryption handle */
if (mcrypt_generic_init($td, $key, $iv) != -1) {
/* Encrypt data */
$c_t = mcrypt_generic($td, $plain);
mcrypt_generic_deinit($td);
/* Clean up */
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
}
return $c_t;
}
Python
def encrypt(text, key, iv=''):
cypher = DES3.new(key, DES3.MODE_ECB, iv)
padding_length = (8 - len(text) % 8) % 8
padding = '\x00' * padding_length
return cypher.encrypt(text + padding)
C#
public static byte[] Encrypt(byte[] plain, byte[] Key, byte[] IV)
{
// Create a MemoryStream to accept the encrypted bytes
MemoryStream ms = new MemoryStream();
TripleDES alg = TripleDES.Create();
alg.Key = Key;
alg.IV = IV;
alg.Mode = CipherMode.ECB;
alg.Padding = PaddingMode.Zeros;
CryptoStream cs = new CryptoStream(ms,
alg.CreateEncryptor(), CryptoStreamMode.Write);
// Write the data and make it do the encryption
cs.Write(plain, 0, plain.Length);
cs.Close();
byte[] cypher = ms.ToArray();
return cypher;
}
Because of Triple DES, you will should be passing in a 24 byte key. Since you are passing in 16 bytes different implementations use different methods to expand this key to 24 bytes.
It appears that in Python/C# the 16 byte key is extended by cycling/repeating it around to make this 24 bytes. So for example:
1234567887654321
becomes
123456788765432112345678
PHP on the other hand appears to simply pad the key with nulls ( \\x00
) which you can verify by doing
$output1 = bin2hex(encrypt($str, "1234567887654321", ""));
$output2 = bin2hex(encrypt($str, "1234567887654321\x00\x00\x00\x00\x00\x00\x00\x00", ""));
echo $output1 == $output2; // true!
If you mimic this Python/C# "cycling" behaviour manually with PHP, you will get a consistent output for all 3 languages:
$output = bin2hex(encrypt($str, "123456788765432112345678", ""));
echo $output; // bc170c677d065caa
Although you can simply extend the 16-byte key to 24-bytes by simple cycling/repeating it, just go for a fully random 24-byte key instead for max security. You can read more here (you want keying option #1)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.