F.25.1. Funciones generales de hash
F.25.2. Funciones de hash de contraseña
F.25.3. Funciones de cifrado PGP
F.25.4. Funciones de cifrado sin procesar
F.25.5. Funciones de datos aleatorios
F.25.6. Notas
F.25.7. Autor

los pgcrypto El módulo proporciona funciones criptográficas para PostgreSQL.

Este módulo se considera de confianza, es decir, puede ser instalado por no superusuarios que tengan CREATE privilegio sobre la base de datos actual.

F.25.1. Funciones generales de hash

F.25.1.1. digest()

digest(data text, type text) returns bytea
digest(data bytea, type text) returns bytea

Calcula un hash binario de lo dado data. type es el algoritmo a utilizar. Los algoritmos estándar son md5, sha1, sha224, sha256, sha384 y sha512. Si pgcrypto fue construido con OpenSSL, hay más algoritmos disponibles, como se detalla en la Tabla F.19.

Si desea el resumen como una cadena hexadecimal, use encode() en el resultado. Por ejemplo:

CREATE OR REPLACE FUNCTION sha1(bytea) returns text AS $$
    SELECT encode(digest($1, 'sha1'), 'hex')
$$ LANGUAGE SQL STRICT IMMUTABLE;

F.25.1.2. hmac()

hmac(data text, key text, type text) returns bytea
hmac(data bytea, key bytea, type text) returns bytea

Calcula MAC hash para data con llave key. type es lo mismo que en digest().

Esto es similar a digest() pero el hash solo se puede volver a calcular conociendo la clave. Esto evita el escenario de que alguien altere los datos y también cambie el hash para que coincida.

Si la clave es más grande que el tamaño del bloque hash, primero se aplicará un hash y el resultado se utilizará como clave.

F.25.2. Funciones de hash de contraseña

Las funciones crypt() y gen_salt() están diseñados específicamente para hash de contraseñas. crypt() hace el hash y gen_salt() prepara los parámetros del algoritmo para ello.

Los algoritmos en crypt() difieren de los algoritmos hash habituales MD5 o SHA1 en los siguientes aspectos:

  1. Son lentos. Como la cantidad de datos es tan pequeña, esta es la única forma de dificultar las contraseñas de fuerza bruta.

  2. Usan un valor aleatorio, llamado sal, de modo que los usuarios que tengan la misma contraseña tendrán diferentes contraseñas cifradas. Esta es también una defensa adicional contra la inversión del algoritmo.

  3. Incluyen el tipo de algoritmo en el resultado, por lo que pueden coexistir contraseñas con algoritmos diferentes.

  4. Algunos de ellos son adaptables, lo que significa que cuando las computadoras se vuelven más rápidas, puede ajustar el algoritmo para que sea más lento, sin introducir incompatibilidad con las contraseñas existentes.

La Tabla F.16 enumera los algoritmos soportados por el crypt() función.

Cuadro F.16. Algoritmos admitidos para crypt()

Algoritmo Longitud máxima de la contraseña ¿Adaptado? Trozos de sal Longitud de salida Descripción
bf 72 128 60 A base de pez globo, variante 2a
md5 ilimitado no 48 34 Cripta basada en MD5
xdes 8 24 20 DES extendido
des 8 no 12 13 Cripta UNIX original

F.25.2.1. crypt()

crypt(password text, salt text) returns text

Calcula un hash estilo cripta (3) de password. Al almacenar una nueva contraseña, debe usar gen_salt() para generar un nuevo salt valor. Para verificar una contraseña, pase el valor hash almacenado como salty pruebe si el resultado coincide con el valor almacenado.

Ejemplo de configuración de una nueva contraseña:

UPDATE ... SET pswhash = crypt('new password', gen_salt('md5'));

Ejemplo de autenticación:

SELECT (pswhash = crypt('entered password', pswhash)) AS pswmatch FROM ... ;

Esto vuelve true si la contraseña ingresada es correcta.

