

  Le module pgcrypto propose des fonctions de
  cryptographie pour PostgreSQL.
 
digest()
    digest(data text, type text) returns bytea
    digest(data bytea, type text) returns bytea
   
    Calcule un hachage binaire de data.
    type est l'algorithme utilisé. Les algorithmes
    standards sont md5 et
    sha1. Si pgcrypto a été construit
    avec OpenSSL, d'autres algorithmes sont disponibles comme le détaille
    Tableau F.19.
   
    Si vous voulez en résultat une chaîne hexadécimale, utilisez
    encode() sur le résultat. Par exemple :
   
    CREATE OR REPLACE FUNCTION sha1(bytea) returns text AS $$
      SELECT encode(digest($1, 'sha1'), 'hex')
    $$ LANGUAGE SQL STRICT IMMUTABLE;
   hmac()
    hmac(data text, key text, type text) returns bytea
    hmac(data bytea, key bytea, type text) returns bytea
   
    Calcule un MAC haché sur data avec la clé
    key.
    type est identique à digest().
   
    C'est similaire à digest() mais le hachage peut être
    recalculé en connaissant seulement la clé. Ceci évite le scénario où
    quelqu'un modifie les données et le hachage en même temps.
   
Si la clé est plus grosse que le bloc haché, il sera tout d'abord haché puis le résultat sera utilisé comme clé.
   Les fonctions crypt() et
   gen_salt() sont spécialement conçues pour hacher les
   mots de passe.
   crypt() s'occupe du hachage et
   gen_salt() prépare les paramètres de l'algorithme pour
   ça.
  
   Les algorithmes de crypt() diffèrent des algorithmes
   de hachage habituels comme MD5 ou SHA1 :
  
Ils sont lents. Comme la quantité de données est petite, c'est le seul moyen de rendre difficile la découverte par la force des mots de passe.
Ils incluent une valeur aléatoire appelée sel (salt en anglais) avec le résultat, pour que les utilisateurs qui ont le même mot de passer puissent avoir des mots de passe chiffrés différents. C'est aussi une défense supplémentaire comme l'inversion de l'algorithme.
Ils incluent le type de l'algorithme dans le résultat pour que les mots de passe hachés avec différents algorithmes puissent co-exister.
Certains s'adaptent. Cela signifie que, une fois que les ordinateurs iront plus vite, vous pourrez configurer l'algorithme pour qu'il soit plus lent, ceci sans introduire d'incompatibilité avec les mots de passe existant.
   Tableau F.16 liste les algorithmes
   supportés par la fonction crypt().
  
Tableau F.16. Algorithmes supportés par crypt()
| Algorithme | Longueur maximum du mot de passe | Adaptif ? | Bits sel | Longueur de la sortie | Description | 
|---|---|---|---|---|---|
| bf | 72 | oui | 128 | 60 | Basé sur Blowfish, variante 2a | 
| md5 | unlimited | non | 48 | 34 | crypt() basé sur MD5 | 
| xdes | 8 | oui | 24 | 20 | DES étendu | 
| des | 8 | non | 12 | 13 | crypt original UNIX | 
crypt()
    crypt(password text, salt text) returns text
   
    Calcule un hachage de mot de passe (password)
    d'après crypt(3) UN*X. Lors du stockage d'un nouveau mot de passe, vous
    devez utiliser la fonction gen_salt() pour générer
    un nouveau sel (salt). Lors de la vérification de
    mot de passe, passez la valeur hachée stockée salt,
    et testez si le résultat correspond à la valeur stockée.
   
Exemple d'ajout d'un nouveau mot de passe :
    UPDATE ... SET pswhash = crypt('new password', gen_salt('md5'));
   Exemple d'authentification :
    SELECT (pswhash = crypt('entered password', pswhash)) AS pswmatch FROM ... ;
   
    Ceci renvoie true si le mot de passe saisi est correct.
   
gen_salt()
    gen_salt(type text [, iter_count integer ]) returns text
   
    Génère une nouvelle valeur aléatoire sel pour son utilisation avec
    crypt().
    La chaîne sel indique aussi à crypt() l'algorithme à
    utiliser.
   
    Le paramètre type précise l'algorithme de hachage.
    Les types acceptés sont : des,
    xdes, md5 et bf.
   
    Le paramètre iter_count laisse l'utilisateur
    indiquer le nombre d'itération, pour les algorithmes qui en ont. Plus le
    nombre est important, plus le hachage du mot de passe prendra du temps,
    et du coup plus le craquage du mot de passe prendre du temps. Cela étant
    dit, un nombre trop important rend pratiquement impossible le calcul du
    hachage. Si le paramètre iter_count est omis,
    le nombre d'itération par défaut est utilisé. Les valeurs autorisées pour
    iter_count dépendent de l'algorithme et sont
    affichées dans Tableau F.17.
   
Tableau F.17. Nombre d'itération pour crypt()
| Algorithme | Par défaut | Min | Max | 
|---|---|---|---|
| xdes | 725 | 1 | 16777215 | 
| bf | 6 | 4 | 31 | 
    Pour xdes, il existe une limite supplémentaire qui fait
    que ce nombre doit être un nombre impair.
   
Pour utiliser un nombre d'itération approprié, pensez que la fonction crypt DES original a été conçu pour avoir la vitesse de quatre hachages par seconde sur le matériel de l'époque. Plus lent que quatre hachages par secondes casserait probablement la facilité d'utilisation. Plus rapide que cent hachages à la seconde est probablement trop rapide.
    Tableau F.18 donne un aperçu de la lenteur relative de
    différents algorithmes de hachage. La table montre le temps que prendrait
    le calcul de toutes les combinaisons réalisables pour un mot de passe sur
    huit caractères, en supposant que le mot de passe contient soit que des
    lettres minuscules, soit des lettres minuscules et majuscules et des
    chiffres. Dans les entrées crypt-bf, le nombre après
    un slash est le paramètre iter_count de
    gen_salt.
   
Tableau F.18. Vitesse de l'algorithm de hachage
| Algorithme | Hachages/sec | Pour [a-z] | Pour [A-Za-z0-9] | Durée par rapport à md5 hash | 
|---|---|---|---|---|
| crypt-bf/8 | 1792 | 4 années | 3927 années | 100k | 
| crypt-bf/7 | 3648 | 2 années | 1929 années | 50k | 
| crypt-bf/6 | 7168 | 1 année | 982 années | 25k | 
| crypt-bf/5 | 13504 | 188 années | 521 années | 12.5k | 
| crypt-md5 | 171584 | 15 jours | 41 années | 1k | 
| crypt-des | 23221568 | 157.5 minutes | 108 jours | 7 | 
| sha1 | 37774272 | 90 minutes | 68 jours | 4 | 
| md5(hash) | 150085504 | 22.5 minutes | 17 jours | 1 | 
Notes :
La machine utilisée est un Intel Mobile Core i3.
      Les numéros des algorithmes crypt-des et
      crypt-md5 sont pris de la sortie
      du -test de John the Ripper v1.6.38.
     
      Les nombres hachés md5 font partie de mdcrack 1.2.
     
      Les nombres sha1 font partie de lcrack-20031130-beta.
     
      Les nombres crypt-bf sont pris en utilisant le
      programme simple qui boucle sur 1000 mots de passe de huit caractères.
      De cette façon, je peux afficher la vitesse avec les différents nombres
      de tours. Pour référence : john -test affiche 13506
      tours/sec pour crypt-bf/5. (La petite différence dans
      les résultats est dû au fait que l'implémentation de
      crypt-bf dans pgcrypto est la
      même que celle utilisée dans John the Ripper.)
     
Notez que « tenter toutes les combinaisons » n'est pas un exercice réaliste. Habituellement, craquer les mots de passe se fait avec l'aide de dictionnaires contenant les mots standards et différentes variantes. Donc, même des mots de passe qui ressemblent vaguement à des mots peuvent être craqués plus rapidement que les nombres ci-dessus le suggèrent alors qu'un mot de passe sur six caractères qui ne ressemble pas à un mot pourrait ne pas être craqué.
Les fonctions implémentent la partie chiffrement du standard OpenPGP (RFC 2440). Les chiffrements à clés symétriques et publiques sont supportés.
Un message PGP chiffré consiste en deux parties ou paquets :
Un paquet contenant la clé de session -- soit une clé symétrique soit une clé publique chiffrée.
Paquet contenant les données chiffrées avec la clé de session.
Lors du chiffrement avec une clé symétrique (par exemple, un mot de passe) :
     Le mot de passe est haché en utilisant l'algorithme String2Key (S2K).
     C'est assez similaire à l'algorithme crypt()  -- 
     lenteur voulue et nombre aléatoire pour le sel  --  mais il produit
     une clé binaire de taille complète.
    
Si une clé de session séparée est demandée, une nouvelle clé sera générée au hasard. Sinon une clé S2K sera utilisée directement en tant que clé de session.
Si une clé S2K est à utiliser directement, alors seuls les paramètres S2K sont placés dans le paquet de session. Sinon la clé de session sera chiffrée avec la clé S2K et placée dans le paquet de session.
Lors du chiffrement avec une clé publique :
Une nouvelle clé de session est générée au hasard.
Elle est chiffrée en utilisant la clé public et placée dans le paquet de session.
Dans les deux cas, les données à chiffrer sont traitées ainsi :
Manipulation optionnelle des données : compression, conversion vers UTF-8, conversion de retours à la ligne.
Les données sont préfixées avec un bloc d'octets pris au hasard. C'est identique à l'utilisation de random IV.
Un hachage SHA1 d'un préfixe et de données au hasard est ajouté.
Tout ceci est chiffré avec la clé de la session et placé dans la paquet de données.
pgp_sym_encrypt()
    pgp_sym_encrypt(data text, psw text [, options text ]) returns bytea
    pgp_sym_encrypt_bytea(data bytea, psw text [, options text ]) returns bytea
   
    Chiffre data avec une clé PGP symétrique
    psw.
    Le paramètre options peut contenir des options
    décrites ci-dessous.
   
pgp_sym_decrypt()
    pgp_sym_decrypt(msg bytea, psw text [, options text ]) returns text
    pgp_sym_decrypt_bytea(msg bytea, psw text [, options text ]) returns bytea
   Déchiffre un message PGP chiffré avec une clé symétrique.
    Déchiffrer des données bytea avec pgp_sym_decrypt
    est interdit.
    Ceci a pour but d'éviter la sortie de données de type caractère invalides.
    Déchiffrer des données textuelles avec
    pgp_sym_decrypt_bytea ne pose pas de problème.
   
    Le paramètre options peut contenir les paramètres
    décrits ci-dessous.
   
pgp_pub_encrypt()
    pgp_pub_encrypt(data text, key bytea [, options text ]) returns bytea
    pgp_pub_encrypt_bytea(data bytea, key bytea [, options text ]) returns bytea
   
    Chiffre data avec la clé PGP publique
    key.
    Avec cette fonction, une clé privée renverra une erreur.
   
    Le paramètre options peut contenir des options
    décrites ci-dessous.
   
pgp_pub_decrypt()
    pgp_pub_decrypt(msg bytea, key bytea [, psw text [, options text ]]) returns text
    pgp_pub_decrypt_bytea(msg bytea, key bytea [, psw text [, options text ]]) returns bytea
   
    Déchiffre un message chiffré avec une clé publique.
    key doit être la clé secrète correspondant à la
    clé publique utilisée pour chiffrer. Si la clé secrète est protégée par
    un mot de passe, vous devez saisir le mot de passe dans
    psw. S'il n'y a pas de mot de passe mais que vous
    devez indiquer des options, vous devez saisir un mot de passe vide.
   
    Déchiffrer des données bytea avec pgp_pub_decrypt est
    interdit. Ceci a pour but d'éviter la sortie de données de type caractère
    invalides. Déchiffrer des données textuelles avec
    pgp_pub_decrypt_bytea ne pose pas de problème.
   
    Le paramètre options peut contenir des options
    décrites ci-dessous.
   
pgp_key_id()
    pgp_key_id(bytea) returns text
   
    pgp_key_id extrait l'identifiant de la clé pour
    une clé PGP publique ou secrète. Ou il donne l'identifiant de la clé
    utilisé pour chiffrer les données si un message chiffré est fourni.
   
Elle peut renvoyer deux identifiants de clés spéciaux :
      SYMKEY
     
Le message est chiffré avec une clé symétrique.
      ANYKEY
     
      La donnée est chiffrée avec une clé publique mais l'identifiant de la clé
      est effacé. Cela signifie que vous avez besoin d'essayer toutes les clés
      secrètes pour voir laquelle la déchiffre. pgcrypto
      ne réalise pas lui-même de tels messages.
     
    Notez que des clés différentes peuvent avoir le même identifiant. C'est
    rare mais normal. L'application client doit alors essayer de déchiffer avec
    chacune d'elle pour voir laquelle correspond  --  ce qui revient à la
    gestion de ANYKEY.
   
