Data corruption mysql with openssl - php

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)

Related

Binary data not stored properly in MySQL

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

php ,openssl function generate random encoding , how can i correctly save encrypted text in database

Kindly I am a developer with basics of encryption ,
I have a task which is encrypting data then save the encryption to database,
I am using openssl php function to encrypte and decrypte like below
function encrypte($stringToEncrypte){
$method="AES-128-CBC";
$iv=mcrypt_create_iv(16, MCRYPT_RAND);
$pass=md5('8123jhewe8dnjsdnq');
$encrypted=openssl_encrypt ($stringToEncrypte, $method, $pass, true , $iv);
return $encrypted."---".$iv;
}
function decrypte($stringToDecrypte){
/*
decrypte by remove --- then get iv then get encrypted then decrypte
*/
}
It's working fine but the encrypted text has random encoding and this will cause many errors in saving correctly into my database which saving in UTF-8 Encoding.
Definitely, I tried to convert the encrypted key to utf-8 by mb_convert_encoding() function but logically , the new encoded text will not be decrypted correctly , because the new encoded text will not be the same of the old encoded text .
For example, the encrypted text will have random encoding like ISO-8859-1
and my database encoding is utf-8 and encoding conversion will not generate text could be decrypted again.
i found something may by not very bad ,is to use URLencode PHP function , i tried it and it was working fine ,
but still i need experts answer
If your database is utf8, than all your content should be utf8. You need to convert your $stringToEncrypte to utf8 before you encrypt it. And make shure your $pass and $iv are utf8 as well. Then you can encrypt (also utf8), save in database and decrypt everything in utf8 as well.

Password doesn't store in database UTF-8

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);

Encrypto in JavaScript and Decrypto in PHP

I want to encrypt in the javascript. decrypt in the PHP.
JavaScript AES crypto library is CryptoJS.
PHP AES crypto library is mcrypt.
I was get incorrect result.
get result like 'I4��L$�"�"E̹_��zHe����V���:�'.
encrypt (JavaScript)
encrypt = CryptoJS.AES.encrypt('HelloWorld', 'test', {mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding });
decrypt (PHP)
$ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($ivSize, MCRYPT_RAND);
mcrypt_decrypt(MCRYPT_RIJNDAEL_256, 'test', $encrypt, MCRYPT_MODE_CBC, $iv);
is wrong somewhere?
Thank you.
As noted in the comments above, SSL is the only way you will acutally protect any data because
Without SSL, anyone could make changes to or sniff your Javascript or webpage and so it cannot be trusted.
Javascript really doesn't allow for non-character based data very well. (i.e. hashes, encoded video, etc.) as all data is usually silently converted to utf-16 or utf-8 internally.
This last point is likly what is causing your problem. The AES library on each end encrypts as if it had access to binary data, however, Javascript is telling the transfer that the encrypted data is in a certain characterset. You may want to try utf8decode or play with iconv() to get it converted to true binary data.

Mysql and Mcrypt Problem with PHP

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.

Categories