F.25.2.2. gen_salt()

gen_salt(type text [, iter_count integer ]) returns text

Genera una nueva cadena de sal aleatoria para usar en crypt(). La cadena de sal también dice crypt() qué algoritmo utilizar.

los type parámetro especifica el algoritmo hash. Los tipos aceptados son: des, xdes, md5 y bf.

los iter_count El parámetro permite al usuario especificar el recuento de iteraciones, para los algoritmos que tienen uno. Cuanto mayor sea el recuento, más tiempo se necesita para codificar la contraseña y, por lo tanto, más tiempo para descifrarla. Aunque con un recuento demasiado alto, el tiempo para calcular un hash puede ser de varios años, lo que es algo poco práctico. Si el iter_count se omite el parámetro, se utiliza el recuento de iteraciones predeterminado. Valores permitidos para iter_count dependen del algoritmo y se muestran en la Tabla F.17.

Cuadro F.17. La iteración cuenta para crypt()

Algoritmo Defecto Min Max
xdes 725 1 16777215
bf 6 4 31

Para xdes Existe una limitación adicional de que el recuento de iteraciones debe ser un número impar.

Para elegir un recuento de iteraciones apropiado, considere que la cripta DES original fue diseñada para tener la velocidad de 4 hashes por segundo en el hardware de ese momento. Más lento de 4 hashes por segundo probablemente reduciría la usabilidad. Más rápido que 100 hashes por segundo probablemente sea demasiado rápido.

La tabla F.18 ofrece una descripción general de la lentitud relativa de los diferentes algoritmos de hash. La tabla muestra cuánto tiempo tomaría probar todas las combinaciones de caracteres en una contraseña de 8 caracteres, asumiendo que la contraseña contiene solo letras minúsculas o letras y números en mayúsculas y minúsculas. En el crypt-bf entradas, el número después de una barra es el iter_count parámetro de gen_salt.

Cuadro F.18. Velocidades del algoritmo hash

Algoritmo Hashes / seg Para [a-z] Para [A-Za-z0-9] Duración relativa a md5 hash
crypt-bf/8 1792 4 años 3927 años 100k
crypt-bf/7 3648 2 años 1929 años 50k
crypt-bf/6 7168 1 año 982 años 25k
crypt-bf/5 13504 188 días 521 años 12,5 km
crypt-md5 171584 15 días 41 años 1k
crypt-des 23221568 157.5 minutos 108 días 7
sha1 37774272 90 minutos 68 días 4
md5 (picadillo) 150085504 22,5 minutos 17 días 1

Notas:

  • La máquina utilizada es un Intel Mobile Core i3.

  • crypt-des y crypt-md5 los números de algoritmo se toman de John the Ripper v1.6.38 -test producción.

  • md5 hash los números son de mdcrack 1.2.

  • sha1 los números son de lcrack-20031130-beta.

  • crypt-bf los números se toman usando un programa simple que recorre más de 1000 contraseñas de 8 caracteres. De esa manera puedo mostrar la velocidad con diferentes números de iteraciones. Para referencia: john -test muestra 13506 bucles / seg para crypt-bf/5. (La diferencia muy pequeña en los resultados está de acuerdo con el hecho de que la crypt-bf implementación en pgcrypto es el mismo que se usa en Juan el Destripador).

Tenga en cuenta que prueba todas las combinaciones no es un ejercicio realista. Por lo general, el descifrado de contraseñas se realiza con la ayuda de diccionarios, que contienen tanto palabras regulares como varias mutaciones de ellas. Por lo tanto, incluso las contraseñas que se parecen a una palabra podrían descifrarse mucho más rápido de lo que sugieren los números anteriores, mientras que una contraseña de 6 caracteres que no sea como una palabra puede escapar al descifrado. O no.

F.25.3. Funciones de cifrado PGP

Las funciones aquí implementan la parte de cifrado del estándar OpenPGP (RFC 4880). Se admiten tanto el cifrado de clave simétrica como el de clave pública.

