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 ?
Related
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!
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.
phpseclib:
php code :
include('Crypt/RSA_XML.php');
$rsa = new Crypt_RSA_XML();
$rsa->loadKeyfromXML($public_key_xml);
$data = "invoice_number=1,100.00&customer_tin=674858994885&serial=ONLYPEMPSERIAL&tin=ONLYPUMPTIN&vat_1_net=2,0000&vat_1_value=3600&vat_2_net=0&vat_2_value=0&vat_3_net=0&vat_3_value=0&vat_4_net=0&vat_4_value=0&vat_5_net=0&vat_5_value=0&vat_6_net=0&vat_6_value=0&vat_7_net=0&vat_7_value=0&vat_8_net=0&vat_8_value=0&payment_mode=3&discount=200&total_gross=9562";
$plaintext = $data;
//define('CRYPT_RSA_PKCS15_COMPAT', true);
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$ciphertext = base64_encode(strrev($rsa->encrypt($plaintext)));
echo "data";
echo $ciphertext; // there is encoded value getting
and
then how to decrypt encrypted data using private key:
echo $rsa->decrypt($ciphertext); // this is giving error , decryption error
actually , i want to encrypt in php and decrypt in c# ,
data encrypted successfully and when c# rsa crypto service decrypt this encrypted data then giving error message : invalid base-64 string length
$public_key_xml and $private_key_xml is defined below...
public key :
<RSAKeyValue>
<Modulus>uidt3bPfWozkIkC6nHnRDbXrvjqplfCslV2zP4hKJ6sVjVnPfjMM0ueCuEDFZ9NK+kCWaPNAVhOKKwL8HmoX/7KcFLWkwSoatnrncHTH5STey+bqR1xTFY+Rubj8BZt7D9JJYyLQC46wn4ySVnLWkCZZ9+aaTriEBzGTpUzeRiUTWVprp3oXsA7ZKyn+lhZfMx1ILhcD8dnX7xFHB57jIKvPBxAdT4K7GxdgENeS76I/zmVmlF//JnmtZ/RM1WmRkx8mFmcK/Ky8gLsmIpPPltoyBWIKIf2NQH9kHqHa2gwoPg34LTutV9AACTWuiVOjqU7Gq2BHQcjovXMF8t3Wiw==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
private key :
<RSAKeyValue>
<Modulus>uidt3bPfWozkIkC6nHnRDbXrvjqplfCslV2zP4hKJ6sVjVnPfjMM0ueCuEDFZ9NK+kCWaPNAVhOKKwL8HmoX/7KcFLWkwSoatnrncHTH5STey+bqR1xTFY+Rubj8BZt7D9JJYyLQC46wn4ySVnLWkCZZ9+aaTriEBzGTpUzeRiUTWVprp3oXsA7ZKyn+lhZfMx1ILhcD8dnX7xFHB57jIKvPBxAdT4K7GxdgENeS76I/zmVmlF//JnmtZ/RM1WmRkx8mFmcK/Ky8gLsmIpPPltoyBWIKIf2NQH9kHqHa2gwoPg34LTutV9AACTWuiVOjqU7Gq2BHQcjovXMF8t3Wiw==</Modulus><Exponent>AQAB</Exponent><P>9NiLuI9TjNvpAPQqD9ySdMX37OmEDCF02isoovt8hwPpiXcZYH4FeasNZoydRrBUOHTTRrW3xdUYGsCZI0H9tSg+gIjo/k/JhmECT7RuSgjEL7mLpusAhi1RFv81TNERGvWP8V9HtB4oZONgOpdTuNqJwhyZ3+aA3zyy7k1mKJc=</P><Q>wqJndWnlZ2i8sW8zhX9SPUddyf8E+wHek3SYynUNQ3T7zJbk+woqyjMuSImXXuZO47uBJlwskYwR+mJr/AuCR7Y0+jtByJF8RoqkY7ttdhS8CpJ9J2o5YMGcGw0JoJ16L0W6QvhY5Zxb5IAG5nuiPLDlgZYNo7+oKRcDyF+fbC0=</Q><DP>hwimhjMFsTnXV19Rk03it+Q2x8JBwS7ycyA6WSi5lPzjX5z/sefOvTtJOLV0R/gXestzehveLo1Hrflqe7d5ZN+9GMZpOVhnnGUEEVFBQjNzf56lFnmk4Fs9zaESlDr5ZBTqPgR+VygKvxlniOjMk7ZzI0sC0ikeCgA/7o1hOiE=</DP><DQ>Fpj2fBpcaSIu7kbj63b53GWBzScPs/jml6Ys6yyl6pQVfA507XSjvTAuCnv3GCyTMjud5g9DmW5y0+hDc1L+wEa2ZeslWx0RGbuVFIM5VUFZB700TLQ3jzVLY5Si7oP6IKzu0EG3SIlb3e7DXlUyY+uB6ga69K0W4BZs+QGpJ80=</DQ><InverseQ>nob08brDfoswDV8JAkGJIg5T9ktMBRzn5djbAfSorOCCVwW+iRz/hkzSs4LaeMuoC3V5AnLeTg1T7J3op67KGerRwwjXSgCKO4crs2pODcZuIMkaE8e/5Ti1O40yKl05mQaxLk/SgSAhy97HhHoiteg/ttLcrvsCcSfyyxzHT3M=</InverseQ><D>bwqYEbh7EjOa3gfIiRBtMIWFExtBD6zZ9dtH0i0FNvZpy8B38iqXirMImcohNxal0fN3BTGc/ft33sJQDABzQlaTnhLgLU1lU9aqeb1fhANjVzPuKhUbhm/2mFeNFfcyCDUDC7y3Zz19hB7BKAomjSQjZKnNAAo2z2e2T9Mzf5kV8uuYsnoum6LEvEfluQ3q3+9Ua64P0E4D2j2iaOnvpBzTCpeaBMDfWZEe19MaS40d/OrZOwlyAVPCW9RkT3948fC5KDvE0KetYDsrVApRSKzvBUQCVNmcO2o+rhMO1qKvS+zkw2VW5OxGDk/QuHuXIkCyipUEMa/DmK74hoxCaQ==</D></RSAKeyValue>
You must be using a really old version of phpseclib since phpseclib has had built in support for the XML format for quite a few years. So my first recommendation would be to upgrade to the latest version. After that you should be able to do something like this:
<?php
include('Crypt/RSA.php');
$plaintext = 'zzz';
$rsa = new Crypt_RSA();
$rsa->loadKey('<RSAKeyValue>
<Modulus>uidt3bPfWozkIkC6nHnRDbXrvjqplfCslV2zP4hKJ6sVjVnPfjMM0ueCuEDFZ9NK+kCWaPNAVhOKKwL8HmoX/7KcFLWkwSoatnrncHTH5STey+bqR1xTFY+Rubj8BZt7D9JJYyLQC46wn4ySVnLWkCZZ9+aaTriEBzGTpUzeRiUTWVprp3oXsA7ZKyn+lhZfMx1ILhcD8dnX7xFHB57jIKvPBxAdT4K7GxdgENeS76I/zmVmlF//JnmtZ/RM1WmRkx8mFmcK/Ky8gLsmIpPPltoyBWIKIf2NQH9kHqHa2gwoPg34LTutV9AACTWuiVOjqU7Gq2BHQcjovXMF8t3Wiw==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>');
define('CRYPT_RSA_PKCS15_COMPAT', true);
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
echo base64_encode($rsa->encrypt($plaintext));
If that doesn't work it'd help to see the .NET code you're using to decrypt. Also, if you could encrypt a string in .NET and post the public key you used to do the encryption and the ciphertext itself that'd be useful. From that I could play around with the phpseclib options until I found some combination of options that let me decrypt the string, which would, presumably, in turn, give us insight in how to encrypt the string.
I've seen this asked a few times, but not exactly how I'm going to ask it here... Hopefully this is ok with you guys.
Basically I have this script that works fine and will print my result without a hitch:
$algorithm = MCRYPT_BLOWFISH;
$mode = MCRYPT_MODE_CFB;
$iv = mcrypt_create_iv(mcrypt_get_iv_size($algorithm, $mode), MCRYPT_DEV_URANDOM);
$key = 'Wassup';
$data = 'I am a guy';
$enc_data = rtrim(mcrypt_encrypt($algorithm,$key,$data,$mode,$iv));
$plain_text = base64_encode($enc_data);
echo $plain_text . "\n";
// OUTPUTS: 6m3D5qSrfz3w6pKuuybs
$enc_data = base64_decode($plain_text);
$decoded = mcrypt_decrypt($algorithm,$key,$enc_data,$mode,$iv);
echo $decoded;
// OUTPUTS: I am a guy
This is perfect. NOW... instead of just instantly outputting what I put in, I'm trying to store that info in my database to be decrypted later.
I can see the encrypted string fine in my table row: 6m3D5qSrfz3w6pKuuybs. So, I'm sure it's going IN just fine..
and when I query to get it out it looks just the same,
but now when I decode and decrypt I get something like: ÝÄ/$ÍñËt05883700
The table field is set up as a VARCHAR (255) utf8_general_ci. Is this where the problem is?
Are you sure you are using the same initialization vector (IV) on encryption and decryption?
Note that you need to save the IV as well and use it when you are decrypting. Also don't use rtrim() on the ciphertext.
That being said, you could use a BINARY (or VARBINARY) field to store your ciphertext (and the IV), so you don't need to base64 encode it. It will save you 33% of storage.