Commit a0d97110 authored by tonu@volk.internalnet's avatar tonu@volk.internalnet

des_encrypt()/des_decrypt() are now ASCII protected and pass testsuite

parent 964c292c
-- source include/have_openssl.inc
use test;
drop table if exists x;
create table x (x blob);
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','The quick red fox jumped over the lazy brown dog'));
insert into x values (des_encrypt('a','The quick red fox jumped over the lazy brown dog'));
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','a'));
insert into x values (des_encrypt('ab','The quick red fox jumped over the lazy brown dog'));
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','ab'));
insert into x values (des_encrypt('abc','The quick red fox jumped over the lazy brown dog'));
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','abc'));
insert into x values (des_encrypt('abcd','The quick red fox jumped over the lazy brown dog'));
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcd'));
insert into x values (des_encrypt('abcde','The quick red fox jumped over the lazy brown dog'));
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcde'));
insert into x values (des_encrypt('abcdef','The quick red fox jumped over the lazy brown dog'));
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdef'));
insert into x values (des_encrypt('abcdefg','The quick red fox jumped over the lazy brown dog'));
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefg'));
insert into x values (des_encrypt('abcdefgh','The quick red fox jumped over the lazy brown dog'));
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefgh'));
insert into x values (des_encrypt('abcdefghi','The quick red fox jumped over the lazy brown dog'));
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghi'));
insert into x values (des_encrypt('abcdefghij','The quick red fox jumped over the lazy brown dog'));
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghij'));
insert into x values (des_encrypt('abcdefghijk','The quick red fox jumped over the lazy brown dog'));
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','abcdefghijk'));
insert into x values (des_encrypt('The quick red fox jumped over the lazy brown dog','sabakala'));
insert into x values (des_encrypt('quick red fox jumped over the lazy brown dog','sabakala'));
insert into x values (des_encrypt('red fox jumped over the lazy brown dog','sabakala'));
insert into x values (des_encrypt('fox jumped over the lazy brown dog','sabakala'));
insert into x values (des_encrypt('jumped over the lazy brown dog','sabakala'));
insert into x values (des_encrypt('over the lazy brown dog','sabakala'));
insert into x values (des_encrypt('the lazy brown dog','sabakala'));
insert into x values (des_encrypt('lazy brown dog','sabakala'));
insert into x values (des_encrypt('brown dog','sabakala'));
insert into x values (des_encrypt('dog','sabakala'));
insert into x values (des_encrypt('jumped over the lazy brown dog','sabakala'));
insert into x values (des_encrypt('jumped over the lazy brown dog','sabakala'));
insert into x values (des_encrypt('jumped over the lazy brown dog','sabakala'));
select * from x;
select des_decrypt(x,'sabakala') from x;
#drop table x;
...@@ -203,58 +203,67 @@ void Item_func_concat::fix_length_and_dec() ...@@ -203,58 +203,67 @@ void Item_func_concat::fix_length_and_dec()
#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.') #define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
#define ascii_to_bin(c) ((c)<=57 ? (c)-46 : (c)<=90 ? (c)-53 : (c)-59) #define ascii_to_bin(c) ((c)<=57 ? (c)-46 : (c)<=90 ? (c)-53 : (c)-59)
/*
Function des_encrypt() by tonu@spam.ee
Works only if compiled with OpenSSL library support.
Output always starts with magic char "1" and all
encrypted output is encoded into ASCII-protected
container.
Original input is returned as output if input string
begins with magic "1". Credit card number always begin
with 4,5 or 6.
Encryption result is longer than original by formula:
new_length=(8-(original_length % 8))*2+1
*/
String *Item_func_des_encrypt::val_str(String *str) String *Item_func_des_encrypt::val_str(String *str)
{ {
String *res =args[0]->val_str(str); String *res =args[0]->val_str(str);
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
des_key_schedule ks1, ks2, ks3; des_key_schedule ks1, ks2, ks3;
des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
union { struct {
des_cblock allkeys[3]; // 24 bytes (168 bits) total
des_cblock key1, key2, key3; // 8 bytes each des_cblock key1, key2, key3; // 8 bytes each
} key; } keyblock;
if ((null_value=args[0]->null_value)) if ((null_value=args[0]->null_value))
return 0; return 0;
if (res->length() == 0) if (res->length() == 0)
return &empty_string; return &empty_string;
String *keystr=args[1]->val_str(&tmp_value); if(res->c_ptr()[0]!='1') { // Skip encryption if already encrypted
int32 mode=0; String *keystr=args[1]->val_str(&tmp_value);
if(arg_count == 3 && !args[2]->null_value) /* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
mode=args[2]->val_int(); EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
// We make good 24-byte (168 bit) key from given plaintext key with MD5
EVP_BytesToKey(EVP_get_cipherbyname("DES-EDE3-CBC"),EVP_md5(),NULL,
(uchar *)keystr->c_ptr(), (uchar *)keystr->c_ptr(),
keystr->length(),1,(uchar *)&key.allkeys,ivec); (int)keystr->length(),1,(uchar *)&keyblock,ivec);
// Here we set all 64-bit (56 actually) one by one des_set_key_unchecked(&keyblock.key1,ks1); // Here we set all 64-bit keys
des_set_key_unchecked(&key.key1,ks1); des_set_key_unchecked(&keyblock.key2,ks2); // (56 effective) one by one
des_set_key_unchecked(&key.key2,ks2); des_set_key_unchecked(&keyblock.key3,ks3);
des_set_key_unchecked(&key.key3,ks3); /*
/* The problem: DES algorithm requires original data to be in 8-bytes The problem: DES algorithm requires original data to be in 8-bytes
* chunks. Missing bytes get filled with zeros and result of encryption chunks. Missing bytes get filled with zeros and result of encryption
* can be up to 7 bytes longer than original string. When decrypted, can be up to 7 bytes longer than original string. When decrypted,
* we do not know the size of original string :( we do not know the size of original string :(
* We add one byte with value 0x0..0x7 to original plaintext marking We add one byte with value 0x0..0x7 to original plaintext marking
* change of string length */ change of string length
uchar tail=8-(res->length() % 8); // 1..8 */
for(int i=0 ; i < (tail-1) ; ++i) res->append('*'); uchar tail= 7-( res->length() %8); // 0..7 marking real offsets 1..8
res->append(tail-1); // Write tail length 0..7 to last pos for(int i=0 ; i < tail ; ++i) res->append('*');
// Real encryption res->append(tail); // Write tail length 0..7 to last pos
des_ede3_cbc_encrypt( str->length(res->length());
(const uchar*)(res->c_ptr()), des_ede3_cbc_encrypt( // Real encryption
(uchar*)(res->c_ptr()), (const uchar*)(res->c_ptr()),
(uchar*)(str->c_ptr()),
res->length(), ks1, ks2, ks3, &ivec, TRUE); res->length(), ks1, ks2, ks3, &ivec, TRUE);
if(mode) { res->set((const char*)"1",(uint)1);
// In case of ASCII mode we should convert binary string into ASCII for(uint i=0 ; i < str->length() ; ++i)
str->set((const char*)0,(uint)0); {
for(uint i=0 ; i < res->length() ; ++i) { res->append(bin_to_ascii((uchar)str->c_ptr()[i] & 0x3f));
str->append(bin_to_ascii((uchar)res->c_ptr()[i] & 0x3f)); res->append(bin_to_ascii(((uchar)str->c_ptr()[i] >> 5 ) & 0x3f));
str->append(bin_to_ascii(((uchar)res->c_ptr()[i] >> 5 ) & 0x3f));
} }
return str; }
} else return res;
return res;
#else #else
null_value=1; null_value=1;
return 0; return 0;
...@@ -267,43 +276,46 @@ String *Item_func_des_decrypt::val_str(String *str) ...@@ -267,43 +276,46 @@ String *Item_func_des_decrypt::val_str(String *str)
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
des_key_schedule ks1, ks2, ks3; des_key_schedule ks1, ks2, ks3;
des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
union { struct {
des_cblock allkeys[3]; // 24 bytes total
des_cblock key1, key2, key3; // 8 bytes each des_cblock key1, key2, key3; // 8 bytes each
} key; } keyblock;
if ((null_value=args[0]->null_value)) if ((null_value=args[0]->null_value))
return 0; return 0;
if (res->length() == 0) if (res->length() == 0)
return &empty_string; return &empty_string;
String *keystr=args[1]->val_str(&tmp_value);
int32 mode=0; if(res->c_ptr()[0]=='1') // Skip decryption if not encrypted
if(arg_count == 3 && !args[2]->null_value) {
mode=args[2]->val_int(); str->set((const char*)0,(uint)0);
// We make good 24-byte (168 bit) key from given plaintext key with MD5 for(uint i=1 ; i < res->length() ; i+=2)
EVP_BytesToKey(EVP_get_cipherbyname("DES-EDE3-CBC"),EVP_md5(),NULL, {
(uchar *)keystr->c_ptr(),
keystr->length(),1,(uchar *)&key.allkeys,ivec);
// Here we set all 64-bit keys (56 effective) one by one
des_set_key_unchecked(&key.key1,ks1);
des_set_key_unchecked(&key.key2,ks2);
des_set_key_unchecked(&key.key3,ks3);
str->set((const char*)0,(uint)0);
if(mode) {
for(uint i=0 ; i < res->length() ; i+=2) {
str->append((ascii_to_bin(res->c_ptr()[i])) str->append((ascii_to_bin(res->c_ptr()[i]))
| (ascii_to_bin(res->c_ptr()[i+1]) << 5 )); | (ascii_to_bin(res->c_ptr()[i+1]) << 5 ));
} }
} else
str->copy(res->c_ptr()); String *keystr=args[1]->val_str(&tmp_value);
// Real decryption int32 mode=0;
des_ede3_cbc_encrypt( if(arg_count == 3 && !args[2]->null_value)
mode=args[2]->val_int();
/* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
(uchar *)keystr->c_ptr(),
(int)keystr->length(),1,(uchar *)&keyblock,ivec);
des_set_key_unchecked(&keyblock.key1,ks1); // Here we set all 64-bit keys
des_set_key_unchecked(&keyblock.key2,ks2); // (56 effective) one by one
des_set_key_unchecked(&keyblock.key3,ks3);
res->length(str->length());
des_ede3_cbc_encrypt( // Real decryption
(const uchar*)(str->c_ptr()), (const uchar*)(str->c_ptr()),
(uchar*)(res->c_ptr()), (uchar*)(res->c_ptr()),
str->length(), str->length(),
ks1, ks2, ks3, &ivec, FALSE); ks1, ks2, ks3, &ivec, FALSE);
uchar tail=(res->c_ptr()[str->length()-1]) & 0x7; uchar tail=(res->c_ptr()[res->length()-1]) & 0x7;
res->length(str->length()-tail-1); if((res->length() > ((uint)1+tail))) // We should avoid negative length
res->length(res->length()-1-tail); // (can happen with wrong key)
}
return res; return res;
#else #else
null_value=1; null_value=1;
......
...@@ -230,7 +230,7 @@ public: ...@@ -230,7 +230,7 @@ public:
Item_func_des_encrypt(Item *a, Item *b): Item_str_func(a,b) {} Item_func_des_encrypt(Item *a, Item *b): Item_str_func(a,b) {}
Item_func_des_encrypt(Item *a, Item *b, Item *c): Item_str_func(a,b,c) {} Item_func_des_encrypt(Item *a, Item *b, Item *c): Item_str_func(a,b,c) {}
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length = 13; } void fix_length_and_dec() { maybe_null=1; max_length = args[0]->max_length; }
const char *func_name() const { return "des_encrypt"; } const char *func_name() const { return "des_encrypt"; }
}; };
...@@ -242,7 +242,7 @@ public: ...@@ -242,7 +242,7 @@ public:
Item_func_des_decrypt(Item *a, Item *b): Item_str_func(a,b) {} Item_func_des_decrypt(Item *a, Item *b): Item_str_func(a,b) {}
Item_func_des_decrypt(Item *a, Item *b, Item *c): Item_str_func(a,b,c) {} Item_func_des_decrypt(Item *a, Item *b, Item *c): Item_str_func(a,b,c) {}
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length = 13; } void fix_length_and_dec() { maybe_null=1; max_length = args[0]->max_length; }
const char *func_name() const { return "des_decrypt"; } const char *func_name() const { return "des_decrypt"; }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment