I have javascript that encrypts and gives the string.
But I have to do this through PHP.
The method I have tried is giving me different result than javascript.
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"
integrity="sha512-nOQuvD9nKirvxDdvQ9OMqe2dgapbPB7vYAMrzJihw5m+aNcf0dX53m6YxM4LgA9u8e9eg9QX+/+mPu8kCNpV2A==" crossorigin="anonymous"></script>
var txt="This text will be encrypted.";
var key = CryptoJS.enc.Hex.parse('0123456789abcdef0123456789abcdef');
var iv = CryptoJS.enc.Hex.parse('abcdef9876543210abcdef9876543210');
var encrypted = CryptoJS.AES.encrypt((txt), key, { iv: iv });
var encrypted_data = encrypted.ciphertext.toString(CryptoJS.enc.Base64);
alert(encrypted_data);
I get output:
2X/btHgrMBhNlgD8oKNO9rzqCg+RSydprVKmpbYY+j0=
In PHP
<?php
$plaintext="This text will be encrypted.";
$key = pack("H*", "0123456789abcdef0123456789abcdef");
$iv = pack("H*", "abcdef9876543210abcdef9876543210");
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $iv);
$ciphertext_base64 = base64_encode($ciphertext);
echo $ciphertext_base64;
?>
I get output:
2X/btHgrMBhNlgD8oKNO9nJyd4xC4VTLGxnnrzGim+U=
I want the out as same as the output in javascript.
I found that the starting 21 characters match, but not the rest of the string.
Anything I am missing?
This is due to the different padding. CryptoJS uses PKCS#7, mcrypt applies zero padding.
You should replace mcrypt on the PHP side as it is deprecated (s. here). An alternative would be PHP/OpenSSL, which uses PKCS#7 by default.
A solution with PHP/OpenSSL which produces the same ciphertext is:
<?php
$plaintext="This text will be encrypted.";
$key = hex2bin("0123456789abcdef0123456789abcdef");
$iv = hex2bin("abcdef9876543210abcdef9876543210");
$ciphertext_base64 = openssl_encrypt($plaintext, "aes-128-cbc", $key, 0, $iv);
echo $ciphertext_base64; // 2X/btHgrMBhNlgD8oKNO9rzqCg+RSydprVKmpbYY+j0=
?>
Related
I am trying to create a PHP equivalent to this JS code with CryptoJS:
function aesEncrypt (data) {
const key = 'GSTEGSTEjdfheyhdHSHSHSHDHHDHmdjjdn12ndndn5r=';
const iv = '\0';
const cipher = CryptoJS.AES.encrypt(data, CryptoJS.enc.Base64.parse(key), {
iv: CryptoJS.enc.Utf8.parse(iv), // parse the IV
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
})
return cipher.toString()
}
result of the js code : pHjpwiyKq7Rf4dFcBMbm1w==
here is the PHP code I wrote by reading other stackoverflow questions. But it did not return the same result.
$plaintext = "plainText";
$method = 'aes-256-cbc';
$key = base64_encode("GSTEGSTEjdfheyhdHSHSHSHDHHDHmdjjdn12ndndn5r=");
$iv = hex2bin('00000000000000000000000000000000');
$ciphertext = openssl_encrypt(
$plaintext,
$method,
$key,
OPENSSL_RAW_DATA,
$iv
);
$ciphertext = base64_encode($ciphertext);
echo $ciphertext;
result of the PHP code : +YJOMi2vISmEXIjUZls3MA==
In the PHP code, the key must be Base64 decoded and not Base64 encoded:
$key = base64_decode("GSTEGSTEjdfheyhdHSHSHSHDHHDHmdjjdn12ndndn5r=");
With this change the desired ciphertext is created.
Note that the ciphertext is Base64 encoded by default if 0 is passed instead of OPENSSL_RAW_DATA in the fourth parameter of the openssl_encrypt() call. The explicit Base64 encoding of the ciphertext is then not necessary.
Keep in mind that a static IV is insecure. Usually during encryption a random IV is generated, which is passed to the decrypting side along with the ciphertext (typically concatenated).
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.
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.
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:
Use a better encryption function than mcrypt, see the comment to the question.
Specify no padding in Javascript and manually add zero padding.
Specify no padding in mcrypt and remove the padding manually.
It is better tospecify all options and no to rely on defaults.
This question already has answers here:
Encrypt with CryptoJS and decrypt with PHP
(3 answers)
Closed 6 years ago.
I have the php code as below, and I want to create a Javascript functions that work the same as the php code below. Also, the data that encrypted in Javascript can also decrypt in php.
`
<?php
class Security {
public static function encrypt($input, $key) {
$size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$input = Security::pkcs5_pad($input, $size);
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$data = base64_encode($data);
return $data;
}
private static function pkcs5_pad ($text, $blocksize) {
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
public static function decrypt($sStr, $sKey) {
$decrypted= mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
$sKey,
base64_decode($sStr),
MCRYPT_MODE_ECB
);
$dec_s = strlen($decrypted);
$padding = ord($decrypted[$dec_s-1]);
$decrypted = substr($decrypted, 0, -$padding);
return $decrypted;
}
}
?>
`
Use crypto.js at javascript end. Reference over here
Javascript
var key = CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef");
var iv = CryptoJS.enc.Hex.parse("abcdef9876543210abcdef9876543210");
/*
if you wish to have a more friendly key, you can convert letters to Hex this way:
var a = "D";
var hex_D = a.charCodeAt(0).toString(16);
just to mention,
if it were to binary, it would be:
var binary_D = a.charCodeAt(0).toString(2);
*/
var secret = "secret key goes here";
//crypted
var encrypted = CryptoJS.AES.encrypt(secret, key, {iv : iv});
//and the ciphertext put to base64
encrypted = encrypted.ciphertext.toString(CryptoJS.enc.Base64);
//Assuming you have control on the server side, and know the key and iv hexes(we do),
//the encrypted var is all you need to pass through ajax,
//Let's follow with welcomed pure JS style, to reinforce one and other concept if needed
var xh = new XMLHttpRequest();
xh.open("POST", "php.php", true);
xh.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xh.send("encrypted=" + encodeURIComponent(encrypted));
xh.onreadystatechange = function() {
if (xh.readyState == 4 && xh.status == 200) {
var myArr = (xh.responseText);
console.log(myArr);
}
};
At PHP
<?php
//Here we have the key and iv which we know, because we have just chosen them on the JS,
//the pack acts just like the parse Hex from JS
$key = pack("H*", "0123456789abcdef0123456789abcdef");
$iv = pack("H*", "abcdef9876543210abcdef9876543210");
//Now we receive the encrypted from the post, we should decode it from base64,
$encrypted = base64_decode($_POST["encrypted"]);
$shown = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_CBC, $iv);
echo trim($shown);
//Although the decrypted is shown, there may be needed to trim and str_replace some \r \n \x06 \x05, if there is not a better "trim" way to do it though
?>
You can use JXG compressor too
I'm using blowfish.js on my clientside.
To encrypt on the clientside I use
var encryptedData = blowfish.encrypt(
JSON.stringify(myData), myEncryptionKey, {cipherMode: 0, outputType: 0}
);
That way encryptedData is Base64 encoded blowfish string. It is OK.
To decrypt on the clientside I use
var decryptedData = blowfish.decrypt(
encryptedData , myEncryptionKey, {cipherMode: 0, outputType: 0}
);
So decryptedData equals to JSON.stringify(myData). It is OK.
Then I send my encryptedData to the .php script that contains
$data = $_POST['data'];
$data = mcrypt_decrypt(MCRYPT_BLOWFISH, $myEncryptionKey, pack('H*',$data), MCRYPT_MODE_ECB);
And when I try to print $data I'm getting something unreadable like
�Nv��Xd�̿�:q6��A����,!v��c�O¡1�%>��ҭ� {0�� � ���g�u�����t�z3q$����T��/Ҧ.j-�/!���;�lS���Z�X
��&����{j�m�����F�`7��.......and so on
It isnt OK.
Does anyone know what I'm doing wrong on the server-side?
Why do you pack('H*',$data) as you wrote the data is a base64 encoded string. Just base64_decode the data and pass it to the decrypt function.
$data = $_POST['data'];
$decryptedData = base64_decode($data);
$data = mcrypt_decrypt(MCRYPT_BLOWFISH, $myEncryptionKey, $decryptedData, MCRYPT_MODE_ECB);
i am trying to store some info in my db. One of the fields are Japanese names. I am getting a error:
Warning: #1366 Incorrect string value: '\xE3\x83\xA9\xE3\x83\x87...' for column 'japan-name' at row 1
So i cannot chnage the charset of my db. Can i use PHP or Javascript to convert Japanese/Korean to something else, and them when i go read it, reconvert to Japanese/Korean?
PHP offers the base64_encode() and base64_decode() functions. They are fast, and impose a storage penalty of about 33%. You can use the first to convert your utf-8 east Asian text to what looks like gibberish in ASCII before you store it in your table. The second will convert it back after you retrieve it.
Here's an example:
$jp = " 私はガラスを食べられます。それは私を傷つけません。";
$jpe = base64_encode ($jp);
$jpd = base64_decode ($jpe);
After you run these lines, the $jpe variable has the value
IOengeOBr+OCrOODqeOCueOCkumjn+OBueOCieOCjOOBvuOBmeOAguOBneOCjOOBr+engeOCkuWCt+OBpOOBkeOBvuOBm+OCk+OAgg==
That stores just fine in an ASCII or Latin-1 column.
utf-8 saves the unicode data in table... but other way is to encode and save and then decode and display
update:
searched on web and found answer at How do you Encrypt and Decrypt a PHP String?
define("ENCRYPTION_KEY", "!##$%^&*");
$string = "This is the original data string!";
echo $encrypted = encrypt($string, ENCRYPTION_KEY);
echo "<br />";
echo $decrypted = decrypt($encrypted, ENCRYPTION_KEY);
/**
* Returns an encrypted & utf8-encoded
*/
function encrypt($pure_string, $encryption_key) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);
return $encrypted_string;
}
/**
* Returns decrypted original string
*/
function decrypt($encrypted_string, $encryption_key) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$decrypted_string = mcrypt_decrypt(MCRYPT_BLOWFISH, $encryption_key, $encrypted_string, MCRYPT_MODE_ECB, $iv);
return $decrypted_string;
}