AES_DECRYPT How do you check value is already decrypted in mysql - mysql

I want to decrypt fields in my database using sql on mysql but before I decrypt I need to check if the fields can be decrypted.
update customer
set name = aes_decrypt(from_base64(name), 'key')
If the provided key is wrong or data is invalid the name field will be set to null;
I have tried adding a where clause like below to make sure the field name is not already decrypted but this doesn't work all the time as the aes_decrypt can return null or garbage if the key is incorrect or data is invalid.
update customer
set name = aes_decrypt(from_base64(name), 'key')
where aes_decrypt(from_base64(name), 'key') is not null.
So how can I check if the returned value is null or "garbage"? Or what other approach is there?
From mysql doc: "it is possible for AES_DECRYPT() to return a non-NULL value (possibly garbage) if the input data or the key is invalid."
garbage example I get: w���� ��Y�'v��Y�m��_
Thanks

Instead of storing raw ciphertext, follow the lead of version 2 of Defuse Security's PHP encryption library:
Use authenticated encryption.
Use a version tag which tells what library was used as well as what version and any optional configuration information you need to add.
Make sure to calculate HMAC(tag || IV || ciphertext) instead of just HMAC(ciphertext).
Store the tag, IV/nonce, ciphertext, and MAC together; preferably as a hex- or base64-encoded string.
Then the question becomes "Do the first N bytes of the string evaluate to a known version tag of my encryption library"?

Related

Error "attribute parameter is not in hash ref" when using Perl DBI selectall_hashref

I'm trying to get my first select to work using selectall_hashref from the Perl DBI module. I've opened a connection to the database (MySQL) successfully. I'm getting an error when I execute the following:
$dbh->selectall_hashref('SELECT id FROM users WHERE login=?',undef,"myusername");
DBI::st=HASH(0x1505a60)->_prepare(...): attribute parameter 'myusername' is not a hash ref at /usr/lib/x86_64-linux-gnu/perl5/5.20/DBD/mysql.pm line 238.
My table should be able to support this query, it has an id column and login column for each user.
The examples I've found for selectall_hashref show the ? substitution parameter being passed as the third parameter. The DBI documentation says that the second and third arguments should be %attr and #bind_values but doesn't give much documentation about them or show working examples.
What is causing the error, and more importantly how do you actually use the %attr and #bind_values correctly?
If you want to store everything as an arrayref where each row is a hashref (which is what your comment seems to indicate), you can use the selectall_arrayref() method with the Slice attribute:
$dbh->selectall_arrayref('SELECT id FROM users WHERE login=?', {Slice => {}}, 'myusername');
It's a little weird, but here's how it works:
If $slice is a hash reference, fetchall_arrayref fetches each row as
a hash reference. If the $slice hash is empty then the keys in the
hashes have whatever name lettercase is returned by default. (See
"FetchHashKeyName" attribute.) If the $slice hash is not empty,
then it is used as a slice to select individual columns by name. The
values of the hash should be set to 1. The key names of the returned
hashes match the letter case of the names in the parameter hash,
regardless of the "FetchHashKeyName" attribute.
It's a good idea to set the FetchHashKeyName attribute on the database handle to make your hash key names consistent; I happen to like NAME_lc in my applications.
The methods expects key column as the second parameter and attributes ref is passed as third one. In the result it builds a hash with the specified column as a key. What you probably want, is selectall_arrayref:
$ dbh->selectall_arrayref('SELECT id FROM users WHERE login=?',undef,"myusername");

How can I encrypt a value in MySQL?

