Why is AES_DECRYPT returning null? - mysql

I've found similar questions, but no clear answer for this question. I have this table:
CREATE DATABASE testDB DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE testTable
(
firstName binary(32) not null,
lastName binary(32) not null
/* Other non-binary fields omitted */
)
engine=INNODB DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
This statement executes just fine:
INSERT INTO testTable (firstName) VALUES (AES_ENCRYPT('Testname', 'test'));
But, this returns NULL:
SELECT AES_DECRYPT(firstName, 'test') FROM testTable;
Why does this return NULL?
Fwiw, this returns "testValue" as expected:
SELECT AES_DECRYPT(AES_ENCRYPT('testValue','thekey'), 'thekey');

The answer is that the columns are binary when they should be varbinary. This article explains it:
Because if AES_DECRYPT() detects invalid data or incorrect
padding, it will return NULL.
With binary column types being fixed length, the length of the input value must be known to ensure correct padding. For unknown length values, use varbinary to avoid issues with incorrect padding resulting from differing value lengths.

When you insert binary data into a VARCHAR field there are some binary characters that a VARCHAR can't handle and they will mess up in the inserted value. And then the inserted value will not be the same when you retrieve it.
1.select hex(aes_encrypt(file,'key'));
2.select aes_decrypt(unhex(file),'key');

Check if type of your field is blob instead binary(32)

Did you try different values other than 'Testname'?
Do other values work?
I ask because I had a situation while testing 2 test credit card numbers where one decrypted fine and the other returned null.
The answer was to hex and unhex as suggested by "abhinai raj"

Related

Why is MySQL not converting my data correctly?

I have a column of decimals, but MySQL is reading them as TEXT. I tried this to alter the column by:
ALTER TABLE `engine_type_project`.`weo_data_eu_test`
CHANGE COLUMN `Mean_GDP_all_time` `Mean_GDP_all_time` DECIMAL(6,2) NULL DEFAULT NULL;
An original value is: 3,282.772
But my code returns it as: 3.00
Prior to this, I attempted:
SELECT CAST('Mean_GDP_all_time' AS DECIMAL(6,2))
FROM weo_data_eu_test;
But the entire column returned as 0.00
In casting non-numeric values to numeric, mysql does not expect commas. So it gives up looking for additional parts of the number after the "3".
Before changing the type, remove the commas with:
update weo_data_eu_test set Mean_GDP_all_time=replace(Mean_GDP_all_time,',','')
fiddle

Initialize Varbinary datatype in MySQL

In MySQL, I want to declare a default value to a varbinary column. How do I achieve it ?
DECLARE result varbinary(8000);
SET result = 0x;
I used select CHAR_LENGTH(00101) and it gives me a result 3. I am expecting my result to be 5 (number of characters in string). To measure the length of a varbinary string, how do I do it ?
When you create your table you can specify a default. For binary data you should probably express it as a hex string, 0x... style:
CREATE TABLE binary_default (
id INT PRIMARY KEY AUTO_INCREMENT,
binary_data VARBINARY(8000) DEFAULT 0x010203
);
You can test this works with:
INSERT INTO binary_default VALUES ()
Then fetch, but as it's binary, you might want a hex view:
SELECT id, HEX(binary_data) FROM binary_default

Strict matching of strings and integers

I am writing a flexible search mechanism for a customer's website. I am utilizing union clauses to query a number of different fields in the database in search of a string value entered by the user. This works fine except for one issue.
When comparing a string of a text to an integer that is currently set to zero, the match always returns true. In other words, according to MySQL, "email#example.com" is equal to 0.
I have tried utilizing the CAST and CONVERT function to turn this into a standard string to string comparison, but I can't seem to get the syntax right. My attempts either repeat the above issue or return no rows at all when some should match. I am also concerned that doing this would have an effect on performance since I am combining lots of unions.
What I really need is a strict comparison between an entered string and the value in the database, be it an integer or string.
EDIT:
Here is an example.
CREATE TABLE `test_table` (
`id` INT NOT NULL AUTO_INCREMENT ,
`email` VARCHAR(255) NOT NULL ,
`phone` BIGINT(19) NOT NULL DEFAULT '0' ,
PRIMARY KEY (`id`) )
ENGINE = MyISAM;
INSERT INTO `test_table` (`id`, `email`, `phone`) VALUES (1, 'email#example.com', 0);
SELECT * FROM test_table WHERE phone = 'email#example.com';
Execute this and the one row that has been inserted will return. My issue is that it shouldn't!
This query should fail:
SELECT * FROM test_table WHERE cast(phone as char) = 'email#example.com';
The cause of the original problem is that when comparing strings and numbers, it converts the string to a number (so you can write where phone = '123'). You need to use an explicit cast of the field to make it a string-to-string comparison, to prevent this default conversion.
Unfortunately, casting like this is likely to prevent it from using indexes. Even if the field is already char, the cast apparently prevents it from indexing.
You could also solve it during input validation: if phone is an integer, don't allow the user to provide a non-integer value in the search field.
How about replacing:
SELECT * FROM test_table WHERE phone = 'email#example.com'
with:
SELECT * FROM test_table WHERE phone = 'email#example.com' and phone <> 0
<> means different from.
This will work for you because you are using 0 in the phone column to mean there isn't a phone number (although it would be better style to use NULL for no phone number).

