I want to encrypt data in livecode using mergAESEncryptWithKey pData,pKey,pIV,[pMode],[pKeySize],[pPadding]. The encrypted data is then posted to php. PhP decrypts the data using the same function, does something with the data and then encrypts the results and posts them to livecode. Livecode then decrypts the data from php
My PHP Code looks like this (This works perfect)
function encrypt($plaintext, $salt) {
$method = "AES-256-CBC";
$key = hash('sha256', $salt, true);
$iv = openssl_random_pseudo_bytes(32);
$ciphertext = openssl_encrypt($plaintext, $method, $key, $iv);
$hash = hash_hmac('sha256', $ciphertext . $iv, $key, true);
return $iv . $hash . $ciphertext;
}
function decrypt($ivHashCiphertext, $salt) {
$method = "AES-256-CBC";
$iv = substr($ivHashCiphertext, 0, 32);
$hash = substr($ivHashCiphertext, 32, 48);
$ciphertext = substr($ivHashCiphertext, 64);
$key = hash('sha256', $salt, true);
//if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true), $hash)) return null;
return openssl_decrypt($ciphertext, $method, $key, $iv);
}
echo $encrypted."</br>";
echo "----------------------------The message is:<br/>";
echo decrypt($encrypted, 'hashsalt');
For most of you who just don't know but still want to post good for nothing comments, I figured it out. #Sammitch and #Mark asking a question don't mean someone is stupid.
/*
* Encrypt or decrypt data using
* AES-256-CBC
*/
function encrypt_decrypt($mode,$data,$key,$salt){
//define the cipher method
$ciphering = "AES-256-CBC";
// Use OpenSSl Encryption method. This works on PHP 7.2 and above
$iv_length = openssl_cipher_iv_length($ciphering);
$options = 0;
if($mode=="encrypt"){
// Use openssl_encrypt() function to encrypt the data
$Data = openssl_encrypt($data, $ciphering, $key, $options, $salt);
}else{
// Use openssl_decrypt() function to decrypt the data
$Data = openssl_decrypt($data, $ciphering, $key,$options, $salt);
}
return $Data;
}
Oooh and this is for livecode
//encrypt
encrypt tString using "aes-256-cbc" with key theKey and IV saltHash at 256 bit
//decrypt
decrypt base64Decode(varEnc) using "aes-256-cbc" with key theKey and IV saltHash at 256 bit
Related
I'm currently implementing encryption on my API. I have to implement this the same way it is encrypted and decrypted in a specific script written in PHP.
This works all fine when I output the result in, let's say, base64. The PHP decrypt method runs against it and works just fine. The problem is that I need to output not in base64 but in binary due to certain requirements, but when I encrypt from the Nodejs side into binary the result is different than when I encrypt in the PHP into binary when it should be the same.
PHP Encryption:
function vd_encrypt($plaintext, $password) {
$method = "AES-256-CBC";
$key = hash('sha256', $password, true);
$iv = openssl_random_pseudo_bytes(16);
$ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
$hash = hash_hmac('sha256', $ciphertext, $key, true);
return $iv . $hash . $ciphertext;
}
Javascript Encryption:
import crypto from 'crypto';
export function encrypt (plain_text: string): string {
const encryptionMethod = 'AES-256-CBC';
const iv = crypto.randomBytes(IV_LENGTH);
const key = crypto.createHash("sha256").update(secret).digest();
var encryptor = crypto.createCipheriv(encryptionMethod, key, iv);
const result = iv + encryptor.update(plain_text, 'utf8', 'binary') + encryptor.final('binary');
return result;
}
I've updated your code slightly to accept an iv parameter. You can generate this in the same way as before (e.g. openssl_random_pseudo_bytes).
For the purposes of demonstration I'll use a fixed IV so we can show the same result.
PHP
function vd_encrypt($plaintext, $password, $iv) {
$method = "AES-256-CBC";
$key = hash('sha256', $password, true);
$ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
$hash = hash_hmac('sha256', $ciphertext, $key, true);
return $iv . $hash . $ciphertext;
}
// Replace with below code in production
// $iv = openssl_random_pseudo_bytes(16);
$iv = base64_decode("eQMrc61Gt8qRejRjhJOkVw==");
$result = vd_encrypt("He was a man take him for all in all, I shall not look upon his like again", "password", $iv);
echo "Result (base64): " . base64_encode($result) . "\n";
Node.js
import crypto from 'crypto';
export function encrypt (plaintext: string, password: string, iv: string): string {
const encryptionMethod = 'AES-256-CBC';
const key = crypto.createHash("sha256").update(password).digest();
const encryptor = crypto.createCipheriv(encryptionMethod, key, iv);
const encryptedData = Buffer.concat([encryptor.update(plaintext, 'utf8'), encryptor.final()]);
const hash = crypto.createHmac("sha256", key).update(encryptedData).digest();
return Buffer.concat([iv, hash, encryptedData]);
}
// Replace with below code in production
//const iv = crypto.randomBytes(16);
const iv = Buffer.from("eQMrc61Gt8qRejRjhJOkVw==", "base64");
const result = encrypt("He was a man take him for all in all, I shall not look upon his like again", "password", iv);
console.log("Result (base64):", result.toString("base64"));
In this case the results will be like so:
PHP:
Result (base64): eQMrc61Gt8qRejRjhJOkVxsqZTqUjSUnaL46yZDLGGK5+o7WKLyIiG4UKj0ST93Wi7UlaAyTFIjpIs0C893SFsnHeuVshG+6EJF99GrLSUCMFJG3J1pJnmxF4Pu8ZCbN7Ounp0BjhJKIpu9yQn6uEYylJLXWpzNw+aCwsnIV1h0=
Node.js:
Result (base64): eQMrc61Gt8qRejRjhJOkVxsqZTqUjSUnaL46yZDLGGK5+o7WKLyIiG4UKj0ST93Wi7UlaAyTFIjpIs0C893SFsnHeuVshG+6EJF99GrLSUCMFJG3J1pJnmxF4Pu8ZCbN7Ounp0BjhJKIpu9yQn6uEYylJLXWpzNw+aCwsnIV1h0=
I am doing encryption which is working good but with same method I am doing decryption I am getting blank string not getting decryption string. I am using method AES-256-ECB and key is hexadecimal so I pass as
$key = pack('H*','xxxxxxxxxxxx');
Encryption is going correct but decryption is not working. Please help me what I am doing wrong.
function encrypt(string $data, string $key, string $method): string
{
$ivSize = openssl_cipher_iv_length($method);
$iv = openssl_random_pseudo_bytes($ivSize);
$encrypted = openssl_encrypt($data, $method, $key, OPENSSL_RAW_DATA, $iv);
$encrypted = strtoupper(implode(null, unpack('H*', $encrypted)));
return $encrypted;
}
function decrypt(string $data, string $key, string $method): string
{
$data = pack('H*', $data);
$ivSize = openssl_cipher_iv_length($method);
$iv = $iv = openssl_random_pseudo_bytes($ivSize);
$decrypted = openssl_decrypt($data, $method, $key, OPENSSL_RAW_DATA, $iv);
return trim($decrypted);
}
Your functions are working perfectly for me with the following code:
$key = pack('H*','aaaaaaaaaaaaa');
$method = 'aes-256-ecb';
$encrypted = encrypt('test string', $key, $method);
$decrypted = decrypt($encrypted, $key.'a', $method);
echo $decrypted; // Output: 'test string'
Since you're getting an empty string for decryption, this means that you've either got the wrong key or cipher text when decrypting. Make sure the key you are using for decryption is exactly the same as the key you're using for encryption, including any manipulations done on it, such as the pack() function you've done here. Even one byte difference and you're not going to be able to decrypt.
Also make sure neither the key nor the cipher text are being truncated when they are stored. If using a database and the column type is too small for what you are trying to store, it will truncate the values.
I have been trying to write two functions that will encrypt and decrypt my data, as I'm storing some information that I don't want going into database in plain text. The function that encrypts works fine. But I don't know why the decryption doesn't bring back the plain text?
Is there something I have done wrong?
<?php
$string = "This is my string!";
$encryption_key = "DVF0!LoQs2bPyTvSF0epXPFStbIn!057";
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(AES_256_CBC));
function encryptString($encryption_key, $iv, $string) {
define('AES_256_CBC', 'aes-256-cbc');
$encrypted = openssl_encrypt($string, AES_256_CBC, $encryption_key, 0, $iv);
return $encrypted;
}
function decryptString($encryption_key, $iv, $encrypted) {
define('AES_256_CBC', 'aes-256-cbc');
$encrypted = $encrypted . ':' . $iv;
$parts = explode(':', $encrypted);
$decrypted = openssl_decrypt($parts[0], AES_256_CBC, $encryption_key, 0, $parts[1]);
return $decrypted;
}
$encryptstring = encryptString($encryption_key, $iv, $string);
$decryptstring = decryptString($encryption_key, $iv, $encryptstring);
?>
Original: <? print $string; ?>
Encryption Key: <?php print $encryption_key; ?>
Encrypted func: <?php print $encryptstring; ?>
Decrypted func: <?php print $decryptstring; ?>
Your encryption key changes with each function call using openssl_random_pseudo_bytes
Make the key static such as $encryption_key = "XXXX"; or global the variable and only call it once.
Don't forget to apply that to your $iv as well.
The command "openssl passwd -1" uses MD5 based BSD password algorithm 1 to compute a string hash.
Example:
openssl passwd -1
$1$./j/us.N$P2tq6IkO0Zu2d3uqkEHpv.
How do I implement exactly the same functionality in PHP? I'd like it to be a native PHP function, rather than something return by exec/shell_exec.
Example code
<?php
define('KEY', 'scret key');
function encrypt($value)
{
$iv = openssl_random_pseudo_bytes(16);
$encrypt = openssl_encrypt($value, 'AES-128-CBC', KEY, 0, $iv);
return base64_encode($encrypt . ':::' . $iv);
}
function decrypt($data)
{
$data = base64_decode($data);
list($data, $iv) = explode(':::', $data);
return openssl_decrypt($data, 'AES-128-CBC', KEY, 0, $iv);
}
$enc = encrypt('password');
echo decrypt($enc);
m using
public function encrypt($plain_str,$key)
{
$str= mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plain_str, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND));
$str = urlencode(base64_encode($str));
return $str ;
}
public function decrypt($cipher_str,$key)
{
$str = urldecode(base64_decode($cipher_str));
return mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND));
}
on crypting :201433~58~g#fds.com~20140820142427
i get : %2BAihYMLwpwrsmL4lSGGzwFTfonvdCyOb%2BCGEUJ%2F%2BE%2F7ZnvgwFRYFtlazQeSrVjUjyaaGZADK8%2BZyynIGxyt4VQ%3D%3D
on decrypting : %2BAihYMLwpwrsmL4lSGGzwFTfonvdCyOb%2BCGEUJ%2F%2BE%2F7ZnvgwFRYFtlazQeSrVjUjyaaGZADK8%2BZyynIGxyt4VQ%3D%3D
i get :201433~58~g#fds.com~20140820142427 back but
when string is malformed like some character removed
like this : %2BAihYMLwpwrsmL4lSGGzwFTfonvdCyOb%2BCGEUJ%2F%2BE%2F7Z
on decrypting i get : 201433~58~g#fds.com~201408201424O#¿W«Gݽˋ¯ È#'oP´ŸØw\Â⦑
How can i detect this anomoly ?
First of all, I'd like to list some flaws in your code:
Don't use ECB mode.
You are encrypting using MCRYPT_RIJNDAEL_128, but you're getting the IV size for MCRYPT_RIJNDAEL_256. (btw, IV is ignored in ECB mode, which is one of the reasons why not to use it)
You are also using MCRYPT_RAND as your randomness source, which is not secure. You should use MCRYPT_DEV_URANDOM (that is also the new default in PHP 5.6).
You don't have to urlencode() the resulting ciphertext, Base64 encoding is URL-safe.
Now, to answer your question ... this is done via a HMAC. The easiest way to use a HMAC is to prepend the cipher-text with it (which you should do with the IV as well; don't worry, it's not a secret):
public function encrypt($plainText, $encKey, $hmacKey)
{
$ivSize = mcrypt_get_iv_size('rijndael-128', 'ctr');
$iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM);
$cipherText = mcrypt_encrypt('rijndael-128', $encKey, $plainText, 'ctr', $iv);
$cipherText = $iv.$cipherText;
$hmac = hash_hmac('sha256', $cipherText, $hmacKey, true);
return base64_encode($hmac.$cipherText);
}
public function decrypt($cipherText, $encKey, $hmacKey)
{
$cipherText = base64_decode($cipherText);
if (strlen($cipherText) <= 32)
{
throw new Exception('Authentication failed!');
}
$recvHmac = substr($cipherText, 0, 32);
$cipherText = substr($cipherText, 32);
$calcHmac = hash_hmac('sha256', $cipherText, $hmacKey, true);
if ( ! hash_equals($recvHmac, $calcHmac))
{
throw new Exception('Authentication failed!');
}
$ivSize = mcrypt_get_iv_size('rijndael-128', 'ctr');
$iv = substr($cipherText, $ivSize);
$cipherText = substr($cipherText, $ivSize);
return mcrypt_decrypt('rijndael-128', $encKey, $cipherText, 'ctr', $iv);
}
Please note that the encryption key and HMAC key are different - they most NOT be the same key. Also, for Rijndael-128, you should create a 128-bit (or 16-byte) random key, it is not something that you can just type in with your keyboard. Here's how to generate one:
$encKey = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);