I have this code:
CREATE TABLE Person
(
primaryKey int unsigned NOT NULL,
emailAddress mediumblob NOT NULL
);
What attribute (like NOT NULL) can I use so that the emailAddress would be encrypted?
I would greatly appreciate the help. I tried encrypt() but that's giving me errors.
if you looking to encrypt data where you can decrypt it later then you should use ES_ENCRYPT() AND AES_DECRYPT()
According to the Manual
AES_ENCRYPT() encrypts a string and returns a binary string. AES_DECRYPT() decrypts the encrypted string and returns the original string. .
MySQL 5.1 Doc: AES_ENCRYPT() / AES_DECRYPT()
you can use it like this
INSERT INTO table (email)VALUES(AES_ENCRYPT('myemail', 'secrectkey' ))
to read the data that is encrypted you can do this
SELECT AES_DECRYPT(email, 'secrectkey' ) FROM table
where secrectkey is really a secret value that only authorized users should have access to
But if you are looking for hashing "a one way hash that can't be read back in plain text" you can use one of the following functions
MD5('myemail');
OR
PASSWORD('myemail');
OR
SHA1('myemail');
Then your table length depends on the encryption method you use. you can use VARCHAR() if the length of your encrypted message changes. If you know that you will be using fixed length I would use CHAR(exact_length)
Again the length will depend on the method you use.
You have the complete list of encryption functions supported by MySQL DBMS on this official documentation.

Why my date is written 0000-00-00

I have a table where the date column name is defined as proddate and defined as DATE.
Here is the code I write the value into table:
cmd.Parameters.Add("#Mydate", MySqlDbType.DateTime).Value = Convert.ToDateTime(MyArray[4]).ToString();
This gives a result of 0000-00-00
When I change it to
cmd.Parameters.Add("#Mydate", MySqlDbType.DateTime).Value = Convert.ToDateTime(MyArray[4]);
The result is correct. eg: 2013-11-14
However few lines down I have this code
cmd1.Parameters.Add("#date", MySqlDbType.DateTime).Value = Convert.ToDateTime(MyArray[4].ToString());
This gives no error. I get the correct result in table
And few lines after I have this code in the same method:
cmd3.Parameters.Add("#Mydate", MySqlDbType.DateTime).Value = MyArray[4].ToString();
This gives no error too
The last two lines I did the mistake for testing. But the columns of 2 last exemples are defined as DATE format
Any idea ? Or Am I welcome in the mystery world of Mysql ?
PS: I use MYSQL CONNECTOR 6.7.4.0 .NET3.5 and C# 2008 Express. In my server MYSQL is 5.0
In the first version, you're converting your value to a DateTime and then to a string, using the default format for a DateTime value. MySQL is then trying to parse that, and presumably failing.
In the second version, you're parsing your value as a DateTime, and supplying it to MySQL directly. This is the best approach, although you need to be careful about the input format you're using.
The third version is like the second, just with an explicit ToString call. If MyArray is of type string[], that's basically a no-op.
The fourth version is providing the string input directly to MySQL, which is presumably able to parse it itself. I would suggest avoiding that form though - parse it in the .NET code, where you have much more control.

I want to extract the parameters of a url in mysql

