Comment crypter et décrypter des champs en AES128 dans une base Oracle 10g

[ 1 ] Commentaire
Share

Voilà un petit bout de code qui fonctionne très bien pour crypter des champs en base de donnée. L’avantage du cryptage par rapport à un chiffrage (= un hash MD5 par ex) c’est qu’il est bijectif, c’est à dire qu’à une chaine de caractère non cryptée correspond exactement une seule autre chaine de caractère cryptée (et l’inverse est vrai). En plus, le cryptage permet d’être « décrypté », ce que ne permet pas un hash (cela découle de la bijectivité, d’ailleurs -dites moi si je dis des bêtises).

Donc le code fonctionne sur une base Oracle 10g. Il utilise notamment la fonction Oracle DBMS_CRYPTO (notez que vous devez avoir les droits suffisant pour exécuter cette fonction). Tout ce petit monde a besoin de variables, définies préalablement, donc c’est rangé dans une procédure PLSQL de base.

Le cryptage du champs

DECLARE 
raw_key RAW(2000);
encrypted_field RAW(30000);
decrypted_field RAW(30000);
encryption_type PLS_INTEGER :=  DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_ECB + DBMS_CRYPTO.PAD_PKCS5;
v_counter INTEGER := 0;
BEGIN
    
    -- First the key is hashed with md5 to make it a 128bit key:
    raw_key := DBMS_CRYPTO.Hash (UTL_I18N.STRING_TO_RAW ('your_personnal_key', 'WE8ISO8859P15'), DBMS_CRYPTO.HASH_MD5);
    
    encrypted_field := DBMS_CRYPTO.ENCRYPT(UTL_I18N.STRING_TO_RAW(field_to_encrypt, 'WE8ISO8859P15'), encryption_type, raw_key);
    
    update my_table set field_to_encrypt = encrypted_field ;
    
    COMMIT;
END;
/

Explication du fonctionnement : comme vous l’avez vu : la clef de 128 bits est générée via un hash MD5 d’une clef personnelle (qui sera nécessaire pour le décryptage), et tout ça est envoyé à la méthode DBMS_CRYPTO qui sort le contenu crypté.

Le décryptage du champs

Pour ce qui est du décryptage, ça fonctionne de la même façon, mais avec la fonction DBMS_CRYPTO.DECRYPT, qui prend les mêmes arguments que DBMS_CRYPTO.ENCRYPT (sauf qu’au lieu de lui donner le champ de base, vous lui filez le champs cypté :

decrypted_raw := dbms_crypto.Decrypt(
        src => encrypted_raw, 
        typ => DBMS_CRYPTO.DES_CBC_PKCS5, 
        key => raw_key);

Sur l’exemple ci-dessus, l’algo de cryptage utilisé était DES_CBC_PKCS5. Les différents algo (et la façon de les appeler) supportés sont listés là. Notez également que sur cet exemple, la decrypted_raw sort en RAW. Il faudra donc faire un UTL_RAW.CAST_TO_VARCHAR2(decrypted_raw) pour pouvoir correctement la lire dans la sortie standard.

Donc pour l’exemple issu du cryptage, ça aurait donné :

decrypted_field := UTL_RAW.CAST_TO_VARCHAR2(dbms_crypto.Decrypt(
        src => encrypted_field, 
        typ => encryption_type, 
        key => raw_key));

Attention aussi au fait que beaucoup de problèmes peuvent venir de l’encodage. Notamment parce que AES va vous sortir des bytes (sans charset), et qu’il va falloir les mettre dans la base sans qu’ils soient filtrés (et changés) par le charset du champs. Donc choisir un BLOB ou un RAW pour ce champs (et non pas un CLOB qui a un charset). Pareil, une fois récupéré dans la base, ce sera des bytes que vous aurez en main. Donc il vous faudra les remettre dans le bon charset (celui que vous utilisez habituellement pour vos champs).

Source de toutes les infos : le site d’Oracle

[Image]

Edit : on ne parle de décryptage que quand on n’a pas la clef utilisée pour le chiffrage. Cf Wikipedia : « Décrypter consiste à retrouver le texte original à partir d’un message chiffré sans posséder la clé de (dé)chiffrement. » (et merci à Chouchoune pour l’info)

Vous serez peut-être intéressé :

Un commentaire sur ce billet

  1. FOURATI dit :

    J’ai besoin de documentation concernant le cryptage/décryptage des données en oracle 10g.

    RépondreRépondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *