I’ve tried to encrypt the value with DES-ECB via PHP 7.4 (Laravel) and OpenSSL, and I try the online tool https://emvlab.org/descalc/ to encrypt value, the result was the expected.
The encrypted data is
355A627E977D8ECF4953C98D801E472F on online tool.
When the next code written in PHP I can’t replicate the result:
$data = "F01DCCE40F8C365ADE0A7DC03BC11DDE"; $key = "96187BBAB2BD19ACF899B74FB4E37972"; $encrypted = openssl_encrypt($data, 'DES-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING); echo base64_encode($encrypted); // KV8Vie63pG2ZyjW7U5NRJUwOrbsEt+lnG1hNyS331Yk=
Is there a way to get the same string that the online tool?
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
What must be considered for the website?
The website allows encryption with DES and TripleDES in 2TDEA variant (double length keys). The algorithm is determined by the key size: For an 8 bytes key DES is used, for a 16 bytes key TripleDES/2TDEA. The supported modes are ECB and CBC.
Key, IV (in case of CBC mode), plaintext and ciphertext have to be entered hex encoded on the website. Zero padding is applied (the variant that does not pad if the plaintext length is already an integer multiple of the DES/TripleDES block size of 8 bytes).
What does this mean for the posted data?
Since the posted hex encoded key
96187BBAB2BD19ACF899B74FB4E37972 has a size of 16 bytes, TripleDES/2TDEA is used (in ECB mode).
The hex encoded plaintext
F01DCCE40F8C365ADE0A7DC03BC11DDE has a size of 16 bytes and is therefore not padded. The resulting hex encoded ciphertext
355A627E977D8ECF4953C98D801E472F thus has the same length.
How can the PHP code be fixed?
The posted PHP code gives a different result because DES is used as algorithm (in ECB mode) and also the hex encoding/decoding is missing. Thus to produce the result of the website, the encoding/decoding has to be fixed and
DES-EDE-ECB has to be applied as algorithm (not to be confused with
DES-EDE3-ECB for 3TDEA/triple length keys):
$data = hex2bin("F01DCCE40F8C365ADE0A7DC03BC11DDE"); // hex decode the 16 bytes data $key = hex2bin("96187BBAB2BD19ACF899B74FB4E37972"); // hex decode the 16 bytes key key $encrypted = openssl_encrypt($data, 'DES-EDE-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); // apply DES-EDE-ECB; use OPENSSL_ZERO_PADDING echo bin2hex($encrypted); // 355a627e977d8ecf4953c98d801e472f // hex encode the 16 bytes ciphertext
with the output:
that is equal to the result of the web site, s. here
How can a consistent result be achieved for DES?
The current PHP code applies DES and therefore implicitly truncates the key to 8 bytes by using only the first 8 bytes. This can be easily verified by removing the last 8 bytes of the key. The result does not change.
If the shortened key is applied to the website, the results match again.
$data = hex2bin("F01DCCE40F8C365ADE0A7DC03BC11DDE"); // hex decode the 16 bytes data $key = hex2bin("96187BBAB2BD19AC"); // hex decode the 8 bytes key $encrypted = openssl_encrypt($data, 'DES-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); // apply DES-ECB; use OPENSSL_ZERO_PADDING echo bin2hex($encrypted); // 692370230b8176f011760ddc07392a4f // hex encode the 16 bytes ciphertext
with the output:
that is equal to the result of the web site, s. here.