I have in my database a column with the parameters value of an url. I want with an sql query to put those parameters in different columns. I give an example:
I have now a column named parameters with for example this value: pOrgNum=j11000&pLanguage=nl&source=homepage
now I want three columns: pOrgnum | pLanguage | source with the values of my parameters.
The problem is that I don't know the order of my parameters or the length of it, so I can't use for example substring(parameters,9,6) to extract the parameter pOrgnum. can someone help me please?
There's a MySQL UDF that you can use to do exactly this, which also handles decoding the params and handles most character encodings, etc.
https://github.com/StirlingMarketingGroup/mysql-get-url-param
Examples
select`get_url_param`('https://www.youtube.com/watch?v=KDszSrddGBc','v');
-- "KDszSrddGBc"
select`get_url_param`('watch?v=KDszSrddGBc','v');
-- "KDszSrddGBc"
select`get_url_param`('watch?v=KDszSrddGBc','x');
-- null
select`get_url_param`('https://www.google.com/search?q=cgo+uint32+to+pointer&rlz=1C1CHBF_enUS767US767&oq=cgo+uint32+to+pointer&aqs=chrome..69i57.12106j0j7&sourceid=chrome&ie=UTF-8','q');
-- "cgo uint32 to pointer"
select`get_url_param`('/search?q=Na%C3%AFvet%C3%A9&oq=Na%C3%AFvet%C3%A9','q');
-- "Naïveté"
Disclaimer, I am the author.
I achieved this by taking the right of the string after the search parameter, then the left of the resulting string before the first &.
This handles
if the parameter was the last in the url (so no "&" follows it)
if the parameter does not exist (returns blank)
varying lengths of the search string (provided you replace "utm_medium" everywhere)
This finds the value of "utm_medium" in a parameter named url:
IF(locate("utm_medium", url)=0, '', LEFT(RIGHT(url,length(url)-locate("utm_medium",url)-length("utm_medium")),IF(locate("&",RIGHT(url,length(url)-locate("utm_medium",url)-length("utm_medium")))=0,length(RIGHT(url,length(url)-locate("utm_medium",url)-length("utm_medium")+1)),locate("&",RIGHT(url,length(url)-locate("utm_medium",url)-length("utm_medium"))))-1)) utm_medium
To use, find and replace url with your field name, and utm_medium with your url parameter.
May be inefficient, but gets the job done, and couldn't find an easy answer elsewhere
Its code work in mysql:
SELECT substring_index(URL_FIELD,'\',-1) FROM DemoTable;

Converting a mySQL table with id's to a MongoDB table with _id's

I'm transferring a MySQL table to MongoDB. There is a primary key id in my MySQL table and I want this id to be converted to the _id in MongoDB.
I use php's MongoCollection::insert( $mysql_array );
However it doesn't work because if I set $mysql_array['_id'] it is seen by mongo as a String instead of a MongoId. I tried $mysql_array['_id'] = new MongoId( $id ) but it doesn't allow me to override the default _id value. I saw that all my MySQL's integer columns are converted to string by MongoCollection::insert(). If I could set MongoCollection::insert() to correctly transfer an integer it would maybe work.
typecast the _id to a integer value like this...
(int) $mysql_array['_id']
You'll find yourself doing this a lot in mongoDB
The ObjectId is a special type in Mongo, but the _id property doesn't have to be of this type. You can't coerce a string or number into an ObjectId, and you shouldn't.
I assume the problem as you perceive it is that your insert worked, but when you looked at the data in the database the _id property didn't look like _id: ObjectId("1234") (if the original ID was 1234). This is as it should be, and it's perfectly fine.
The idea with ObjectId is that it has a predefined structure that makes it guaranteed (mostly) to be unique across a Mongo cluster, but this also means that it has to have this structure, otherwise it is not an ObjectId.
You also mention that all your integer columns are converted to strings. PHP and PHP libraries, are notoriously sloppy when it comes to types, so make sure that it's not the case that the values are already strings when they come from the MySQL result set. Worst case you have to explicitly cast the values before inserting them into Mongo.
You won't be able to convert an arbitrary String value into an Mongo ObjectId due to its specific characteristics (12 bytes -> 24 chars generated from 4 bytes timestamp, 3 bytes client hostname, 2 bytes PID, 3 bytes inc value).
Either you abandon using the MongoId type in your collection's _id-fields and use your MySQL-ID as a string instead (which is not a problem and makes the most sense) or you let Mongo to generate the documents' _id for you, which is also a suitable solution if you want to be able to use the MongoId functions (assuming you're working with PHP):
The MongoId class
Choosing the second solution you still are able to store your MySQL-IDs in another field of the doc, like id or *mysql_id* to reference them later.
Concerning your question about (int) and (string) values: Are you sure they come as a PHP integer from your MySQL DB? If so, they usually should be stored as integers in Mongo. Check it with a var_dump() and in case of incompatibility cast it with an (int). Maybe it would be helpful if you post your select/insert code...
Use MongoCollection::save() and your array should work.