Am working on a project where the data stored in the qrCode must be encrypted for security reasons,
so i have encrypted the data ( which plain text ) using openssl
I have saved the QrCode image on the local directory (public/images)
now in order to scan the content of the image i have used the Zxing library,
i have succefully gotten the encrypted text ,now i need to decode it.
this the " decrypting code " :
$secretKey = "glop";
$iv = random_bytes(16);
$qrcode = new QrReader('images/qr/sb.png');
$decrypted = openssl_decrypt($qrcode->text(), "AES-128-CBC", $secretKey,0,$iv);
dd($decrypted); //return decoded text from QR Code
by the way the dump function is echoing " False "
what is it that i am doing wrong ?
When decryption CBC mode the IV must be the same IV that was used for encryption.
The IV needs to be random for each encryption, just prefix the encrypted data with the IV for use in decryption, it does not need to be secret.
Related
I'm using phplibsec to do some encryption operations. The library has a method to set the IV and I'm using it to generate a random initialization vector to use in encrypt operations. The problem is that I need to have the same IV to decrypt the data (I didn't know this aspect). Now after small code modification I want to prepend the generated IV to the encrypted data but I don't know how to proceed.
encrypt.php
use phpseclib\Crypt\AES;
use phpseclib\Crypt\Random;
$payload = [];
// new phpseclib AES instance
$cipher = new AES();
// set a password for the encrypt
$cipher->setPassword($password);
// IV creation
$iv = Random::string($cipher->getBlockLength() >> 3);
// this method of the library will make the forst part of my data unreadable without iv
$cipher->setIV($iv);
// encrypt data - here I want to prepend the iv to get it later on decrypt
$output = $cipher->encrypt("some data");
// push encrypted data into an array
array_push($payload, $output);
decrypt.php
use phpseclib\Crypt\AES;
use phpseclib\Crypt\Random;
$cipher = new AES();
$cipher->setPassword($password);
// here is my mistake - I'm creating a new IV but I need the same
$cipher->setIV(Random::string($cipher->getBlockLength() >> 3));
// opening the file that hold encrypted data
$payload = file_get_contents('myencrypted.file');
// I've used the : to separate each line of encrypted data with php implode()
$exploded = explode(' : ', $payload);
// iterating over the array that hold encrypted data to decrypt them then base64_encode before pass back to the client in json.
foreach( $exploded as $str ){
array_push($output, base64_encode($cipher->decrypt($str) ));
}
The decrypt operation will give me something similar (I'm encrypting images data uri)
XGG”)”>hÑÏÄr*‹base64,/9j/4AAQSkZJRgABAgAAAQABAAD…D8
I think that this part XGG”)”>hÑÏÄr*‹ of the decrypted data is the IV?
How I can prepend or append it to the encrypted data and then extrac it when the data needs to be decrypted?Can anyone help me please?
UPDATE
I've followed the suggestion of Topaco in comments and now I'm able to get back the data uri but it will have the iv attached so I need to remove it. At the moment after decrypt the data uri will have this structure:
¸ÈouFH#¬ÆÌ~k!Eâdata:image/jpeg;base64,/9j/4AAQSk
How I will remove the part before the data:image/jpeg;base64 ?
I'm using phpseclib to encrypt/decrypt data uri of some images. I've noticed that when I'm using the IV the data:image/png;base64,data:image/jpg;base64,data:image/jpeg;base64 part of the passed data uri will be lost, only the rest of the base64 string will remain and I will be unable to display the images after decryption operations. Is possible to use the IV without loosing the that part of each data uri encrypted?
//data URI creation from uploaded image using PHP-dataURI https://github.com/alchemy-fr/PHP-dataURI
$dataObject = DataURI\Data::buildFromFile('myimage.jpg');
//data URI encrypt
$cipher = new AES();
//set password for encryption
$cipher->setPassword($password);
//set the IV - this will corrupt data uri generated
$cipher->setIV(Random::string($cipher->getBlockLength() >> 3));
//encrypting the data
$output = $cipher->encrypt(DataURI\Dumper::dump($dataObject));
This is the way I've used to solve this issue. I'm new to phplibsec so I was using $cipher->setIV(Random::string($cipher->getBlockLength() >> 3)) method in a wrong way to set and read the IV. The phpseclib documentations are not very useful and lack of examples on how to implement correctly encrypt and decrypt methods, in particular no example of how to manage the IV is provided. After some research here on SO and thanks to the help of community, I've figured out how to manage the IV.
Encryption of the data uri:
//data URI creation from uploaded image using PHP-dataURI https://github.com/alchemy-fr/PHP-dataURI
$dataObject = DataURI\Data::buildFromFile('myimage.jpg');
//data URI encrypt
$cipher = new AES();
//set password for encryption
$cipher->setPassword($password);
//random IV creation
$iv = Random::string($cipher->getBlockSize() >> 3);
//set the IV
$cipher->setIV($iv);
//encrypting the data
$encrypted = $cipher->encrypt(DataURI\Dumper::dump($dataObject));
//output
$output = $iv.$encrypted;
Into the encryption script I've assigned the random generated IV to a variable that after encryption is prepended to the encrypted data. This because the IV is needed to decrypt correctly the data and this imply that it need to be stored in a database or appended/prepended to the data (no, there is no security risk by doing this). The prepended IV then can be extracted from the encrypted data using the substr() function in this way:
//data URI decrypt
$cipher = new AES();
//set previously selected password for encryption
$cipher->setPassword($password);
//extract the IV from encrypted data
$ivLength = $cipher->getBlockLength() >> 3;
$iv = substr($encrypted, 0, $ivLength);
//set the IV
$cipher->setIV($iv);
//removing the IV from the data before decrypt
$data = substr($encrypted, $ivLength);
//decrypting the data
$output = $cipher->decrypt($data);
After the decrypt the original base64 data uri will be returned back as expected.
I have this issue where something is encrypted in python using aes 256 cbc encryption as shown in the python codes encrypt method .
I am trying to create a Decrypt method in php to actually decrypt whats encrypted using the python class .
Here is my attempt to convert the python decryption method to php does it look right or am I missing something in my conversion as every time i use the php version to decrypt it says hmac failed ?
anyhelp in converting the python class to php i will appreciate.
public function decrypt(){
$encrypt_method ="AES-256-CBC";
$secret_key =base64_decode('samekeyusedintheencryption');
$encrypted=(string)'some encrypted text to be decrypted';
$data=json_decode(base64_decode($encrypted),true);
$secret_iv =base64_decode($data['iv']);
$output = \openssl_decrypt($data['value'],
$encrypt_method,$secret_key,0,$secret_iv);
return json_encode($output);
}
def decrypt(self, payload):
data = json_c.decode(base64.b64decode(payload))
value = base64.b64decode(data['value'])
iv = base64.b64decode(data['iv'])
crypt_object=AES.new(self.key,AES.MODE_CBC,iv)
plaintext = crypt_object.decrypt(value)
return loads(plaintext)
OK, I got it to work!
function decrypt($encryptedText, $secret_key){
$secret_key = base64_decode($secret_key);
$encrypt_method ="AES-256-CBC";
$data = json_decode(base64_decode($encryptedText),true);
$data['iv'] = base64_decode($data['iv']);
$data['value'] = base64_decode($data['value']);
return openssl_decrypt($data['value'], $encrypt_method, $secret_key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $data['iv']);
}
Some things I learned:
If the options in the openssl function are set to '0' it expects a base64_encoded input for the cipher text. Also, if the default options is set to '0' the padding default is set to PKCS#7. This, I think, is why we were getting the bad block size error.
So, the cipher text needs to be base64_decoded and we need to set both options for the padding.
I was able to decrypt your provided cipher text and see the email addresses.
You are provided the MAC in the Data array so this would allow you to check the MAC in the PHP script. This allows you to make sure the data has not been tampered with.
I recently did an encryption project and started with the open ssl, but ended up changing to the libSodium library. I highly recommend you check it out for any further projects.
Cheers!
I'm a noob developer and I'm trying to decrypt some data but when I use OpenSSL in PHP I received no response. Also, when trying to encrypt data OpenSSL add a block of characters.
This is the code:
<?php
$dataToDecrypt = hex2bin("C2E5CDFE8BBFBC7350D40538434824DD3E11520B89A5BFDE24FA064DB2EED6EA");
$aesKey = hex2bin("E3FB8EA130722FA99266B96B77C2735C39393939393939393920202020202020");
$iv = hex2bin("00000000000000000000000000000000");
$result = openssl_decrypt($dataToDecrypt, 'AES-256-CBC', $aesKey, OPENSSL_RAW_DATA, $iv);
echo bin2hex($result);
?>
The $result is supposed to be:
C3A6149C73FFBE4EAD36DC62FE40877D17CD690F37B06058CA3D65A345CC8212
I've tried this on VB and even in a AES encription web page (http://aes.online-domain-tools.com/) and the result is correct. But when trying with PHP I've got no answer.
I noticed when encrypting with the same information, the encrypted data is different. This is the code:
<?php
$dataToEncrypt = hex2bin("C3A6149C73FFBE4EAD36DC62FE40877D17CD690F37B06058CA3D65A345CC8212");
$aesKey = hex2bin("E3FB8EA130722FA99266B96B77C2735C39393939393939393920202020202020");
$iv = hex2bin("00000000000000000000000000000000");
$result = openssl_encrypt($dataToEncrypt, 'AES-256-CBC', $aesKey, OPENSSL_RAW_DATA, $iv);
echo bin2hex($result);
?>
When I encrypt the result is:
C2E5CDFE8BBFBC7350D40538434824DD3E11520B89A5BFDE24FA064DB2EED6EA3A3ED407DC78D6AF9030BAB90CB40EAD
I get 32 characters more than expected (3A3ED407DC78D6AF9030BAB90CB40EAD). When I encrypt in VB or using the web page mentioned before I don't get these 32 extra characters.
Why is this happening? Am I missing something? I've been searching for an answer for several days. Any help is appreciated.
To see something during PHP decrypt you need to turn on warning messages.
Essentially the openssl_decrypt call will first decrypt your ciphertext. As long as your ciphertext is a multiple of 16 bytes (the block size of AES) this will always succeed. After that it will try and perform PKCS#7 compatible unpadding, which will fail (with high probability). To make it not unpad, use the OPENSSL_ZERO_PADDING in addition to OPENSSL_RAW_DATA.
The same goes for your encryption function of course. Currently you receive the ciphertext of the padded plaintext. This will add exactly one block of padding if the input plaintext is a multiple of the block size (and it is in your sample code). So you need OPENSSL_ZERO_PADDING there as well.
In our application we are getting encrypted text from external server. This text have been encrypted using openssl in php.
When I am trying to decrypt the text in my Ruby code, I am getting following error message:
OpenSSL::Cipher::CipherError: wrong final block length
I read couple of solutions on Stackoverflow and was suggest to add following line to the code cipher.padding = 0. But after adding padding = 0, I am getting different error:
OpenSSL::Cipher::CipherError: data not multiple of block length
Below is my rough script I have written to decrypt the code.
require 'openssl'
require 'digest/sha1'
require 'base64'
encrypted = "VaZYJzn9QVEQIH4fmtA1Cg=="
key = "my_secret_key"
cipher = OpenSSL::Cipher::Cipher.new("aes-128-ecb")
cipher.decrypt
cipher.padding = 0
cipher.key = key
decrypted = cipher.update(encrypted)
decrypted << cipher.final
puts Base64.decode64(decrypted)
If I encrypt the text using Ruby then I can easily decrypt it. I am having problem to decrypt the code which are encrypted in php. Is there any way I can make encryption and decryption compatible between php and Ruby.
Simply change the way you call it.
From decrypted << cipher.final to decrypted = cipher.update(encrypted) + cipher.final
could get the string like
<GF\x8F\xDC\x91\xE1ew\xB1\x1C\xE8\xF8V\xA0\x99g\x01C\xCDF\xD6\v\x841l\x13\xA6\x9496{
Last, quote from Ruby Doc You should never use ECB mode unless you are absolutely sure that you absolutely need it