1

I have the following code in Javascript to encrypt a string using a key:

des.js is this: http://www.tero.co.uk/des/code.php

<script src="/js/des.js"></script>
<script>
var key = '12345678';
var message = 'hello world';

var ciph = des(key, message, 1, 0);
ciph = stringToHex(ciph);
console.log("Encrypted Result: " + ciph);
</script> 

Then I send it server side and attempt to decrypt with this PHP code:

$key = '12345678';
$hexa = '0x28dba02eb5f6dd476042daebfa59687a'; /This is the output from Javascript
$string = '';
for ($i=0; $i < strlen($hexa)-1; $i+=2) {
$string .= chr(hexdec($hexa[$i].$hexa[$i+1])); }
echo mcrypt_decrypt(MCRYPT_DES, $key, $string, MCRYPT_MODE_ECB);

Ive tried converting it to utf8, changing encoding, changing the hex decoding, etc, but it always comes out gibberish, sometimes as nonreadable characters, other times as readable but nonsense.

3
  • It is best not to use mcrypt, it has been abandonware for nearly a decade now. It has therefore been deprecated and will be removed from the core and into PECL in PHP 7.2. It does not support standard PKCS#7 (née PKCS#5) padding, only non-standard null padding that can't even be used with binary data. mcrypt has many outstanding bugs dating back to 2003. Instead consider using defuse or RNCryptor, they provide a complete solution, are being maintained and is correct. Commented Jan 19, 2017 at 23:11
  • Do not use DES, it is not secure and has been superceededby AES. Do not use ECB mode, it is insecure, see ECB mode, scroll down to the Penguin. Instead use CBC mode with a random IV, just prefix the encrypted data with the IV for use in decryption, it does not need to not secret. Commented Jan 19, 2017 at 23:20
  • You need to remove the '0x' from the hex encoded string (actually, I'd try and switch from hex to base64 altogether). Commented Jan 19, 2017 at 23:45

2 Answers 2

1

The way to decrypt the string is not working properly, try this:

$key = '12345678';
$hexa = '0x28dba02eb5f6dd476042daebfa59687a'; 

function hexToString ($h) {
  $r = "";
 for ($i= (substr($h, 0, 2)=="0x")?2:0; $i<strlen($h); $i+=2) {$r .= chr (base_convert (substr ($h, $i, 2), 16, 10));}
return $r;
}

echo mcrypt_decrypt(MCRYPT_DES, $key,hexToString('0x28dba02eb5f6dd476042daebfa59687a'), MCRYPT_MODE_ECB);

The output will be: hello world

This way work properly, however, you should search another method to encrypt your data, in your script the key (12345678) and your encrypt method is visible to everyone.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I ended up using public/private key encryption instead. My plan was to use a temporary key set in a PHP session, changed hourly.
0

Data to be encrypted with a block cipher such as DES or AES must be an exact multiple of the block size in length. The solution is to add padding to the data to be encrypted, PKCS#5 padding is the usual padding for DES and probably the default for Javascript. Unfortunately mcrypt does not support PKCS#5 padding, only a non-standard zero padding.

Potential solutions:

  1. Use a better encryption function than mcrypt, see the comment to the question.
  2. Specify no padding in Javascript and manually add zero padding.
  3. Specify no padding in mcrypt and remove the padding manually.

It is better tospecify all options and no to rely on defaults.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.