Un mensaje PGP cifrado consta de 2 partes, o paquetes:

  • Paquete que contiene una clave de sesión, ya sea con clave simétrica o con clave pública encriptada.

  • Paquete que contiene datos cifrados con la clave de sesión.

Al cifrar con una clave simétrica (es decir, una contraseña):

  1. La contraseña proporcionada se codifica mediante un algoritmo String2Key (S2K). Esto es bastante similar a crypt() algoritmos, deliberadamente lentos y con sal aleatoria, pero produce una clave binaria de longitud completa.

  2. Si se solicita una clave de sesión separada, se generará una nueva clave aleatoria. De lo contrario, la clave S2K se utilizará directamente como clave de sesión.

  3. Si la clave S2K se va a utilizar directamente, solo se colocarán las configuraciones S2K en el paquete de claves de sesión. De lo contrario, la clave de sesión se cifrará con la clave S2K y se incluirá en el paquete de claves de sesión.

Al cifrar con una clave pública:

  1. Se genera una nueva clave de sesión aleatoria.

  2. Se cifra con la clave pública y se coloca en el paquete de claves de sesión.

En cualquier caso, los datos a cifrar se procesan de la siguiente manera:

  1. Manipulación de datos opcional: compresión, conversión a UTF-8 y / o conversión de finales de línea.

  2. Los datos tienen como prefijo un bloque de bytes aleatorios. Esto es equivalente a usar un IV aleatorio.

  3. Se agrega un hash SHA1 del prefijo aleatorio y los datos.

  4. Todo esto se cifra con la clave de sesión y se coloca en el paquete de datos.

F.25.3.1. 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

Cifrar data con una clave PGP simétrica psw. los options El parámetro puede contener configuraciones de opciones, como se describe a continuación.

F.25.3.2. 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

Descifre un mensaje PGP cifrado con clave simétrica.

Descifrando bytea datos con pgp_sym_decrypt no está permitido. Esto es para evitar la salida de datos de caracteres no válidos. Descifrar datos originalmente textuales con pgp_sym_decrypt_bytea está bien.

los options El parámetro puede contener configuraciones de opciones, como se describe a continuación.

F.25.3.3. 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

Cifrar data con una clave PGP pública key. Dar a esta función una clave secreta producirá un error.

los options El parámetro puede contener configuraciones de opciones, como se describe a continuación.

F.25.3.4. 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

Descifre un mensaje cifrado con clave pública. key debe ser la clave secreta correspondiente a la clave pública que se utilizó para cifrar. Si la clave secreta está protegida con contraseña, debe ingresar la contraseña en psw. Si no hay contraseña, pero desea especificar opciones, debe proporcionar una contraseña vacía.

Descifrando bytea datos con pgp_pub_decrypt no está permitido. Esto es para evitar la salida de datos de caracteres no válidos. Descifrar datos originalmente textuales con pgp_pub_decrypt_bytea está bien.

los options El parámetro puede contener configuraciones de opciones, como se describe a continuación.

F.25.3.5. pgp_key_id()

pgp_key_id(bytea) returns text

pgp_key_id extrae el ID de clave de una clave pública o secreta de PGP. O proporciona el ID de clave que se utilizó para cifrar los datos, si se le proporciona un mensaje cifrado.

Puede devolver 2 ID de clave especiales:

  • SYMKEY

    El mensaje está encriptado con una clave simétrica.

  • ANYKEY

    El mensaje está cifrado con clave pública, pero el ID de clave se ha eliminado. Eso significa que deberá probar todas sus claves secretas para ver cuál lo descifra. pgcrypto en sí mismo no produce tales mensajes.

Tenga en cuenta que diferentes claves pueden tener el mismo ID. Este es un evento raro pero normal. La aplicación cliente debería intentar descifrar con cada uno, para ver cuál encaja, como el manejo ANYKEY.

F.25.3.6. armor(), dearmor()

