Posts Tagged ‘hash’

28
nov

Les nouveautés de MySQL 5.1 — (part 1/5)

   Posted by: freshdaz    in MySQL

Que de chemin parcouru depuis ce 5 juillet 1999, date de lancement de MySQL 3.23.0. En plus des objectifs de simplicité d’administration, de hautes performances et de fiabilité, se sont greffées, au fur et à mesure, les fonctionnalités les plus demandées par les utilisateurs. La nouvelle version du SGBDR open-source le plus utilisé, sortie en GA le jeudi 27 novembre 2008, ne déroge pas à ces règles d’or. Numéro un pour les applications en ligne, MySQL se positionne maintenant sur le secteur des applications d’entrepôts de données et d’informatique décisionnelle.

Le but de cet article est de brasser un large panorama des principales nouveautés de MySQL 5.1, telles que le partitionnement, le programmateur d’évènements, la réplication par les données, ainsi que le support des données sur disque avec MySQL Cluster et le support xml/xpath.

Le partitionnement

Une des fonctionnalités phare de cette nouvelle mouture, est la possibilité de partitionner ses tables MySQL. Le partitionnement consiste à fragmenter une table en fonction des données qu’elle contient. Le but principal est d’optimiser les performances : le partitionnement peut permettre d’améliorer les réponses de certaines requêtes. Les données étant stockées dans différentes partitions, l’optimiseur ne prendra pas en compte les partitions non impactées par la requête (PRUNING).

Un autre objectif est de faciliter certaines tâches de maintenance : les données d’une partition peuvent être facilement et rapidement effacées, simplement en supprimant la partition.

Enfin, le partitionnement permet de mettre les données et les index sur des disques différents : il est possible de stocker les données et les index sur des disques séparés, pour les tables MyISAM.

Le partitionnement avec MySQL

La commande SHOW VARIABLES LIKE ‘have_partitioning’ est un moyen simple de savoir si votre version de MySQL supporte le partitionnement.

mysql> SHOW VARIABLES LIKE 'have_partitioning';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| have_partitioning | YES   |
+-------------------+-------+
1 row in set (0.10 sec)

L’opération de partitionnement proprement dite se réalise lors de la création de la table (avec la commande CREATE TABLE) ou lors de la modification de sa structure (avec la commande ALTER TABLE) en utilisant la clause PARTITION BY.

CREATE TABLE ... ENGINE = <engine>
      PARTITION BY <type> ( <expression> )

Il est a noter que les moteurs Merge, Federated, CSV ne permettent pas le partitionnement.

<engine> = MyIsam | InnoDB | Archive | Falcon | NDBCluster | Memory

MySQL propose 4 types de partitionnement, par intervalle (RANGE), par liste (LIST), et par hachage (HASH ou KEY).

<type> = RANGE | LIST | HASH | KEY

Quelques exemples de partitionnements

Partitionner sa table est une opération très simple. Le plus délicat est finalement de savoir pourquoi partitionner et comment le faire. Le critère de partitionnement est donc essentiel pour espérer gagner en performance.

-- Partitionnement par intervalle
CREATE TABLE 'City_part_range' (
   'ID' int(11) NOT NULL AUTO_INCREMENT,
   'Population' int(11) NOT NULL DEFAULT '0',  KEY 'ID' ('ID')
) ENGINE=MyISAM
   PARTITION BY RANGE (population) (
   PARTITION p0 VALUES LESS THAN (100),
   PARTITION p1 VALUES LESS THAN (1000),
   PARTITION p2 VALUES LESS THAN (10000),
   PARTITION p3 VALUES LESS THAN (100000),
   PARTITION p4 VALUES LESS THAN (1000000),
   PARTITION p5 VALUES LESS THAN MAXVALUE
);

-- Partitionnement par liste
CREATE TABLE 'Country_part_list' (
   'Code' char(3) NOT NULL DEFAULT '',
   'Continent' tinyint UNSIGNED DEFAULT 1,
   KEY ('Code')
) ENGINE=MEMORY
   PARTITION BY LIST(Continent) (
   PARTITION pCateg1 VALUES IN (1),
   PARTITION pCateg2 VALUES IN (4),
   PARTITION pCateg3 VALUES IN (2,6),
   PARTITION pCateg4 VALUES IN (3,5,7)
);

