I want to store a base64_encoded string as binary data. So use base64_decode() on the string before inserting in a LONGBLOB field of MySQL. So far so good, however when I retrieve the data from MySQL, I can't generate the correct base64_encoded string which I have started with...
How is this possible? Thanks in advance
EDIT
The stored data is an encrypted string with AES-256CBC OPENSSL encryption routine.
CODE
For my code I use OpenSSL to encrypt a string
$string = "Test";
$IV = "1234567890123456";
$key = "12345678901234561234567890123456";
$encrypted = openssl_encrypt($string, "AES-256-CBC", $key, false, $IV);
$encrypted string is stored in LONGBLOB field by
$sql_insert_data = $mysqli->prepare("INSERT INTO `TBLName` (String) Values(?)");
$sql_insert_data->bind_param('s', $mysqli->real_escape_string($encrypted));
//Thereafter, it is retrieved by a select statement
$decrypted = openssl_decrypt($row['String'], "AES-256-CBC", $key, true, $IV);
When I do base64_encode on the string and store that as a TEXT value in the DB, the above works. However, when I do not, the above does not work...
Thanks
You are using prepared statements incorrectly:
$sql_insert_data->bind_param('s', $mysqli->real_escape_string($encrypted));
^^^^^^^^^^^^^^^^^^ :-!
Your code will add random backslashes to the binary stream. You don't need real_escape_string() at all.
"damn son, the question is how to I optimize the storage of base64_encoded data successfully in mysql. That's all." -- See https://stackoverflow.com/a/42080296/1766831
Related
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.
I'm having a problem where my password doesn't store after encryption even though it stores perfectly when I don't encrypt it. When I go to the database to check whether it's stored or not, I just see a blank under the password column. I want my password's encoding to be UTF-8 (or whatever it's called) since I want to use the Arabic language in my database.
PHP CODE
$password = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $_POST['password'], MCRYPT_MODE_CBC, $iv);
base64_encode($password);
Here's a picture that will show you my table's structure :
http://prntscr.com/91nhyx
You need to store the base64 encoded version before storing it in the database:
$password = base64_encode($password);
I use openssl to encrypt a text, then put this into a mysql database.
This works fine, however with long texts, the decrypted text becomes corrupted.
Personally I think this is due to the way mysql saves this text into the database, there are a lot of not alpha numeric characters in the encrypted text. But I am not sure about that.
Also I don't know which collation to use in mysql, right now I set it to *utf8_unicode_ci*, but still there is corruption of data.
A live example can be seen here: http://todolist.x10.mx
Username: example
Password: password
To view the corrupted data, click Download Backup.
Below the code, of course $encrypted is saved into the database. This code works fine without database.
<?php
$source = 'very long text';
$iv = "1234567812345678";
$pass = 'difficultpassphrase';
$method = 'aes-256-ofb';
$encrypted = openssl_encrypt ($source, $method, $pass, true, $iv);
echo $encrypted;
$decrypted = openssl_decrypt ($encrypted, $method, $pass, true, $iv);
echo $decrypted;
?>
Thank you in advance for your time and expertise.
To store encrypted content in binary form, you can't use a character type with encoding since it's very likely that the encoding "breaks" your data.
You should instead use BINARY or VARBINARY datatypes, they're made exactly for the purpose of storing binary data.
The alternative is to base64_encode the data before storing it in the character datatypes, and base64_decode the data when you've fetched it from the database. This will encode the data so that the encrypted data is possible to store in a varchar/char datatype (although it will make the data slightly longer, so beware of that)
PHP code:
$key = "12345678abcdefgh12345678abcdefgh";
$iv = "12345678abcdefgh";
$plaindata = "This is a test string.";
$enc = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaindata, MCRYPT_MODE_CBC, $iv));
echo($enc);
Result:
QBN0Yue3D9hBrBuD01n5KWG+lv2doMf97cKm/AeusAI=
How can this be decrypted in Python?
Try something like this (altho i do have PyCrypto installed)
from Crypto.Cipher import AES
import base64
AES.key_size=128
iv="your iv"
key="your key"
crypt_object=AES.new(key=key,mode=AES.MODE_CBC,IV=iv)
decoded=base64.b64decode(plain) # your ecrypted and encoded text goes here
decrypted=crypt_object.decrypt(decoded)
This will bring the decoded text but it will be padded with bytes for it to be a size multiple of 16.
You should probably decide on a proper padding scheme and remove it afterwards accordingly
Read the manual, its pretty well documented.
data = base64.b64decode('QBN0Yue3D9hBrBuD01n5KWG+lv2doMf97cKm/AeusAI=')
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.