MySql insert statement to binary datatype?

I am using MySQL database.
I have one table having column with datatype binary(16).
I need help with the insert statement for this table.
Example:
CREATE TABLE `assignedresource` (
`distid` binary(16) NOT NULL
)
insert into assignedresource values ('9fad5e9e-efdf-b449');
Error : Lookup Error - MySQL Database Error: Data too long for column 'distid' at row 1
How to resolve this issue?
You should remove the hyphens to make the value match the length of the field...
Example:
CREATE TABLE `assignedresource` (
`distid` binary(16) NOT NULL
)
insert into assignedresource values ('9fad5e9eefdfb449');
Also, MySQL standard is to use this notation to denote the string as binary... X'9fad5e9eefdfb449', i.e.
insert into assignedresource values (X'9fad5e9eefdfb449');
Well, assuming that you want to strictly insert a hexadecimal string, first you need to remove the dashes and then "unhex" your string before inserting it into a binary(16) data type column, the code would go like this:
INSERT INTO `assignedresource` VALUES(UNHEX(REPLACE('9fad5e9e-efdf-b449','-','')));
Also... the "usable" data you are inserting is actually 8 bytes after undashing it, so binary(8) would do fine if you plan on not storing the dashes.
You can strip the hyphens and perpend 0x to the value unquoted, like this:
insert into assignedresource values (0x9fad5e9eefdfb449);
As well as, as this (mentioned in other answers):
insert into assignedresource values (X'9fad5e9eefdfb449');
Both are valid notation for a hexadecimal literal.
Your string is 18 char long, change the database
CREATE TABLE `assignedresource` (
`distid` binary(18) NOT NULL
)

SQL - how to return exact matches only (special characters)

I have a table with words in spanish (INT id_word,VARCHAR(255) word). Lets suppose the table has these records:
1 casa
2 pantalon
If I search for the word pantalón (with a special char ó) it should not return any rows. How do I select exact matches only? It is currently returning the 2nd row.
SELECT * FROM words WHERE word='pantalón';
Thanks!
Solution from ifx, i changed the word field's collation to utf8_bin.
The reason this happens is down to the collation. There are collations that are accent sensitive (which you want in this case) and other that are accent insensitive (which is what you currently have configured). There are also case-sensitive and case-insensitive collations.
The following code produces the correct result:
create table test (
id int identity(1,1),
value nvarchar(100) collate SQL_Latin1_General_Cp437_CI_AS
)
insert into test values ('casa')
insert into test values ('pantalon')
select value collate SQL_Latin1_General_Cp437_CS_AS from test where value = 'pantalón'
The below code produces the incorrect result:
drop table test
go
create table test (
id int identity(1,1),
value nvarchar(100) collate SQL_Latin1_General_Cp437_CI_AI
)
insert into test values ('casa')
insert into test values ('pantalon')
select value collate SQL_Latin1_General_Cp437_CS_AS from test where value = 'pantalón'
The key here is the collation - AI means Accent-insensitive, AS means accent-sensitive.
i have this problem in our language too, so i did this, i have 2 coulmns for names, one of the i have named SearchColumn and the other one ViewColumn, when saving data I replace Special characters with other characters. when a user wants to search for something with the same function I do the changes and search it in the SearchColumn, if the search matches, I would display the value of the ViewColumn.