-- Partitionnement par hash
CREATE TABLE 'City_part_hash' (
   'ID' int(11) NOT NULL AUTO_INCREMENT,
   'Name' char(35) NOT NULL DEFAULT '',
   'CountryCode' char(3) NOT NULL DEFAULT '',
   'District' char(20) NOT NULL DEFAULT '',
   'Population' int(11) NOT NULL DEFAULT '0',
   PRIMARY KEY ('ID')
) ENGINE=InnoDB PARTITION BY HASH (id) PARTITIONS 4;

-- Partitionnement par key
CREATE TABLE 'City_part_key' (
   'ID' int(11) NOT NULL AUTO_INCREMENT,
   'Name' char(35) NOT NULL DEFAULT '',
   'CountryCode' char(3) NOT NULL DEFAULT '',
   'District' char(20) NOT NULL DEFAULT '',
   'Population' int(11) NOT NULL DEFAULT '0',
   PRIMARY KEY ('ID')
) ENGINE=Archive PARTITION BY KEY () PARTITIONS 6;

(à suivre... event scheduler & row based Replication)

Tags: , , , , , ,

11
nov

Hash, sécurité & MySQL

   Posted by: freshdaz    in MySQL

Une fonction de hash est une fonction qui prend une chaîne de caractères en entrée et qui renvoi une autre chaine de caractères. La chaîne de caractères résultat a toujours la même longueur et est strictement identique pour une même entrée.

Une des utilisations du hashage sert a masquer les mots de passes stockés dans une table.

Au lieu d’avoir une table utilisateur, faiblement sécurisée avec un mot de passe en clair:

+----------+------------------------+
| name     | password_en_clair      |
+----------+------------------------+
| freshdaz | mot_de_passe           |
+----------+------------------------+

Il est préférable d’avoir ceci, le même mot de passe mais hashé:

+----------+---------------------------------------+
| name     | password_hash                         |
+----------+---------------------------------------+
| freshdaz | 8b70bf2ffce34ced3223dfc9e4fa9cc7      |
+----------+---------------------------------------+

Comme vous pouvez le constater le mot de passe hashé est plus difficile à lire, d’autant plus que le hash est (sensé être) irréversible (en fait tout est une question de temps).

MySQL propose 5 fonctions de hashage:

CRC : (contrôle de redondance cyclique)

c’est une méthode pour contrôler l’intégrité des données, donc hors sujet :)

mysql> SELECT crc32('mot_de_passe');
+-----------------------+
| crc32('mot_de_passe') |
+-----------------------+
|             965676113 |
+-----------------------+

MD5 : (Message Digest 5)

très populaire mais n’est donc plus considéré comme sûr au sens cryptographique. Autrement dit, une petite recherche sur le net et vous trouverez facilement des algorithmes pour le cracker.

mysql> SELECT md5('mot_de_passe');
+----------------------------------+
| md5('mot_de_passe')              |
+----------------------------------+
| 8b70bf2ffce34ced3223dfc9e4fa9cc7 |
+----------------------------------+

SHA1 : (Secure Hash Algorithm )

Conçue par la National Security Agency (NSA) (est-ce une bonne nouvelle ?) :D

Plus sécurisé que le md5.

mysql> SELECT sha1('mot_de_passe');
+------------------------------------------+
| sha1('mot_de_passe')                     |
+------------------------------------------+
| d10c988ca61b785f5a7756b5852683d798fe4d92 |
+------------------------------------------+

PASSWORD:

Algorithme « maison » de MySQL. Utilisé pour stocker les mots de passes des utilisateurs du serveur MySQL.

mysql> SELECT password('mot_de_passe');
+-------------------------------------------+
| password('mot_de_passe')                  |
+-------------------------------------------+
| *C3D87F1C2FADE3F03484FC62E669276C2A37266F |
+-------------------------------------------+

OLD_PASSWORD :

Ancien algorithme pour stocker les mot de passes des utilisateurs du serveur MySQL. Utilisé jusqu’à la version 4.0.x de MySQL. Il a été changé lui aussi pour des raison de sécurité. Là encore vous trouverez très facilement le nécessaire pour le cracker.

mysql> SELECT old_password('mot_de_passe');
+------------------------------+
| old_password('mot_de_passe') |
+------------------------------+
| 684ec7590a2271b0             |
+------------------------------+

Quelles fonctions utiliser ?

