Cryptage des données dans Oracle 9iDate de publication : le 16 Novembre 2006
Par
Mohammed Bouayoun Dans cet article, on décrit comment crypter les données dans une base Oracle 9i
I. Introduction
II. Remplissage et Chaînage
III. Cryptage des données
IV. Le vecteur d'initialisation
V. Décryptage de données
VI. Remerciements
I. Introduction
Le Cryptage, appelée également chiffrement, est un processus consistant à convertir des données de texte simple en texte crypté afin de
les rendre incompréhensibles par un tiers non autorisé. Ce procédé se fait par le biais d'une clé de cryptage.
À partir de la 9i, Oracle fournit le paquetage DBMS_OBFUSCATION_TOOLKIT qui utilise seulement deux types de cryptages standards :
DES et Triple DES.
 |
DES : Data Encryption Standard. Outil de cryptographie, mis au point par IBM dans les années 1970.
|
Le triple DES est basé sur une clé de 128 bytes et est plus robuste qu'un simple DES qui est basé sur une clé de 56 bytes.
 |
Le DES 56 bits a été cassé en moins de 24 heures par Distributed.net, en janvier 1999.
À la place du DES,
NIST (novembre 2001)
recommande l'utilisation de l'AES (Advanced Encryption Standard) qu'on va trouver
dans le nouveau paquetage DBMS_CRYPTO (Oracle 10g).
|
II. Remplissage et Chaînage
Quand une chaîne de caractères est cryptée, elle est divisée en plusieurs morceaux de 8 bytes, qui sont
traités indépendamment par l'algorithme de cryptage. Quand la longueur de données n'est pas un multiple
de 8 bytes, l'algorithme ajoute quelques caractères à la fin pour l'amener exactement à 8 bytes.
Ce processus est connu sous le nom de Remplissage (Padding).
Pour sécuriser la valeur de ce remplissage, on peut utiliser une méthode de remplissage pré-développée
dans Oracle, connue sous le nom de PCKS#5 (Public Key Cryptography System), mais il existe d'autres options.
Quand une chaîne a été divisée en plusieurs morceaux, après, on doit ensuite les relier ensemble,
ce processus est connu sous le nom de Chaînage (chaining). En général, la sécurité d'un système
de cryptage est basée sur la manière d'enchaîner ces morceaux. Oracle fournit les méthodes suivantes :
| Méthode |
Description |
| CBC |
Cipher Block Chaining, la méthode la plus utilisé |
| ECB |
Electronic Code Book |
| CFB |
Cipher Feedback |
| OFB |
Output Feedback |
III. Cryptage des données
On va chiffrer le mot MOHAMMEDBOUAYOUN avec la clé ABCDEFGHIJKLMNOP
DECLARE
val_crypt VARCHAR2(200);
BEGIN
DBMS_OBFUSCATION_TOOLKIT.des3encrypt
(entree => 'MOHAMMEDBOUAYOUN',
cle => 'ABCDEFGHIJKLMNOP',
crypte => chif_val
);
DBMS_OUTPUT.put_line('Valeur chiffrée = '|| val_crypt);
END;
Valeur chiffrée = â4u¿Nc
ä§)^Sóq |
Il peut être intéressant de stocker le résultat de la requête, pour par exemple l'imprimer.
On peut également convertir cette valeur en un type de données RAW par le package UTL_RAW puis
en Hexadécimal avec la fonction RAWTOHEX.
Ce qui donne :
DECLARE
val_chif VARCHAR2(200);
BEGIN
DBMS_OBFUSCATION_TOOLKIT.des3encrypt
(entree => 'MOHAMMEDBOUAYOUN',
cle => 'ABCDEFGHIJKLMNOP',
crypte => chif_val
);
val_chif := RAWTOHEX(UTL_RAW.cast_to_raw(val_chif));
DBMS_OUTPUT.put_line('Valeur chiffrée = '|| val_chif);
END;
Valeur chiffrée = E23475AD8A4E630A81E4A7295E53F371 |
On peut aussi convertir la valeur chiffrée de l'Hexadecimal en valeur numérique
val_chif := to_number('E23475AD8A4E630A81E4A7295E53F371','XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
Valeur chiffré = 300677913275234235803498582057300521841 |
Dans les exemple précédents on a utilisé la fonction DES3ENCRYPT qui est un triple
chiffrement DES. On peut utiliser d'autres fonctions.
Pour faciliter les choses, on crée la fonction :
CREATE OR REPLACE FUNCTION encrypte (p_entree IN VARCHAR2, p_cle IN VARCHAR2)
RETURN VARCHAR2
IS
l_crypte VARCHAR2 (200);
BEGIN
l_crypte :=
DBMS_OBFUSCATION_TOOLKIT.des3encrypt (input_string => p_entree,
key_string => p_cle
);
l_crypte := RAWTOHEX (UTL_RAW.cast_to_raw (l_crypte));
RETURN l_crypte;
END;
DECLARE
v_crypte VARCHAR2 (200);
BEGIN
v_crypte := encrypte ('MOHAMMEDBOUAYOUN', 'ABCDEFGHIJKLMNOP');
DBMS_OUTPUT.put_line ('Valeur chiffrée= ' || v_crypte);
END;
/ |
Le resultat est :
| Valeur chiffrée = E23475AD8A4E630A81E4A7295E53F371 |
Modifions la valeur à chiffrer MOHAMMEDBOUAYOUN par MOHAMMEDBOUAYOUN1.
Ceci nous donne le script suivant :
DECLARE
v_crypte VARCHAR2 (200);
BEGIN
v_crypte := encrypte ('MOHAMMEDBOUAYOUN1', 'ABCDEFGHIJKLMNOP');
DBMS_OUTPUT.put_line ('Encrypted value = ' || v_crypte);
END;
/ |
En lançant le script précédent, on a l'erreur suivante :
ORA-28232: invalid input length for obfuscation toolkit
ORA-06512: at "SYS.DBMS_OBFUSCATION_TOOLKIT_FFI", line 0
ORA-06512: at "SYS.DBMS_OBFUSCATION_TOOLKIT", line 216
ORA-06512: at "SYSTEM.ENCRYPTE", line 6
ORA-06512: at line 4 |
On obtient cette erreur car l'entrée de la fonction DES3ENCRYPT doit être un multiple de
8 caractères, ce type de chiffrement est connu sous le nom de chiffrement par bloc (block ciphering).
Pour remédier à ce problème, on écrit une autre fonction qui ajoute des espaces pour que
la longueur de l'entrée soit un multiple de 8.
CREATE OR REPLACE FUNCTION encrypte (p_entree IN VARCHAR2, p_cle IN VARCHAR2)
RETURN VARCHAR2
IS
l_crypte VARCHAR2 (200);
l_entree VARCHAR2 (200);
BEGIN
l_entree := RPAD(p_entree,(8*ROUND(LENGTH(p_entree)/8,0)+8));
l_crypte :=
DBMS_OBFUSCATION_TOOLKIT.des3encrypt (input_string => l_entree,
key_string => p_cle
);
l_crypte := RAWTOHEX (UTL_RAW.cast_to_raw (l_crypte));
RETURN l_crypte;
END;
DECLARE
v_crypte VARCHAR2 (200);
BEGIN
v_crypte := encrypte ('MOHAMMEDBOUAYOUN1', 'ABCDEFGHIJKLMNOP');
DBMS_OUTPUT.put_line ('Valeur chiffrée = ' || v_crypte);
END;
/ |
Le résultat est :
| Valeur chiffrée = E23475AD8A4E630A81E4A7295E53F371DC94046D7D5747F8 |
IV. Le vecteur d'initialisation
Dans la méthode utilisée précédemment, un intrus peut utiliser un utilitaire de cryptoanalyse
pour vérifier l'entête de l'information cryptée en identifiant le pattern. Pour éviter ceci, il est possible
d'ajouter une valeur aléatoire au début la donnée en cours. Si par exemple, on a la valeur 12345678,
on peut attacher au début la valeur 6564 qui devient 656412345678 puis l'encrypter après.
L'entête de l'information contiendra des valeurs en relation avec 6564, et non pas avec la valeur
en cours 12345678. Il ne faut pas oublier d'enlever la valeur aléatoire 6564 après le décryptage.
La valeur aléatoire préfixe au données est connu sous le nom vecteur d'initialisation (IV).
Dans DBMS_OBFUSCATION_TOOLKIT, on spécifie ce vecteur d'initialisation dans la fonction DES3ENCRYPT
comme un paramètre supplémentaire appelé iv_string. La combinaison de l'IV avec la donnée doit être
un multiple de huit.
CREATE OR REPLACE FUNCTION encrypte (
p_entree IN VARCHAR2,
p_cle IN VARCHAR2,
p_iv IN VARCHAR2 := NULL
)
RETURN VARCHAR2
IS
l_crypte VARCHAR2 (200);
l_entree VARCHAR2 (200);
l_iv VARCHAR2 (200);
BEGIN
l_entree := RPAD (p_entree, (8 * ROUND (LENGTH (p_entree) / 8, 0) + 8));
l_iv := RPAD (p_iv, (8 * ROUND (LENGTH (p_iv) / 8, 0) + 8));
l_crypte :=
DBMS_OBFUSCATION_TOOLKIT.des3encrypt (input_string => l_entree,
key_string => p_cle,
iv_string => l_iv
);
l_crypte := RAWTOHEX (UTL_RAW.cast_to_raw (l_crypte));
RETURN l_crypte;
END; |
V. Décryptage de données
Maintenant, on va essayer de décrypter la valeur originale avec la fonction DES3DECRYPT.
On créera une valeur cryptée depuis un texte clair et on le décryptera.
DECLARE
l_crypte VARCHAR2 (2000);
l_decrypte VARCHAR2 (2000) := 'Clear Text Data';
l_cle VARCHAR2 (2000) := 'ABCDEFGHIJKLMNOP';
BEGIN
l_crypte := get_enc_val (l_decrypte, l_cle, '12345678');
l_decrypte :=
DBMS_OBFUSCATION_TOOLKIT.des3decrypt
(input_string => UTL_RAW.cast_to_varchar2
(HEXTORAW (l_crypte)
),
key_string => l_cle
);
DBMS_OUTPUT.put_line ('Valeur décryptée = ' || l_decrypte);
END;
/ |
Le résultat est différent de la valeur originale !
Tout simplement, on doit spécifier l'IV pendant le décryptage qui était 12345678.
DECLARE
l_crypte VARCHAR2 (2000);
l_decrypte VARCHAR2 (2000) := 'Clear Text Data';
l_cle VARCHAR2 (2000) := 'ABCDEFGHIJKLMNOP';
BEGIN
l_enc_val := encrypte (l_decrypte, l_cle, '12345678');
l_decrypte :=
DBMS_OBFUSCATION_TOOLKIT.des3decrypt
(input_string => UTL_RAW.cast_to_varchar2
(HEXTORAW (l_crypte)
),
key_string => l_cle,
iv_string => '12345678'
);
DBMS_OUTPUT.put_line ('Valeur Décryptée = ' || l_decrypte);
END;
/ |
Le résultat est :
Valeur Décryptée = Clear Text Data
PL/SQL procedure successfully completed. |
VI. Remerciements
Je tiens à remercier toute l'équipe de Developpez.com pour son aide dans la relecture et
l'amélioration du présent tutoriel, en particulier Xo pour la correction de l'orthographe.
 
Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur.
La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.
|