armor(data bytea [ , keys text[], values text[] ]) returns text
dearmor(data text) returns bytea

Estas funciones envuelven / desenvuelven datos binarios en formato PGP ASCII-armor, que es básicamente Base64 con CRC y formato adicional.

Si el keys y values se especifican matrices, una encabezado de armadura se agrega al formato blindado para cada par clave / valor. Ambas matrices deben ser unidimensionales y deben ser de la misma longitud. Las claves y los valores no pueden contener caracteres que no sean ASCII.

F.25.3.7. pgp_armor_headers

pgp_armor_headers(data text, key out text, value out text) returns setof record

pgp_armor_headers() extrae los encabezados de armadura de data. El valor de retorno es un conjunto de filas con dos columnas, clave y valor. Si las claves o valores contienen caracteres que no son ASCII, se tratan como UTF-8.

F.25.3.8. Opciones para funciones PGP

Las opciones se nombran para que sean similares a GnuPG. El valor de una opción debe darse después de un signo igual; separe las opciones entre sí con comas. Por ejemplo:

pgp_sym_encrypt(data, psw, 'compress-algo=1, cipher-algo=aes256')

Todas las opciones excepto convert-crlf se aplica solo a las funciones de cifrado. Las funciones de descifrado obtienen los parámetros de los datos PGP.

Las opciones más interesantes son probablemente compress-algo y unicode-mode. El resto debe tener valores predeterminados razonables.

F.25.3.8.1. cifrado-algo

Qué algoritmo de cifrado utilizar.

Valores: bf, aes128, aes192, aes256 (solo OpenSSL: 3des, cast5) Predeterminado: aes128 Se aplica a: pgp_sym_encrypt, pgp_pub_encrypt

F.25.3.8.2. comprimir-algo

Qué algoritmo de compresión utilizar. Solo está disponible si PostgreSQL se creó con zlib.

Valores: 0 – sin compresión 1 – Compresión ZIP 2 – Compresión ZLIB (= ZIP más metadatos y CRC de bloque) Predeterminado: 0 Se aplica a: pgp_sym_encrypt, pgp_pub_encrypt

F.25.3.8.3. nivel de compresión

Cuánto comprimir. Los niveles más altos se comprimen más pequeños pero son más lentos. 0 desactiva la compresión.

Valores: 0, 1-9 Predeterminado: 6 Se aplica a: pgp_sym_encrypt, pgp_pub_encrypt

F.25.3.8.4. convertir-crlf

Ya sea para convertir n dentro rn al cifrar y rn para n al descifrar. RFC 4880 especifica que los datos de texto deben almacenarse utilizando rn saltos de línea. Use esto para obtener un comportamiento totalmente compatible con RFC.

Valores: 0, 1 Predeterminado: 0 Se aplica a: pgp_sym_encrypt, pgp_pub_encrypt, pgp_sym_decrypt, pgp_pub_decrypt

F.25.3.8.5. desactivar-mdc

No proteja los datos con SHA-1. La única buena razón para usar esta opción es lograr compatibilidad con productos PGP antiguos, anteriores a la adición de paquetes protegidos SHA-1 a RFC 4880. El software reciente de gnupg.org y pgp.com lo soporta bien.

Valores: 0, 1 Predeterminado: 0 Se aplica a: pgp_sym_encrypt, pgp_pub_encrypt

F.25.3.8.6. sess-key

Utilice una clave de sesión independiente. El cifrado de clave pública siempre usa una clave de sesión separada; esta opción es para el cifrado de clave simétrica, que de forma predeterminada utiliza la clave S2K directamente.

Valores: 0, 1 Predeterminado: 0 Se aplica a: pgp_sym_encrypt

F.25.3.8.7. modo s2k

Qué algoritmo S2K usar.

Valores: 0 – Sin sal. ¡Peligroso! 1 – Con sal pero con recuento de iteraciones fijo. 3 – Recuento de iteraciones variable. Predeterminado: 3 Se aplica a: pgp_sym_encrypt