armor(), dearmor()
    armor(data bytea [ , keys text[], values text[] ]) returns text
    dearmor(data text) returns bytea
   Ces fonctions enveloppent les données dans une armure ASCII PGP qui est basiquement en Base64 avec CRC et un formatage supplémentaire.
    Si les tableaux keys et
    values sont précisées, un entête
     d'armure est ajouté au format standard pour chaque paire
    clé/valeur. Les deux tableaux doivent avoir une seule dimension, et ils
    doivent avoir la même longueur. Les clés et valeurs ne peuvent pas
    contenir de caractères non ASCII.
   
pgp_armor_headerspgp_armor_headers(data text, key out text, value out text) returns setof record
    pgp_armor_headers() extrait les en-têtes d'armure à
    partir de data. La valeur de retour est un ensemble
    de lignes avec deux colonnes, une clé et une valeur. Si les clés ou
    valeurs contiennent des caractères non ASCII, ils sont traités avec
    l'encodage UTF-8.
   
Les options sont nommées de façon similaires à GnuPG. Les valeurs sont fournies après un signe d'égalité ; les options sont séparées par des virgules. Par exemple :
    pgp_sym_encrypt(data, psw, 'compress-algo=1, cipher-algo=aes256')
   
    Toutes les options en dehors de convert-crlf
    s'appliquent seulement aux fonctions de chiffrement. Les fonctions de
    déchiffrement obtiennent des paramètres des données PGP.
   
    Les options les plus intéressantes sont probablement
    compression-algo et unicode-mode.
    Le reste doit avoir des valeurs par défaut raisonnables.
   
Quel algorithme de chiffrement à utiliser.
     Valeurs : bf, aes128, aes192, aes256 (OpenSSL seulement :
     3des, cast5)
     Par défaut : aes128
     Applique à : pgp_sym_encrypt, pgp_pub_encrypt
    