Comme souvent en informatique, il faut faire un compromis entre meilleurs performances et sécurité optimale. En d’autre terme un sha1 plus sécurisé qu’un md5 mettra cependant plus de temps pour hasher une même chaine de caractères.

Vérifions tout ceci:

mysql> SELECT md5('olivierdasini');
+----------------------------------+
| md5('olivierdasini')             |
+----------------------------------+
| a42bc0139343fc758a414f70eda6f209 |
+----------------------------------+
1 row in set (0.00 sec)

mysql> SELECT sha1('olivierdasini');
+------------------------------------------+
| sha1('olivierdasini')                    |
+------------------------------------------+
| f2cdbfdf62d717ab96528235a1b1ff34671860d4 |
+------------------------------------------+
1 row in set (0.00 sec)

hum, hum pas très probant…

Aidons nous de la fonction benchmark():

mysql> SELECT benchmark(3000000,md5('olivierdasini'));
+-----------------------------------------+
| BENCHMARK(3000000,md5('olivierdasini')) |
+-----------------------------------------+
|                                       0 |
+-----------------------------------------+
1 row in set (12.27 sec)

mysql> SELECT benchmark(3000000,sha1('olivierdasini'));
+------------------------------------------+
| BENCHMARK(3000000,sha1('olivierdasini')) |
+------------------------------------------+
|                                        0 |
+------------------------------------------+
1 row in set (15.91 sec)

En exécutant ces 2 fonctions plusieurs fois, (grâce à benchmark()) on s’aperçoit qu’il faut environ 25% de temps supplémentaire pour l’algorithme sha1 que pour le md5. Ce qui est loin d’être négligeable.

Regardons comment se débrouillent les fonctions « maison » de MySQL:

mysql> SELECT benchmark(3000000,password('olivierdasini'));
+----------------------------------------------+
| BENCHMARK(3000000,password('olivierdasini')) |
+----------------------------------------------+
|                                            0 |
+----------------------------------------------+
1 row in set (7.24 sec)

17:08 root$test> SELECT benchmark(3000000,old_password('olivierdasini'));
+--------------------------------------------------+
| BENCHMARK(3000000,old_password('olivierdasini')) |
+--------------------------------------------------+
|                                                0 |
+--------------------------------------------------+
1 row in set (4.26 sec)

Le verdict est sans appels, avec ses 7 secondes (près de 50% de temps en moins que md5 ), la fonction password() est d’un bon rapport performance sécurité. Pour rappel, c’est cette fonction qu’utilise le serveur MySQL pour gérer les mots de passes de ses comptes utilisateurs. Inconvénient non négligeable, elle est spécifique (à ma connaissance) à MySQL (mais est-ce vraiment un inconvénient ?  :) ).

Quant à l’ancienne façon de hasher les mots de passes, elle est évidement très performante, mais on a vu que niveau sécurité, elle laisse à désirer…

Les fonctions présentées sont une bonne solution pour sécuriser ses mots de passes. Il est néanmoins possible d’augmenter encore un peu plus le niveau de sécurité. Une des techniques consiste à renforcer le mot de passe utilisateur en lui rajoutant une chaine de caractères et en combinant plusieurs algorithmes de hashage.

Par exemple, avec comme mot de passe: olivierdasini, on peut concaténer, avec la fonction concat(), la date de naissance: 121174_ et combiner différents algorithmes:

mysql> SELECT benchmark(3000000,md5(concat(sha1('121174_'), 'olivierdasini')));
+------------------------------------------------------------------+
| benchmark(3000000,md5(concat(sha1('121174_'), 'olivierdasini'))) |
+------------------------------------------------------------------+
|                                                                0 |
+------------------------------------------------------------------+
1 row in set (29.30 sec)
mysql> SELECT benchmark(3000000,password(concat(old_password('121174_'), 'olivierdasini')));
+-------------------------------------------------------------------------------+
| benchmark(3000000,password(concat(old_password('121174_'), 'olivierdasini'))) |
+-------------------------------------------------------------------------------+
|                                                                             0 |
+-------------------------------------------------------------------------------+
1 row in set (12.06 sec)

Avec de telles combinaisons, vos mots de passes sont plus à l’abri, par contre les temps de hashage sont doublés. Comme ont le disait précédemment, tout est une histoire de compromis.

Tags: , ,