-
-
Save ve3/0f77228b174cf92a638d81fddb17189d to your computer and use it in GitHub Desktop.
/** | |
* Encryption class for encrypt/decrypt that works between programming languages. | |
* | |
* @author Vee Winch. | |
* @link https://stackoverflow.com/questions/41222162/encrypt-in-php-openssl-and-decrypt-in-javascript-cryptojs Reference. | |
* @link https://github.com/brix/crypto-js/releases crypto-js.js can be download from here. | |
*/ | |
class Encryption { | |
/** | |
* @var integer Return encrypt method or Cipher method number. (128, 192, 256) | |
*/ | |
get encryptMethodLength() { | |
var encryptMethod = this.encryptMethod; | |
// get only number from string. | |
// @link https://stackoverflow.com/a/10003709/128761 Reference. | |
var aesNumber = encryptMethod.match(/\d+/)[0]; | |
return parseInt(aesNumber); | |
}// encryptMethodLength | |
/** | |
* @var integer Return cipher method divide by 8. example: AES number 256 will be 256/8 = 32. | |
*/ | |
get encryptKeySize() { | |
var aesNumber = this.encryptMethodLength; | |
return parseInt(aesNumber / 8); | |
}// encryptKeySize | |
/** | |
* @link http://php.net/manual/en/function.openssl-get-cipher-methods.php Refer to available methods in PHP if we are working between JS & PHP encryption. | |
* @var string Cipher method. | |
* Recommended AES-128-CBC, AES-192-CBC, AES-256-CBC | |
* due to there is no `openssl_cipher_iv_length()` function in JavaScript | |
* and all of these methods are known as 16 in iv_length. | |
*/ | |
get encryptMethod() { | |
return 'AES-256-CBC'; | |
}// encryptMethod | |
/** | |
* Decrypt string. | |
* | |
* @link https://stackoverflow.com/questions/41222162/encrypt-in-php-openssl-and-decrypt-in-javascript-cryptojs Reference. | |
* @link https://stackoverflow.com/questions/25492179/decode-a-base64-string-using-cryptojs Crypto JS base64 encode/decode reference. | |
* @param string encryptedString The encrypted string to be decrypt. | |
* @param string key The key. | |
* @return string Return decrypted string. | |
*/ | |
decrypt(encryptedString, key) { | |
var json = JSON.parse(CryptoJS.enc.Utf8.stringify(CryptoJS.enc.Base64.parse(encryptedString))); | |
var salt = CryptoJS.enc.Hex.parse(json.salt); | |
var iv = CryptoJS.enc.Hex.parse(json.iv); | |
var encrypted = json.ciphertext;// no need to base64 decode. | |
var iterations = parseInt(json.iterations); | |
if (iterations <= 0) { | |
iterations = 999; | |
} | |
var encryptMethodLength = (this.encryptMethodLength/4);// example: AES number is 256 / 4 = 64 | |
var hashKey = CryptoJS.PBKDF2(key, salt, {'hasher': CryptoJS.algo.SHA512, 'keySize': (encryptMethodLength/8), 'iterations': iterations}); | |
var decrypted = CryptoJS.AES.decrypt(encrypted, hashKey, {'mode': CryptoJS.mode.CBC, 'iv': iv}); | |
return decrypted.toString(CryptoJS.enc.Utf8); | |
}// decrypt | |
/** | |
* Encrypt string. | |
* | |
* @link https://stackoverflow.com/questions/41222162/encrypt-in-php-openssl-and-decrypt-in-javascript-cryptojs Reference. | |
* @link https://stackoverflow.com/questions/25492179/decode-a-base64-string-using-cryptojs Crypto JS base64 encode/decode reference. | |
* @param string string The original string to be encrypt. | |
* @param string key The key. | |
* @return string Return encrypted string. | |
*/ | |
encrypt(string, key) { | |
var iv = CryptoJS.lib.WordArray.random(16);// the reason to be 16, please read on `encryptMethod` property. | |
var salt = CryptoJS.lib.WordArray.random(256); | |
var iterations = 999; | |
var encryptMethodLength = (this.encryptMethodLength/4);// example: AES number is 256 / 4 = 64 | |
var hashKey = CryptoJS.PBKDF2(key, salt, {'hasher': CryptoJS.algo.SHA512, 'keySize': (encryptMethodLength/8), 'iterations': iterations}); | |
var encrypted = CryptoJS.AES.encrypt(string, hashKey, {'mode': CryptoJS.mode.CBC, 'iv': iv}); | |
var encryptedString = CryptoJS.enc.Base64.stringify(encrypted.ciphertext); | |
var output = { | |
'ciphertext': encryptedString, | |
'iv': CryptoJS.enc.Hex.stringify(iv), | |
'salt': CryptoJS.enc.Hex.stringify(salt), | |
'iterations': iterations | |
}; | |
return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(JSON.stringify(output))); | |
}// encrypt | |
} |
<?php | |
/** | |
* Encryption class for encrypt/decrypt that works between programming languages. | |
* | |
* @author Vee Winch. | |
* @link https://stackoverflow.com/questions/41222162/encrypt-in-php-openssl-and-decrypt-in-javascript-cryptojs Reference. | |
*/ | |
class Encryption | |
{ | |
/** | |
* @link http://php.net/manual/en/function.openssl-get-cipher-methods.php Available methods. | |
* @var string Cipher method. Recommended AES-128-CBC, AES-192-CBC, AES-256-CBC | |
*/ | |
protected $encryptMethod = 'AES-256-CBC'; | |
/** | |
* Decrypt string. | |
* | |
* @link https://stackoverflow.com/questions/41222162/encrypt-in-php-openssl-and-decrypt-in-javascript-cryptojs Reference. | |
* @param string $encryptedString The encrypted string that is base64 encode. | |
* @param string $key The key. | |
* @return mixed Return original string value. Return null for failure get salt, iv. | |
*/ | |
public function decrypt(string $encryptedString, string $key) | |
{ | |
$json = json_decode((string) base64_decode($encryptedString), true); | |
// check array keys must exists to prevent errors. | |
if ( | |
!is_array($json) || | |
!array_key_exists('salt', $json) || | |
!array_key_exists('iv', $json) || | |
!array_key_exists('ciphertext', $json) || | |
!array_key_exists('iterations', $json) | |
) { | |
return null; | |
} | |
try { | |
$salt = hex2bin($json['salt']); | |
$iv = hex2bin($json['iv']); | |
} catch (\Exception $e) { | |
return null; | |
} | |
$cipherText = base64_decode($json['ciphertext']); | |
$iterations = intval(abs((int)$json['iterations'])); | |
if ($iterations <= 0) { | |
$iterations = 999; | |
} | |
$hashKey = hash_pbkdf2('sha512', $key, $salt, $iterations, ($this->encryptMethodLength() / 4)); | |
unset($iterations, $json, $salt); | |
$decrypted= openssl_decrypt($cipherText , $this->encryptMethod, hex2bin($hashKey), OPENSSL_RAW_DATA, $iv); | |
if (!is_string($decrypted)) { | |
$decrypted = null; | |
} | |
unset($cipherText, $hashKey, $iv); | |
return $decrypted; | |
}// decrypt | |
/** | |
* Encrypt string. | |
* | |
* @link https://stackoverflow.com/questions/41222162/encrypt-in-php-openssl-and-decrypt-in-javascript-cryptojs Reference. | |
* @param string $string The original string to be encrypt. | |
* @param string $key The key. | |
* @return string Return encrypted string. | |
*/ | |
public function encrypt(string $string, string $key): string | |
{ | |
$ivLength = openssl_cipher_iv_length($this->encryptMethod); | |
$iv = openssl_random_pseudo_bytes($ivLength); | |
$salt = openssl_random_pseudo_bytes(256); | |
$iterations = 999; | |
$hashKey = hash_pbkdf2('sha512', $key, $salt, $iterations, ($this->encryptMethodLength() / 4)); | |
$encryptedString = openssl_encrypt($string, $this->encryptMethod, hex2bin($hashKey), OPENSSL_RAW_DATA, $iv); | |
$encryptedString = base64_encode($encryptedString); | |
unset($hashKey); | |
$output = ['ciphertext' => $encryptedString, 'iv' => bin2hex($iv), 'salt' => bin2hex($salt), 'iterations' => $iterations]; | |
unset($encryptedString, $iterations, $iv, $ivLength, $salt); | |
return base64_encode(json_encode($output)); | |
}// encrypt | |
/** | |
* Get encrypt method length number (128, 192, 256). | |
* | |
* @return integer. | |
*/ | |
protected function encryptMethodLength(): int | |
{ | |
$number = (int) filter_var($this->encryptMethod, FILTER_SANITIZE_NUMBER_INT); | |
return intval(abs($number)); | |
}// encryptMethodLength | |
/** | |
* Set encryption method. | |
* | |
* @link http://php.net/manual/en/function.openssl-get-cipher-methods.php Available methods. | |
* @param string $cipherMethod | |
*/ | |
public function setCipherMethod(string $cipherMethod) | |
{ | |
$this->encryptMethod = $cipherMethod; | |
}// setCipherMethod | |
} |
<?php | |
$nonceValue = 'nonce_value';// use nonce that generated while using OAuth. | |
$readableString = 'asdf-ghjk-qwer-tyui'; | |
$encryptedString = 'eyJjaXBoZXJ0ZXh0IjoiNkRuSzRueVR5aERIQTVCdkF6SU9Mc0E0S1llUW5tZndvS0hIbERRMlE1VT0iLCJpdiI6IjNlNGU0YjFlNTBjNGRmODc2ZWExZTg3NjY3MDc4ZjBkIiwic2FsdCI6IjY0OWUxZDQ0NGNiZDc1YjBhODk2NmY2YTRjZTNjYzUzMmIyYTA4ZDQzZjlmYTQzNDRiOGU2MDFmNWIxODlkNzFjZGE3ZDc1YzU1YTBjMzNhMmM1ZWRlMjc5MTMxZTM5ZjNhYjgzY2JjNGQ5ZjIwYmY5YWE3YjdjN2MwNmVlMTZmNjJmYWEzMWU1MjFiMWZjNWFmZDcxMmRlNDQ3MWEyOTg3MDM0MzliODk0N2E0NGViOTMyMWFlMzI0ZWM2Zjg1ZjkwYmQzYzRmNjk5YzdmN2ViMTVhOGE0ZWExYjU1OGJmNWFiYjg5MzFjMjA5YTkzMWEwY2Q1NWM1NTgxMTRkNTY5NTIzZTk5OWMwZDA4Y2FiYmY4MzAzMTA0MzJkNzE2NmJlMDZlYzk3NjQzNzY1MzQ2NDI4YTM0ODM3MWUyOWRkNDU2ZTVmOGQ0NDgxZGVmZjY4M2FlOGYwOTJjODk3NjdhMzRhN2I0MWNlM2VlMDVlOWQ2ZDg4ZDI5MzVmZGM5MDUxY2VlZDhiYjllZDM5MzNjNjg2ODczZGNiOTJhZWI2MzBkMjNjODNhMjIyNTRjZDkxMDg4OTc4OWQ1MTI1MTc2MjQ2ZGYwOTQyODE5MTZlMmY4Y2RjYTU2MDEwMzEzZTM2NmE2ZDMyOTA4OGM3NzI5MWY3NDE3ODRiNTdmNTc1IiwiaXRlcmF0aW9ucyI6OTk5fQ=='; | |
?> | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<link rel="stylesheet" href="style.css"> | |
</head> | |
<body> | |
<div class="resultPlaceholder"></div> | |
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> | |
<script src="crypto-js.js"></script><!-- https://github.com/brix/crypto-js/releases crypto-js.js can be download from here --> | |
<script src="Encryption.js"></script> | |
<script> | |
var readableString = '<?php echo $readableString; ?>'; | |
var nonceValue = '<?php echo $nonceValue; ?>'; | |
var encryptedString = '<?php echo $encryptedString; ?>'; | |
// on page loaded. | |
jQuery(document).ready(function($) { | |
let encryption = new Encryption(); | |
var encrypted = encryption.encrypt(readableString, nonceValue); | |
console.log(encrypted); | |
var decrypted = encryption.decrypt(encrypted, nonceValue); | |
console.log(decrypted); | |
var decryptedOldString = encryption.decrypt(encryptedString, nonceValue); | |
console.log(decryptedOldString); | |
$('.resultPlaceholder').html('readable string: '+readableString+'<br>'); | |
$('.resultPlaceholder').append('encrypted: '+encrypted+'<br>'); | |
$('.resultPlaceholder').append('decrypted: '+decrypted+'<br>'); | |
$('.resultPlaceholder').append('decrypted from old encrypted string: <strong>'+decryptedOldString+'</strong><br>'); | |
}); | |
</script> | |
</body> | |
</html> |
<?php | |
require 'Encryption.php'; | |
$nonceValue = 'nonce_value';// use nonce that generated while using OAuth. | |
$readableString = 'asdf-ghjk-qwer-tyui'; | |
$encryptedString = 'eyJjaXBoZXJ0ZXh0IjoiNkRuSzRueVR5aERIQTVCdkF6SU9Mc0E0S1llUW5tZndvS0hIbERRMlE1VT0iLCJpdiI6IjNlNGU0YjFlNTBjNGRmODc2ZWExZTg3NjY3MDc4ZjBkIiwic2FsdCI6IjY0OWUxZDQ0NGNiZDc1YjBhODk2NmY2YTRjZTNjYzUzMmIyYTA4ZDQzZjlmYTQzNDRiOGU2MDFmNWIxODlkNzFjZGE3ZDc1YzU1YTBjMzNhMmM1ZWRlMjc5MTMxZTM5ZjNhYjgzY2JjNGQ5ZjIwYmY5YWE3YjdjN2MwNmVlMTZmNjJmYWEzMWU1MjFiMWZjNWFmZDcxMmRlNDQ3MWEyOTg3MDM0MzliODk0N2E0NGViOTMyMWFlMzI0ZWM2Zjg1ZjkwYmQzYzRmNjk5YzdmN2ViMTVhOGE0ZWExYjU1OGJmNWFiYjg5MzFjMjA5YTkzMWEwY2Q1NWM1NTgxMTRkNTY5NTIzZTk5OWMwZDA4Y2FiYmY4MzAzMTA0MzJkNzE2NmJlMDZlYzk3NjQzNzY1MzQ2NDI4YTM0ODM3MWUyOWRkNDU2ZTVmOGQ0NDgxZGVmZjY4M2FlOGYwOTJjODk3NjdhMzRhN2I0MWNlM2VlMDVlOWQ2ZDg4ZDI5MzVmZGM5MDUxY2VlZDhiYjllZDM5MzNjNjg2ODczZGNiOTJhZWI2MzBkMjNjODNhMjIyNTRjZDkxMDg4OTc4OWQ1MTI1MTc2MjQ2ZGYwOTQyODE5MTZlMmY4Y2RjYTU2MDEwMzEzZTM2NmE2ZDMyOTA4OGM3NzI5MWY3NDE3ODRiNTdmNTc1IiwiaXRlcmF0aW9ucyI6OTk5fQ=='; | |
?> | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<link rel="stylesheet" href="style.css"> | |
</head> | |
<body> | |
<?php | |
echo 'readable string: ' . $readableString . '<br>'; | |
$Encryption = new Encryption(); | |
$encrypted = $Encryption->encrypt($readableString, $nonceValue); | |
echo 'encrypted: ' . $encrypted . '<br>'; | |
echo "\n\n\n"; | |
echo '<hr>'; | |
echo "\n\n\n"; | |
$decrypted = $Encryption->decrypt($encrypted, $nonceValue); | |
echo 'decrypted: ' . $decrypted . '<br>'; | |
$decrypted = $Encryption->decrypt($encryptedString, $nonceValue); | |
echo 'decrypted from old encrypted string: <strong>' . $decrypted . '</strong><br>'; | |
?> | |
</body> | |
</html> |
@maulvi The nonce value must be match or the same because it is the key. If you had run my test files (test-js.php, test-php.php) without any modification and it work properly then it means it is working, the trouble maybe from key changed.
@maulvi The nonce value must be match or the same because it is the key. If you had run my test files (test-js.php, test-php.php) without any modification and it work properly then it means it is working, the trouble maybe from key changed.
yes I tried mine working just fine the decrypted value is appear in console but not in browser page :(, idk if it's because html source.
here's screenshot https://i.imgur.com/yTgmTEb.png
https://gist.github.com/maulvi/f5e6d8005a5fc3d06a81396db966b5c1
I confirm it is working. Here is example https://jsfiddle.net/xb5Lteqk/
If something wrong, please carefully check your code.
The encrypted can be decrypt by using the same 'key' as when it was encrypted. The key must be same.
I made a implementation in angular
with typescript
and works perfectly, nice work, thanks bro 🍻
Thank you so much. It helped me post a large html code to the server
not working in ie and edge browser
https://jsfiddle.net/xb5Lteqk/
It is working on MS Edge 44.18362.449.0, EdgeHTML 18.18363
Md5 encode your encrypted data
I use it through php encrypt a jpeg file then use js decrypt appear js error.
I have never encrypt/decrypt jpeg (binary) file. I'm not sure how you do it.
Do you base64 the file content before doing this or not?
If it is string, number, any text please try it with my demo here -> https://jsfiddle.net/xb5Lteqk/
You may change my encrypted string to yours and check if it is working or not.
yes. It's need base64. I'm also try it for other type files like docx, xls etc...
Is it possible this could be updated for PHP 8?
Fatal error: Uncaught TypeError: abs(): Argument #1 ($num) must be of type int|float, string given in Encryption.php
Is it possible this could be updated for PHP 8?
Fatal error: Uncaught TypeError: abs(): Argument #1 ($num) must be of type int|float, string given in Encryption.php
Fixed, please update your Encryption.php.
@ve3 The encrpty value is to long, How to make it a short?
@jafarpagerjaya Maybe use another method of encryption. See ...
https://crypto.stackexchange.com/questions/63022/what-is-the-shortest-type-of-text-encryption
Can you help me to develop Encryption.js like encryption in java android?
@Mayuri-JoshiA Sorry, I don't know JAVA.
@maulvi The nonce value must be match or the same because it is the key. If you had run my test files (test-js.php, test-php.php) without any modification and it work properly then it means it is working, the trouble maybe from key changed.
That helped
thanks a lot for this
edit: well I was able to encrypt html source but got some trouble print decrypted output
any help would be appreciated, thanks.
here's my encrypted value
$nonceValue = 'lol'; $readableString = 'xxx'; $encryptedString = 'eyJjaXBoZXJ0ZXh0IjoiTUlTbURQZThWQ1puQm9wT1ZVVjg0T0pLWkJ0UzIwRGp0SkRWWkduRVo5MExDa3JyZitFM2N2UEhMUlNvVW1scGxyS1BBdERWNWt5OHNjNUtQUEpZUUI0bW9YOGh2R0ZBQmZyeWozMFpkUHlORFlKZWo0elI3WkZtV09vN1kwV1dYNUdNYW9RcGZCbEFyRDAwXC9aK01rK0JZc3NqcGhzc0pvSStKSXdPYnlDclc4MDVDdXpONVA5R0N3S0QrTUtDbGJyTERvRWVjOXBvSWgzK3Y0S3o1XC95cG05ZkpIbzBCOUJxYTFVSkVyMmc2NGNIRkJVWmR5SVZRZDVzWTFQXC8zdnBLZTlVVlU4dkpyWm9ybjhRMlJtNWhkM3JRXC9VRWpjNEh5T3AzUG9vZ2wydGZjNGo3ZDh3aUNKQlwvTXlIcEFOczZYR0pxVXNrcXBZdHl0alpUbUNqZW4wODlsb1ltbFlpUTh4SnFkZUxBM0gwOUtVVlJyV3Q0dFplbXYzVUtIY2ZZYXJubWxiaUMwYjJZMmNmTmdWXC9QdVZpZGNuRnkrNGtudkJFTnN6XC83ZnhYWWJUdzhPVVZqWTF0RFlqSGdIY1R2TCtwRUdoalppYW8xT3EwYUkwZHRpSnVWRndSYmgzR1RON0ZCdldTWjh6Slg5eU42d0ZTUVRRd2FSZmJ1b2ZlS0VuYlhZcFpNQlJcL0c4SitRbzVRNlVSRytJZUkyWlRGWHhaZmlTeEYzbGhrTlBMeUtBZ0dXUHNLUGxvNlVKY0E0eWN2KzN1b1NzSWxSTis3eHRQa04xd2JYTkFpV0IxSVJzRUVkKzhtUW90ODR1NmorUVlOcDZvU1padUkzTnV4K0JTcWZHVWZMWDc1aXNsYlwvSk5pVndjOU5ZcG1jeE11cjBjRlBhTWJmQ1RtUEVmazgrVWtLY3RXYVQwWkpDUzU5OW00cUFyNTE1S2V6MXZhaFR4c2NzeHE1TE5yOU0xYzNJSm85Ym9KMlwvQXVPc0JMZk1peWtYYU40Qmw1a3JkcVJrcUI3NUNIdnVoZStuR0dCMkhEM0NFT3RQMWNsTTZFZFQzYWN1SlJlczNFTmZiTVBxM1lzNFUrdzJuWVRVd21MMzNBNUt4RUMza1ZmNmRPZ2tuTUNBRmswcXhwYzE3aUxrRjBxdWEyVzFzPSIsIml2IjoiMTc1MTQ0YmJjYjM2OGZhYWQ2Y2IyYzk2MWUxNDQyZDEiLCJzYWx0IjoiZDQ3ODM2NTRlYzY1NTRjMjUzNzg2ZDU3NTM4Zjc1MDE4MjA2NDdkOTc4N2Q2OTYyMDUyZGEzNGFlNjg3YzE2ZWIyYzRjZjdlMTEzNGI4N2QyNTE1MjMzNzY0NTVmMDFiMGU5ZjNjZmRlNjE4YmMyMDM2NzViNDNlM2Q3MWQ1ODQ4ZDg5MTc0YWFhYzdmMDBiNzU1NWQ1MzZhNjE1ZjM4YzMzMDBjMGQzZmFiNGJkNzY1Y2IwNzVhOWRlOWUwZGRmYWMyYzg1N2Y4ZjE5NzcwNTAxYmVhMzkzMGFiYTc0MGNmZDBlOWFiYzYyMjUyZDM0ZmQxNTFhN2U3MTA2OGYzMTY1OGRjNDA0NmYwZTM1NTIyYTVkOTQ4MDA1MzNiNmFjMDdmMGQ0NDNkMWMyZjBiNmZiYTU1YjUwMGM5NGJhOWVjZTE4YjQ1MWJjNWY2MTc3NTFmN2YzOWNjMGY0ZmI4YWQyMzc1OTY2YmI1ZmZjMjJjNjA0ZWUwN2FlMDM3MjY4ZTgxNTM5MWY4YWY5OTFmNWIyZDFjMWY0MzAwZjEzNDg2N2U1ZjIyMGU2NzUxM2IxMDc5MDNlNTI4Y2VjYzJlNTI3MTAzYTkyY2Y1MWZhZTA5YTE1NTA4ZDlmNTIzMDRiNWNjYzJiMzEwNmQ5OTY4M2Y1ODEyMzVhOWUwMGNiZGMiLCJpdGVyYXRpb25zIjo5OTl9';