2. Índice de contenidos
Introducción.
Criptografía con Java.
Infraestructura con PKI con Java.
Control de acceso.
Aplicaciones con Java SSL.
Seguridad en aplicaciones WEB.
4. Introducción
El soporte que da el JDK a la criptografía se
divide en dos grandes bloques:
JCA (Java Cryptography Architecture): define las
bases del soporte criptográfico de Java.
JCE (Java Cryptography Extension): proporciona los
algoritmos necesarios para poder encriptar y
desencriptar datos.
Para un programador, el conocimiento de
protocolos y algoritmos en encriptación no es
necesario, dado que toda esa problemática ha
sido encapsulada dentro de unos paquetes java.
Ambas parte de J2SE SDK v1.4
5. Introducción
Debido a las leyes de los Estados Unidos, que
prohiben exportar software de encriptación de
datos, el JCE no venían incluido inicialmente en
las versiones del JDK, y existían restricciones
para bajarlo de la site de SUN.
Existen paquetes de terceros, desarrollados
fuera de los Estados Unidos, que implementan
todas las especificaciones del JCE y que no
están sujetos a sus restricciones legales, como
por ejemplo la librería CRYPTICS.
6. Arquitectura criptográfica de Java (JCA)
Marco o framework para acceder y desarrollar
la funcionalidad criptográfica de Java.
Incluye todas las APIs relativas a la criptografía
(el paquete java.security y sus subpaquetes),
así como una serie de especificaciones a tener
en cuenta por los programadores que quieran
crear extensiones criptográficas (como la
librería CRYPTICS, etc).
7. Arquitectura criptográfica de Java (JCA)
La arquitectura criptográfica de Java ha sido
diseñada teniendo en cuenta dos principios:
independencia de la implementación e interoperabilidad.
independencia de algoritmos.
La independencia de la implementación se consigue
introduciendo el concepto de "Proveedor" (Cryptography
Package Provider).
Estos dos conceptos son complementarios. Se
pueden utilizar servicios criptográficos tales
como Firma Digital sin preocuparse por los
detalles de implementación o los algoritmos que
los implementan.
8. Arquitectura criptográfica de Java (JCA)
Cuando el concepto de independencia de
implementación no es deseable JCA permite al
programador usar una implementación
específica.
La independencia de algoritmos se alcanza
definiendo tipos de servicios criptográficos, y
proporcionando clases específicas para cada
uno.
9. Arquitectura criptográfica de Java (JCA)
La independencia de implementación se alcanza
usando una arquitectura basada en Proveedor.
Cryptographic Service Provider: conjunto de
paquetes que implementan uno o más servicios
criptográficos.
Un programa sólo debe solicitar un determinado
objeto que proporciona un específico servicio,
obteniendo una implementación a partir de uno
de los proveedores instalados.
11. Arquitectura criptográfica de Java (JCA)
Paquetes más importantes:
java.security : proporciona las clases e interfaces del
framework de seguridad.
java.security.cert : clases e interfaces para el manejo
de listas de revocación, etc.
13. Servicios criptográficos
Una instancia de un servicio está asociada a
varios algoritmos o tipos:
Ejemplo: Signature, CertificateFactory
Estos servicios carecen de constructores:
Independencia del algoritmo.
Método getInstance().
14. Servicios criptográficos
SERVICIO ALGORITMO/TIPO DESCRIPCIÓN
SecureRandom SHA1PRNG Genera números pseudo-
aleatorios
KeyGenerator DES,Triple-DES, Blowfish Genera claves
KeyParGenerator DSA, RSA,DH Genera pares de claves
publica-privada
MessageDigest SHA1, MD5 Computa el diggest de un
mensaje
Mac Computa el código de
autenticación de un mensaje
Signature SHA1WithDSA, Crea y verifica firmas
SHA1WithRSA digitales de un mensaje
KeyStore JKS, JCEKS, PKCS12 Almacena claves y
certificados
CertificateFactory X509 Crea Certificados
Cipher DES, Triple-DES, Blowfish Encripta y desencripta
KeyAgreement DH Permite a dos partes
coincidir de forma segura en
una clave secreta
15. Proveedores
El término Proveedor de Servicio Criptográfico o
Proveedor se refiere a un conjunto de paquetes
que proporcionan una implementación concreta
de un conjunto de servicios criptográficos.
Es posible tener instalados varios proveedores
en un entorno de desarrollo.
Por ejemplo
Signature.getInstance(“SHA1WithDSA”).
Signature.getInstance(“SHA1WithDSA”, “SUN”).
16. Proveedores
Instalación de un nuevo proveedor.
Obtención de las bibliotecas de dicho proveedor (jar).
Instalación en jre-homelibext.
La configuración se puede hacer editando el archivo
java.security en el jre-homelibsecurity con entradas
del tipo security.provider.i=<proveedor>.
17. Proveedores
La clase Provider:
Es la interface que utilizaremos para acceder a ese
paquete o conjunto de paquetes.
Tiene métodos para acceder al nombre del proveedor,
número de versión y otra información.
Métodos:
protected Provider(String name,double version,String
info)
public String getName()
public double getVersion()
public String getInfo()
public String toString()
public void clear()
18. Proveedores
Más métodos:
public void load(InputStream inStream)throws
IOException
public void putAll(Map t)
public Set entrySet()
public Set keySet()
public Collection values()
public Object put(Object key,Object value)
Object.equals(Object), Hashtable.get(Object)
public Object remove(Object key)
19. Clases engine
Clases que definen un servicio criptográfico de
forma abstracta.
Un servicio criptográfico está asociado a un
algoritmo específico, proporciona operaciones,
genera material criptográfico necesario en las
operaciones, genera objetos que encapsulan
claves.
Por ejemplo: la clase Signature proporciona
acceso a la funcionalidad de un algoritmo de
firma digital.
20. Claves criptográficas
El manejo de claves es vital para el uso de determinados
servicios de encriptación.
Se necesitan claves para generar servicios de firma
digital y encriptación.
La interfaz java.security.Key representa un algoritmo y
tipo de clave con los siguientes métodos:
public String getAlgorithm(): devuelve el algoritmo de la
clave.
public byte[]getEncoded(): devuelve la clave como un array
de bytes.
Una clave se puede generar a partir de su flujo binario o
bien por generación expresa dentro de un programa a partir
de algún algoritmo de generación.
21. Claves criptográficas
Dos tipos de claves:
simétricas (secret key).
asimétricas (public y private).
Las posibilidades de los algoritmos de clave pública
nos permiten varias opciones que no permite los
algoritmos de clave privada :
Servicios de autentificación.
Firma digital.
Publicar una clave de cifrado, que puede ser distribuida
sin riesgos.
22. Claves criptográficas
Pero los algoritmos de clave privada también
tienen sus ventajas:
Los algoritmos simétricos son mas rápidos que los de
clave publica, por lo que en mensajes largos es mejor
usar uno de clave privada.
Hay dos clases Engine que actúan sobre claves:
Generador de claves.
Factoría de claves.
El concepto de clave es modelado por la
interface Key, que se encuentra en el paquete
java.security.
public interface Key extends Serializable
Análisis de la interface.
23. Claves criptográficas
Claves asimétricas:
Son claves muy populares.
Siempre vienen en parejas.
Java proporciona dos interfaces más:
public interface PublicKey extends Key.
public interface PrivateKey extends Key.
No proporcionan ningún método adicional, una clase que
implementa PublicKey se identifica a si misma como una
clave pública, pero no contiene ningún método diferente.
Los proveedores que vienen con Java proporcionan
dos tipos de claves asimétricas: DSA y RSA.
JCE proporciona otro: Diffie-Hellman.
24. Claves criptográficas
Claves asimétricas:
DSA:
public interface DSAPrivateKey extends DSAKey.
public interface DSAPublicKey extends DSAKey.
RSA:
public interface RSAPublicKey extends RSAKey, PublicKey.
public interface RSAPrivateKey extends RSAKey,
PrivateKey.
Clase que hereda el concepto general de clave
asimétrica:
public final class KeyPair.
26. Claves criptográficas
Claves simétricas:
Sólo son usadas dentro de JCE.
Paquete javax.crypto .
public interface SecretKey extends Key
Si una clase implementa esta interface es una clave
simétrica.
Esta interface está vacía, sólo se utiliza como
identificador de un tipo.
JCE proporciona distintos tipos de claves
simétricas:
Blowfish, DES, DESede, HmacMD5, HmacSHA1 ...
27. Claves criptográficas
Claves simétricas:
Sólo son usadas dentro de JCE.
Paquete javax.crypto .
public interface SecretKey extends Key
Si una clase implementa esta interface es una clave
simétrica.
Esta interface está vacía, sólo se utiliza como
identificador de un tipo.
JCE proporciona distintos tipos de claves
simétricas:
Blowfish, DES, DESede, HmacMD5, HmacSHA1 ...
28. Claves criptográficas
La interfaz java.security.Key representa un algoritmo y
tipo de clave con los siguientes métodos:
public String getAlgorithm():
Devuelve el algoritmo de la clave. Todo objeto Key está
asociado con un algoritmo único.
public byte[]getEncoded():
Devuelve la clave como un array de bytes en el formato
de codificación principal de la clave (RAW o PKCS#8).
getFormat():
Devuelve el formato en el que está codificada la clave.
Una clave se puede generar a partir de su flujo binario o
bien por generación expresa dentro de un programa a
partir de algún algoritmo de generación.
29. Claves criptográficas
Claves simétricas:
La interface Key se ve ampliada por una serie de
interface especializadas, nos centramos en este caso
en:
SecretKey.
Se trabaja a continuación con algoritmos simétricos o
de clave secreta.
30. Claves criptográficas
Interface SecretKey:
Se encuentra en el paquete javax.crypto.
Hereda de la interface Key y no añade métodos
nuevos.
Las implementaciones de proveedores deben
implementar dicha interface.
31. Claves criptográficas
Generación de claves:
Se proporcionan dos clases engine para generar claves
simétricas y asimétricas.
clase KeyPairGenerator.
clase KeyGenerator.
32. Generación de claves simétricas
Clase KeyGenerator:
Utilizada para generar clave secretas.
Paquete javax.crypto.
Se instancia a través de una factoría, a través del
método getInstance():
Parámetro 1: String algorithm.
Este parámetro es el nombre del algoritmo para el que se
genera dicha clave.
Los nombres que se pueden utilizar vienen definidos en el
estándar de Sun y son:
AES y Blowfish.
DES y DESede.
DiffieHellman.
OAEP.
PBE.
PBEWith<digest>And<encryption>.
RC2.
33. Generación de claves simétricas
Clase KeyGenerator:
Valores de clave por defecto:
DES: 56 bits.
Triple DES: 112 bits.
Blowfish: 56 bits.
HmacMD5: 64 bytes: Claves para algoritmos de firma
digital con clave secreta (MAC).
HmacSHA1: 64 bytes. Claves para algoritmos de firma
digital con clave secreta (MAC).
34. Generación de claves simétricas
Clase KeyGenerator:
Restricciones:
DES: su tamaño de clave es obligatoriamente 56.
Triple DES: 112 o 168.
Nota: Un tamaño de clave de 112 generará una clave Triple
DES con dos claves intermedias, un tamaño de clave de 168
generará una clave Triple DES con tres claves intermedias.
Blowfish: el tamaño de clave debe ser múltiplo de 8, y
sólo puede estar en el rango 32-448 ambos inclusive.
35. Generación de claves simétricas
Clase KeyGenerator:
Método getInstance().
public static KeyGenerator getInstance(String algorithm):
Se generan claves para un algoritmo simétrico especificado
mediante la cadena pasada como parámetro.
Nombre de los algoritmos:
DES, Triple DES, Blowfish, HmacMD5, HmacSHA1.
public static KeyGenerator getInstance(String algorithm,
String provider).
Se generan claves para un algoritmo simétrico especificado
mediante el nombre del algoritmo y el proveedor.
Nombre de los algoritmos:
DES, Triple DES, Blowfish, HmacMD5, HmacSHA1.
Nombre de los proveedores:
SUN 1.5, Apple 1.0, ...
36. Generación de claves simétricas
Clase KeyGenerator:
Método getInstance().
// OPCIÓN 1:
// Creación de un generador de claves mediante el nombre del algoritmo.
KeyGenerator kg=KeyGenerator.getInstance("DES");
// OPCIÓN 2:
// Creación de un generador de claves mediante el nombre del algoritmo y
// proveedor específico
KeyGenerator kg=KeyGenerator.getInstance("DES",“SUN 1.5”);
37. Generación de claves simétricas
Clase KeyGenerator:
Los objetos KeyGenerator se inicializan con su método
init. Este método está sobrecargado:
public final void init(int keysize):
Inicializa el objeto en una clave de un tamaño especificado
por el parámetro utilizando el generador aleatorio por
defecto.
public final void init(int keysize,SecureRandom random)
Inicializa el objeto en una clave de un tamaño especificado
por el parámetro utilizando el generador aleatorio
suministrado por el usuario.
38. Generación de claves simétricas
Clase KeyGenerator:
public final void init(SecureRandom random):
Inicializa el objeto en una clave utilizando el generador
aleatorio suministrado por el usuario. Se utiliza un tamaño de
clave apropiado para el algoritmo.
public final void init(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException:
Inicializa el objeto utilizando parámetros específicos de la
implementación.
public final void init(AlgorithmParameterSpec params,
SecureRandom random)throws
InvalidAlgorithmParameterException:
Inicializa el objeto utilizando parámetros específicos de la
implementación y objeto SecureRandom suministrado por el
usuario.
39. Generación de claves simétricas
Clase KeyGenerator:
public final SecretKey generateKey():
40. Generación de claves simétricas
Nota aclaratoria. SecureRandom:
Los números aleatorios son importantes en
criptografía.
Se suelen usar para generar los resultados de las
operaciones, como la generación de claves.
Los ordenadores no suelen generar números
verdaderamente aleatorios, en vez de ello, se utilizan
los algoritmos de generación de números
pseudoaleatorios (PRNG).
Algunos son más aleatorios que otros. Se consigue un
nivel más alto de aleatoriedad sembrando el PRNG con
un valor seleccionado aleatoriamente (semilla).
41. Generación de claves simétricas
Nota aclaratoria. SecureRandom:
La clase SecureRandom se utiliza para acceder a los
algoritmos seguros PRN de los distintos proveedores.
Constructores:
public SecureRandom(): crea un objeto que se inicializa
con un valor de semilla que es generada internamente.
Esta semilla puede no ser segura.
public SecureRandom(byte[] seed): crea un objeto que
se inicializa con un valor de semilla suministrada como
parámetro.
Si desea tener un alto nivel de seguridad, deberá
generar la semilla de forma manual.
42. Generación de claves simétricas
Nota aclaratoria. SecureRandom:
Una vez creado y sembrado el objeto, está listo para
ser usado para generar valores aleatorios utilizando:
protected final int next(int numBits).
public void nextBytes(byte[] bytes).
44. Claves criptográficas
Clase KeyPairGenerator:
Paquete java.security.
Se instancia a través de una factoría, a través del
método getInstance().
public static KeyPairGenerator getInstance(String
algorithm).
public static KeyPairGenerator getInstance(String
algorithm, String provider).
Los algoritmos para los que generar claves esta
disponible son:
DSA, RSA, Diffie-Hellman.
Método initialize().
46. Introducción
Es el proceso de convertir texto plano a algo
incomprensible o cifrado aplicando
transformaciones matemáticas.
Estas transformaciones se conocen como
algoritmos de encriptación y requieren una
clave de encriptación.
Desencriptación es el proceso inverso, y
requiere también una clave.
Cuando ambas claves son la misma se habla de
criptografía secreta o simétrica.
Cuando son distintas se habla de criptografía de
clave pública o asimétrica.
47. Confidencialidad con clave privada
Introducción.
Clase Cipher:
Creación.
Inicialización.
Encriptado y desencriptado.
Esquema básico de cifrado con clave privada.
48. Introducción
JDK 1.4 soporta los siguientes algoritmos:
DES (Data Encryption Standard) desarrollado por IBM en los
70. Es un cifrado de bloque de 56-bit.
TripleDES. Consiste en aplicar el algoritmo DES tres veces
(encriptar desencriptar encriptar) con dos claves dando un
resultado de 112 bits.
AES. Es el algoritmo que reemplazó a DES. Creado por Joan
Daemen y Vincent.
Rijmen. Es un cifrado por bloque de 128-bit con claves de
longitud 128, 192 o 256 bits.
RC2, RC4 y RC5.
Blowfish. Fue creado por Bruce Schneier y hace un cifrado
por bloques con claves de longitud variable desde 32 a 448
bits (en múltiplos de 8), Diseñado para ser eficiente en
computadores.
PBE. PBE (Password Based Encryption) puede ser usado con
algoritmos de clave privada y funciones de resumen.
49. Clase Cipher
Se usa para cifrar mediante algoritmos de
clave simétrica.
Forma parte del JCE (Java Cryptography
Extension).
Vamos a analizar los distintos pasos a seguir
para poder trabajar con objetos de dicha clase:
Creación de objetos de la clase Cipher.
Inicialización de objetos de la clase Cipher.
50. Creación de objetos de la clase Cipher
Como ya vimos es muy normal instanciar clases
a través de una factoría:
public static Cipher getInstance(String
transformation);
public static Cipher getInstance(String transformation,
String provider);
Nota: transformación.
algoritmo / modo / relleno
algoritmo
51. Creación de objetos de la clase Cipher
Ejemplo:
Cipher c1 = Cipher.getInstance("DES/ECB/
PKCS5Padding");
Cipher c1 = Cipher.getInstance("DES");
Los modos son la forma de trabajar del
algoritmo:
Ninguno.
ECB (Electronic Code Book).
CBC (Cipher Block Chaining).
CFB (Cipher Feedback Mode).
OFB (Output Feedback Mode).
PCBC (Propagating Cipher Block Chaining).
52. Creación de objetos de la clase Cipher
Relleno:
Un algoritmo puede cifrar por bloques de una longitud
determinada, cuando el mensaje es un múltiplo de
dicha longitud no existe ningún problema. Pero
cuando el mensaje no es un múltiplo, el último bloque
es menor que la longitud necesaria para realizar el
cifrado, entonces se realiza un relleno de ese bloque.
A este relleno se le llama padding.
Existen varias formas de rellenar los bloques de
menor tamaño:
No rellenar
PKCS5
OAEP
SSL3
53. Inicialización del objeto Cipher
Un objeto Cipher obtenido mediante el método
getInstance() debe ser inicializado a uno de los
cuatro modos disponibles. Dichos modos son
identificados mediante constantes enteras:
ENCRYPT_MODE: encriptación de datos.
DECRYPT_MODE: desencriptación de datos.
WRAP_MODE: envuelve una clave de modo que dicha
clave puede ser transportada con seguridad.
UNWRAP_MODE: desenvolver una clave que ha sido
previamente envuelta, en un objeto Key.
54. Inicialización del objeto Cipher
Para inicializar el objeto se debe utilizar el método:
public void init(int opmode, Key key);
public void init(int opmode, Certificate certificate)
public void init(int opmode, Key key, SecureRandom
random);
public void init(int opmode, Certificate certificate,
SecureRandom random)
public void init(int opmode, Key
key,AlgorithmParameterSpec params);
public void init(int opmode, Key key,
AlgorithmParameterSpec params,
SecureRandom random);
public void init(int opmode, Key key,
AlgorithmParameters params)
public void init(int opmode, Key key, AlgorithmParameters
params,SecureRandom random)
55. Encriptado y desencriptado
Un paso:
Llamada al método doFinal.
Cabecera:
public byte[] doFinal(byte[] input);
y otras variantes del mismo método.
Varios pasos:
Llamada al método update.
Cabecera:
public byte[] update(byte[] input);
Operación en varios pasos debe ser terminada con una
llamada al método doFinal.
56. Transferencia de clave
Llamada al método wrap:
Cabecera: public final byte[] wrap(Key key);
Para que pueda recuperarse la clave se debe
proporcionar más información:
Algoritmo de la clave.
Tipo de clave: Cipher.SECRET_KEY, Cipher.PRIVATE_KEY,
Cipher.PUBLIC_KEY.
Para recuperar la clave se debe utilizar el
método unwrap:
Cabecera:public final Key unwrap(byte[] wrappedKey,
String wrappedKeyAlgorithm, int wrappedKeyType));
57. Esquema básico de cifrado con clave privada
Creación de la clave.
Creación del objeto Cipher.
Cifrado.
Configuración del objeto Cipher.
Descifrado.
59. Introducción
La claves privadas tienen un problema:
Supongamos que rx quiere comunicarse con tx, por lo
que rx necesita conocer esa clave.
Debe ser enviada, de ese modo pone en peligro el
cifrado, de ahí que la clave es información sensible.
Si alguien intercepta la clave, el cifrado será
inútil.
La encriptación asimétrica elimina el problema
de compartir información sensible:
La clave de cifrado se puede compartir sin problemas,
y la clave de descifrar sólo la tiene que poseer el
receptor.
60. Esquema básico de cifrado con clave pública
Creamos la clave.
Creamos un objeto Cipher y lo configuramos
con los parámetros deseados.
Realizamos el cifrado.
Configuramos otra vez el objeto Cipher.
Desciframos.
61. Trabajando con flujos
Clase CipherInputStream:
Análisis de su constructor.
Métodos de lectura.
Clase CipherOutputStream:
Análisis de su constructor.
Métodos de escritura.