F.25.3.8.8. s2k-count

El número de iteraciones del algoritmo S2K que se utilizará. Debe tener un valor entre 1024 y 65011712, inclusive.

Predeterminado: un valor aleatorio entre 65536 y 253952 Se aplica a: pgp_sym_encrypt, solo con s2k-mode = 3

F.25.3.8.9. s2k-digest-algo

Qué algoritmo de resumen usar en el cálculo de S2K.

Valores: md5, sha1 Predeterminado: sha1 Se aplica a: pgp_sym_encrypt

F.25.3.8.10. s2k-cifrado-algo

Qué cifrado utilizar para cifrar una clave de sesión independiente.

Valores: bf, aes, aes128, aes192, aes256 Predeterminado: use cipher-algo Se aplica a: pgp_sym_encrypt

F.25.3.8.11. modo unicode

Ya sea para convertir datos textuales de la codificación interna de la base de datos a UTF-8 y viceversa. Si su base de datos ya es UTF-8, no se realizará ninguna conversión, pero el mensaje se etiquetará como UTF-8. Sin esta opción no será así.

Valores: 0, 1 Predeterminado: 0 Se aplica a: pgp_sym_encrypt, pgp_pub_encrypt

F.25.3.9. Generando claves PGP con GnuPG

Para generar una nueva clave:

gpg --gen-key

El tipo de clave preferido es DSA y Elgamal.

Para el cifrado RSA, debe crear una clave de solo signo DSA o RSA como maestra y luego agregar una subclave de cifrado RSA con gpg --edit-key.

Para enumerar claves:

gpg --list-secret-keys

Para exportar una clave pública en formato ASCII-armor:

gpg -a --export KEYID > public.key

Para exportar una clave secreta en formato ASCII-armor:

gpg -a --export-secret-keys KEYID > secret.key

Necesitas usar dearmor() en estas teclas antes de asignarlas a las funciones PGP. O si puede manejar datos binarios, puede soltar -a desde el comando.

Para obtener más detalles, consulte man gpg, El manual de privacidad de GNU y otra documentación sobre https://www.gnupg.org/.

F.25.3.10. Limitaciones del código PGP

  • No hay soporte para firmar. Eso también significa que no se comprueba si la subclave de cifrado pertenece a la clave maestra.

  • No se admite la clave de cifrado como clave maestra. Como tal práctica generalmente se desaconseja, esto no debería ser un problema.

  • No hay soporte para varias subclaves. Esto puede parecer un problema, ya que es una práctica común. Por otro lado, no debe utilizar sus claves GPG / PGP habituales con pgcrypto, pero cree otros nuevos, ya que el escenario de uso es bastante diferente.

F.25.4. Funciones de cifrado sin procesar

Estas funciones solo ejecutan un cifrado sobre datos; no tienen funciones avanzadas de cifrado PGP. Por tanto, tienen algunos problemas importantes:

  1. Usan la clave de usuario directamente como clave de cifrado.

  2. No proporcionan ninguna verificación de integridad para ver si se modificaron los datos cifrados.

  3. Esperan que los usuarios gestionen todos los parámetros de cifrado por sí mismos, incluso IV.

  4. No manejan el texto.

Por lo tanto, con la introducción del cifrado PGP, se desaconseja el uso de funciones de cifrado sin procesar.

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

Cifre / descifre datos utilizando el método de cifrado especificado por type. La sintaxis del type cadena es:

algorithm [ - mode ] [ /pad: padding ]

dónde algorithm es uno de:

  • bf – Pez globo

  • aes – AES (Rijndael-128, -192 o -256)

y mode es uno de:

  • cbc – el siguiente bloque depende del anterior (predeterminado)

  • ecb – cada bloque se cifra por separado (solo para pruebas)

y padding es uno de:

  • pkcs – los datos pueden tener cualquier longitud (predeterminado)

  • none – los datos deben ser múltiplos del tamaño del bloque de cifrado

Entonces, por ejemplo, estos son equivalentes:

encrypt(data, 'fooz', 'bf')
encrypt(data, 'fooz', 'bf-cbc/pad:pkcs')

En encrypt_iv y decrypt_iv, los iv parámetro es el valor inicial para el modo CBC; se ignora para el BCE. Se recorta o se rellena con ceros si no es exactamente el tamaño del bloque. Por defecto, todos los ceros en las funciones sin este parámetro.

F.25.5. Funciones de datos aleatorios

gen_random_bytes(count integer) returns bytea

Devoluciones count Bytes aleatorios criptográficamente fuertes. Se pueden extraer como máximo 1024 bytes a la vez. Esto es para evitar agotar el grupo de generadores de aleatoriedad.

gen_random_uuid() returns uuid

Devuelve un UUID de la versión 4 (aleatorio). (Obsoleto, esta función ahora también se incluye en el núcleo de PostgreSQL).

F.25.6. Notas

F.25.6.1. Configuración

pgcrypto se configura de acuerdo con los hallazgos del PostgreSQL principal configure texto. Las opciones que lo afectan son --with-zlib y --with-openssl.

Cuando se compila con zlib, las funciones de cifrado PGP pueden comprimir datos antes de cifrar.

Cuando se compila con OpenSSL, habrá más algoritmos disponibles. Además, las funciones de cifrado de clave pública serán más rápidas ya que OpenSSL tiene funciones BIGNUM más optimizadas.

Cuadro F.19. Resumen de funcionalidad con y sin OpenSSL

Funcionalidad Incorporado Con OpenSSL
MD5
SHA1
SHA224 / 256/384/512
Otros algoritmos de resumen no sí (nota 1)
Pez globo
AES
DES / 3DES / CAST5 no
Cifrado sin procesar
Cifrado simétrico PGP
Cifrado de clave pública PGP

Notas:

  1. Cualquier algoritmo de resumen compatible con OpenSSL se selecciona automáticamente. Esto no es posible con cifrados, que deben ser compatibles explícitamente.

F.25.6.2. Manejo NULO

Como es estándar en SQL, todas las funciones devuelven NULL, si alguno de los argumentos es NULL. Esto puede crear riesgos de seguridad en caso de uso descuidado.

F.25.6.3. Limitaciones de seguridad

Todos pgcrypto las funciones se ejecutan dentro del servidor de la base de datos. Eso significa que todos los datos y contraseñas se mueven entre pgcrypto y aplicaciones de cliente en texto claro. Por lo tanto, debe:

  1. Conéctese localmente o use conexiones SSL.

  2. Confíe en el administrador del sistema y de la base de datos.

Si no puede, es mejor que haga criptomonedas dentro de la aplicación del cliente.

La implementación no resiste ataques de canal lateral. Por ejemplo, el tiempo necesario para una pgcrypto función de descifrado para completar varía entre los textos cifrados de un tamaño determinado.

F.25.6.4. Lectura útil

F.25.6.5. Referencias técnicas

F.25.7. Autor

Marko Kreen

pgcrypto usa código de las siguientes fuentes:

Algoritmo Autor Origen de la fuente
DES cripta David Burren y otros Libcrypt de FreeBSD
Cripta MD5 Poul-Henning Kamp Libcrypt de FreeBSD
Cripta de pez globo Diseñador Solar www.openwall.com
Cifrado de pez globo Simon Tatham Masilla
Cifrado de Rijndael Brian Gladman Sys / cripto de OpenBSD
Hash MD5 y SHA1 Proyecto WIDE KAME kame / sys / crypto
SHA256 / 384/512 Aaron D. Gifford Sys / cripto de OpenBSD
Matemáticas BIGNUM Michael J. Fromberger dartmouth.edu/~sting/sw/imath

Anterior

Hasta próximo
F.24. pg_buffercache Hogar F.26. pg_freespacemap