Algorithme de compression à utiliser. Seulement disponible si PostgreSQL a été construit avec zlib.
     Valeurs :
     0 - sans compression
     1 - compression ZIP
     2 -  compression ZLIB [=ZIP plus meta-data and block-CRC's]
     Par défaut : 0
     S'applique à : pgp_sym_encrypt, pgp_pub_encrypt
    
Niveau de compression. Les grands niveaux compressent mieux mais sont plus lents. 0 désactive la compression.
     Valeurs : 0, 1-9
     Par défaut : 6
     S'applique à : pgp_sym_encrypt, pgp_pub_encrypt
    
     Précise si \n doit être converti en
     \r\n lors du chiffrement et \r\n en
     \n  lors du déchiffrement. La RFC 4880 spécifie que
     les données texte doivent être stockées en utilisant les retours chariot
     \r\n. Utilisez cette option pour obtenir un comportement
     respectant la RFC.
    
     Valeurs : 0, 1
     Par défaut : 0
     S'applique à : pgp_sym_encrypt, pgp_pub_encrypt, pgp_sym_decrypt,
     pgp_pub_decrypt
    
Ne protège pas les données avec SHA-1. La seule bonne raison pour utiliser cette option est d'avoir une compatibilité avec les anciens produits PGP précédant l'ajout de paquets protégés SHA-1 dans la RFC 4880. Les versions récentes des logiciels de gnupg.org et pgp.com le supportent.
     Valeurs : 0, 1
     Par défaut : 0
     S'applique à : pgp_sym_encrypt, pgp_pub_encrypt
    
Utilise la clé de session séparée. Le chiffrement par clé publique utilise toujours une clé de session séparée, c'est pour le chiffrement de clé symétrique, qui utilise directement par défaut S2K.
     Valeurs : 0, 1
     Par défaut : 0
     S'applique à : pgp_sym_encrypt
    
Algorithme S2K à utiliser.
     Valeurs :
     0 - Sans sel. Dangereux !
     1 - Avec sel mais avec un décompte fixe des itérations.
     3 - Décompte variables des itérations.
     Par défaut : 3
     S'applique à : pgp_sym_encrypt
    
Le nombre d'itérations de l'algorithme S2K à utiliser. La valeur doit être comprise entre 1024 et 65011712, valeurs incluses.
     Par défaut : Une valeur aléatoire entre 65536 et 253952
     S'applique à : pgp_sym_encrypt, seulement avec s2k-mode=3
    
Algorithme digest à utiliser dans le calcul S2K.
     Valeurs : md5, sha1
     Par défaut : sha1
     S'applique à : pgp_sym_encrypt
    
Chiffrement à utiliser pour le chiffrage de la clé de session séparée.
     Valeurs : bf, aes, aes128, aes192, aes256
     Par défaut : use cipher-algo
     S'applique à : pgp_sym_encrypt
    
Sélection de la conversion des données texte à partir de l'encodage interne de la base vers l'UTF-8 et inversement. Si votre base de données est déjà en UTF-8, aucune conversion ne sera réalisée, seules les données seront marquées comme étant en UTF-8. Sans cette option, cela ne se fera pas.
     Valeurs : 0, 1
     Par défaut : 0
     S'applique à : pgp_sym_encrypt, pgp_pub_encrypt
    
Pour générer une nouvelle clé :
gpg --gen-key
Le type de clé préféré est « DSA and Elgamal ».
    Pour le chiffrement RSA, vous devez créer soit une clé de signature seulement
    DSA ou RSA en tant que maître, puis ajouter la sous-clé de chiffrement RSA
    avec gpg --edit-key.
   
Pour lister les clés :
gpg --list-secret-keys
Pour exporter une clé publique dans un format armure ASCII :
gpg -a --export KEYID > public.key
Pour exporter une clé secrète dans un format armure ASCII :
gpg -a --export-secret-keys KEYID > secret.key
    Vous avez besoin d'utiliser la fonction dearmor() sur
    ces clés avant de les passer aux fonctions PGP. Ou si vous gérez des données
    binaires, vous pouvez supprimer l'option -a pour la
    commande.
   
    Pour plus de détails, voir la page de référence de gpg,
    le livre « GNU
     Privacy Handbook » et d'autres documents sur le
    site gnupg.org.
   
Pas de support des signatures. Cela signifie aussi qu'on ne peut pas vérifier si la sous-clé de chiffrage appartient bien à la clé maître.
Pas de support de la clé de chiffrement en tant que clé maître. Cela ne devrait pas être un problème étant donné que cette pratique n'est pas encouragée.
      Pas de support pour plusieurs sous-clés. Ceci peut être un problème car
      c'est une pratique courante. D'un autre côté, vous ne devez pas utiliser
      vos clés GPG/PGP habituelles avec pgcrypto, mais en
      créer de nouvelles car l'utilisation est assez différente.
     
Ces fonctions exécutent directement un calcul des données ; ils n'ont pas de fonctionnalités avancées de chiffrement PGP. Du coup, ils ont les problèmes majeurs suivant :
Elles utilisent directement la clé de l'utilisateur comme clé de calcul.
Elles ne fournissent pas une vérification de l'intégrité pour savoir si les données chiffrées ont été modifiées.
Elles s'attendent à ce que les utilisateurs gèrent eux-même tous les paramètres du chiffrement, même IV.
Elles ne gèrent pas le texte.
Donc, avec l'introduction du chiffrement PGP, l'utilisation des fonctions de chiffrement brut n'est pas encouragée.
    encrypt(data bytea, key bytea, type text) returns bytea
    decrypt(data bytea, key bytea, type text) returns bytea
    encrypt_iv(data bytea, key bytea, iv bytea, type text) returns bytea
    decrypt_iv(data bytea, key bytea, iv bytea, type text) returns bytea
  
   Chiffrer/déchiffrer les données en utilisant la méthode de calcul spécifiée
   par type. La syntaxe de la chaîne
   type est :
  
algorithm[-mode] [/pad:padding]
   où algorithm fait partie de :
  
bf  --  Blowfish
aes  --  AES (Rijndael-128, -192 ou -256)
   et mode fait partie de :
  
     cbc  --  le bloc suivant dépend du précédent. (par
     défaut)
    
     ecb  --  chaque bloc est chiffré séparément.
     (seulement pour les tests)
    
   et padding fait partie de :
  
     pkcs  --  les données peuvent avoir n'importe quelle
     longueur (par défault)
    
     none  --  les données doivent être des multiples de
     la taille du bloc de calcul.
    
Donc, pour exemple, ces derniers sont équivalents :
encrypt(data, 'fooz', 'bf') encrypt(data, 'fooz', 'bf-cbc/pad:pkcs')
   Dans encrypt_iv et decrypt_iv, le
   paramètre iv est la valeur initiale pour le mode
   CBC ; elle est ignorée pour ECB. Elle est remplie de zéro pour
   l'alignement si la taille de données ne correspond à un multiple de la
   taille du bloc. Elle a pour valeur par défaut que des zéros dans les
   fonctions sans ce paramètre.
  
gen_random_bytes(count integer) returns bytea
   Renvoie count) octets pour un chiffrement fort.
   Il peut y avoir au maximum 1024 octets extrait à un instant t, ceci pour
   éviter de vider le contenu du générateur de nombres aléatoires.
  
gen_random_uuid() returns uuid
Retourne un UUID de version 4 (aléatoire).
    pgcrypto se configure lui-même suivant les
    découvertes du scrip configure principal de PostgreSQL.
    Les options qui l'affectent sont --with-zlib et
    --with-openssl.
   
Quand il est compilé avec zlib, les fonctions de chiffrement PGP peuvent compresser les données avant chiffrement.
Quand il est compilé avec OpenSSL, plus d'algorithmes seront disponibles. De plus, les fonctions de chiffrement à clé publique seront plus rapides car OpenSSL a des fonctions BIGNUM plus optimisées.
Tableau F.19. Résumé de fonctionnalités avec et sans OpenSSL
| Fonctionnalité | Interne | Avec OpenSSL | 
|---|---|---|
| MD5 | oui | oui | 
| SHA1 | oui | oui | 
| SHA224/256/384/512 | oui | oui | 
| D'autres algorithmes digest | non | oui (Note 1) | 
| Blowfish | oui | oui | 
| AES | oui | oui | 
| DES/3DES/CAST5 | non | oui | 
| Raw encryption | oui | oui | 
| PGP Symmetric encryption | oui | oui | 
| PGP Public-Key encryption | oui | oui | 
    Lorsqu'elle est compilée avec OpenSSL 3.0.0 ou
    une version ultérieure, le fournisseur hérité doit être activé dans le
    fichier de configuration openssl.cnf pour utiliser
    les anciens chiffrements tels que DES or Blowfish.
   
Notes :
Tout algorithme digest qu'OpenSSL supporte est automatiquement choisi. Ce n'est pas possible avec les chiffreurs qui doivent être supportés explicitement.
Comme le standard SQL le demande, toutes les fonctions renvoient NULL si un des arguments est NULL. Cela peut permettre une faille de sécurité si c'est utilisé sans précaution.
    Toutes les fonctions de pgcrypto sont exécutées au
    sein du serveur de bases de données. Cela signifie que toutes les données
    et les mots de passe sont passés entre pgcrypto et
    l'application client en texte clair. Donc, vous devez :
   
Vous connecter localement ou utiliser des connexions SSL ;
Faire confiance à votre administrateur système et de base de données.
Si vous ne le pouvez pas, alors il est préférable de chiffrer directement au sein de l'application client.
    L'implémentation ne résiste pas à des attaques par canal
     auxiliaire. Par exemple, le temps requis pour terminer l'exécution
    d'une fonction de déchiffrement de pgcrypto varie
    suivant les texts de déchiffrement d'une certaine taille.
   
https://www.gnupg.org/gph/en/manual.html
The GNU Privacy Handbook.
https://www.openwall.com/crypt/
Décrit l'algorithme crypt-blowfish.
https://www.iusmentis.com/security/passphrasefaq/
Comment choisir un bon mot de passe.
https://www.usenix.org/legacy/events/usenix99/provos.html
Idée intéressante pour choisir des mots de passe.
http://www.interhack.net/people/cmcurtin/snake-oil-faq.html
Décrit la bonne et la mauvaise cryptographie.
https://tools.ietf.org/html/rfc4880
Format du message OpenPGP.
https://tools.ietf.org/html/rfc1321
Algorithme MD5.
https://tools.ietf.org/html/rfc2104
HMAC: Keyed-Hashing for Message Authentication.
http://www.usenix.org/events/usenix99/provos.html
Comparaison des algorithmes crypt-des, crypt-md5 et bcrypt.
https://en.wikipedia.org/wiki/Fortuna_(PRNG)
Description de Fortuna CSPRNG.
Jean-Luc Cooke Fortuna-based /dev/random driver for Linux.
   Marko Kreen <markokr@gmail.com>
  
   pgcrypto utilise du code provenant des sources
   suivantes :
  
| Algorithme | Auteur | Origine du source | 
|---|---|---|
| DES crypt | David Burren and others | FreeBSD libcrypt | 
| MD5 crypt | Poul-Henning Kamp | FreeBSD libcrypt | 
| Blowfish crypt | Solar Designer | www.openwall.com | 
| Blowfish cipher | Simon Tatham | PuTTY | 
| Rijndael cipher | Brian Gladman | OpenBSD sys/crypto | 
| Hachage MD5 and SHA1 | WIDE Project | KAME kame/sys/crypto | 
| SHA256/384/512 | Aaron D. Gifford | OpenBSD sys/crypto | 
| BIGNUM math | Michael J. Fromberger | dartmouth.edu/~sting/sw/imath |