Skip to content

Instantly share code, notes, and snippets.

@emresaracoglu
Forked from ve3/Encryption.js
Created June 28, 2020 18:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emresaracoglu/d6de3d7957f3370f6e7583b08219c793 to your computer and use it in GitHub Desktop.
Save emresaracoglu/d6de3d7957f3370f6e7583b08219c793 to your computer and use it in GitHub Desktop.
Encrypt and decrypt between programming languages (PHP & JavaScript).
/**
* 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($encryptedString, $key)
{
$json = json_decode(base64_decode($encryptedString), true);
try {
$salt = hex2bin($json["salt"]);
$iv = hex2bin($json["iv"]);
} catch (Exception $e) {
return null;
}
$cipherText = base64_decode($json['ciphertext']);
$iterations = intval(abs($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);
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, $key)
{
$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()
{
$number = 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($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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment