
Repasaremos con ejemplos ilustrativos las cuestiones más importantes referentes a Java security. La seguridad es un tema muy amplio, que comprende muchas áreas.
Algunas de estas áreas están directamente cubiertas por el propio API de Java como modificadores de acceso y cargadores de clases. También deben tenerse en cuenta temas como la encriptación de datos, securización de las comunicaciones y gestión de autorizaciones entre otros.
Características propias del lenguaje
Para poder empezar a entender el alcance de Java security debemos empezar por lo que el propio lenguaje nos ofrece. Java nos permite escribir código seguro a partir de las siguientes características:
- Tipado estático de datos: Reduce la posibilidad de errores de tipado en tiempo de ejecución.
- Modificadores de acceso: De cara a controlar el acceso a métodos, atributos y clases Java proporciona modificadores como público y privado.
- Gestión automática de memoria: Java cuenta con un recolector de basura para la liberación automática de memoria que permite que el programador se olvide de esta tarea.
- Verificación del bytecode: Java es un lenguaje compilado, se convierte el código en un bytecode agnóstico de la plataforma, en tiempo de ejecución se verifica el bytecode antes su carga.
Arquitectura de la seguridad en Java
El núcleo de la seguridad en Java se basa en la implementación de la interfaz Provider. Una implementación específica de Provider puede incorporar uno o todos los servicios de seguridad.
Algunos de los servicios que puede implementar son algoritmos criptográficos (DSA, RSA, SHA-256, ec), generación de claves, etc. Una aplicación puede configurar múltiples providers con un orden de preferencia.
Criptografía
La criptografía provee las herramientas y técnicas necesarias para securizar la comunicación ante la presencia de atacantes.
La arquitectura criptográfica de Java (JCA) pone a disposición del desarrollador un API que le permite implementar funcionalidades criptográficas. Entre las posibilidades que da el framework están las siguientes:
- Firma digital
- Cifrados simétricos y asimétricos
- Códigos de autenticación
- Generador de claves
Java ya incluye internamente en su framework algunos algoritmos criptográficos básicos como RSA, DSA y AES.
Uno de los problemas clásicos es el almacenamiento de contraseñas. Una de las soluciones que podemos incorporar directamente es a través de un método de encriptación de una sola dirección como SHA1. Podemos hacerlo desde Java de la siguiente forma:
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
byte[] passwordHasheada = messageDigest.digest("password_de_prueba".getBytes());
Infraestructura de clave pública
La infraestructura de clave pública (PKI) se refiere al conjunto de configuraciones que permite habilitar el intercambio seguro de información sobre la red usando encriptación de clave pública. Esta relación de confianza se basa en certificados digitales emitidos por una autoridad neutral conocida como Certificate Authority (CA).
La plataforma Java incluye APIs que facilitan la gestión de certificados digitales:
- KeyStore: Java proporciona la clase KeyStore para la persistencia de claves criptográficas y certificados.
- CertStore: Tambien está disponible esta clase que representa un repositorio público para certificados potencialmente no confiables y listas de revocación.
Como trabajar con certificados en Java
Cargar el KeyStore programaticamente:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
char[] keyStorePassword = "changeit".toCharArray();
try(InputStream keyStoreData = new FileInputStream("keystore.jks")){
keyStore.load(keyStoreData, keyStorePassword);
}
También puede hacerse directamente como parámetro al arrancar Java:
-Djavax.net.ssl.trustStore=truststore.jks
-Djavax.net.ssl.keyStore=keystore.jks
Autenticación
El proceso de autenticación consiste en validar la identidad de un usuario o máquina a través datos como contraseña, token o cualquier otro tipo de credenciales.
Autenticación en Java
Desde Java se ofrece la posibilidad de extender la clase abstracta LoginContext para implementar el proceso de autenticación, aunque ya ofrece algunos para su uso directo:
- Krb5LoginModule: Para autenticación basada en kerberos.
- JndiLoginModule: Autenticación basada en usuario y contraseña contra un directorio activo (LDAP).
- KeyStoreLoginModule: Autenticación criptográfica basada en clave.
Aquí podemos ver un ejemplo de uso sobre la autenticación con credenciales contra directorio activo:
LoginContext loginContext = new LoginContext("Ejemplo", new SampleCallbackHandler());
loginContext.login();
Ejemplo {
com.sun.security.auth.module.JndiLoginModule required;
};
Comunicación Segura
La comunicación a través de la red está sometida a numerosos vectores de ataque. Java provee APIs para encriptar, mantener la integridad de los mensajes y autenticación cliente/servidor:
- SSL/TLS: SSL y su sucesor TLS, proveen seguridad mediante encriptación de datos y PKI (public key infraestructure). Implementado en Java en la clase java.security.ssl.SSLSocket.
- SASL: Simple Authentication and Security Layer, estándar de autenticación entre cliente y servidor, implementado en el paquete java.security.sasl.
- GGS-API/Kerberos: Implementado en el paquete java.security.jgss.
Ejemplo SSL
SocketFactory factoria = SSLSocketFactory.getDefault();
try (Socket conexion = factoria.createSocket(host, puerto)) {
BufferedReader br = new BufferedReader(
new InputStreamReader(conexion.getInputStream()));
return br.readLine();
}
Para que funcione correctamente debe estar creado previamente el key-store y el trust-store.
Control de acceso
El control de acceso se encarga de restringir el acceso a recursos como sistemas de ficheros a accesos no deseados.
En Java, las clases que se encargan de implementar el control de acceso están en el paquete java.lang y son Policy, Permission y SecurityManager. Aquí podemos ver un ejemplo de su uso:
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
securityManager.checkPermission(
new FilePermission("/var/subcarpeta", "read"));
}
Recursos Java fundamentales
| Asunto | Descripción |
| Tutorial básico y sintaxis | Tutorial básico Java y sintaxis. Aprende los fundamentos del lenguaje. |
| Hilos (Threads) | Aprende a manejar hilos y las cuestiones básicas de la concurrencia |
| Funciones Lambda | Aquí te enseñamos las nociones más importantes para arrancas con funciones lambda |
| Palíndromos | Programa de ejemplo para el uso de palíndromos en Java. |
| Máquina Virtual de Java | Te explicamos el funcionamiento de la máquina virtual de java (Java Virtual Machine – JVM) |
| JDK, JRE y JVM | Diferencias entre el JDK, JRE y JVM. |
| Mejores libros Java en Español | Hazte con los mejores libros Java para aprender paso a paso y profundizar en las mejores prácticas |
| TensorFlow | Manejo del API de TensorFlow para la construcción de grafos de operaciones y su ejecución |
| Tutorial Log4j | Tutorial para el manejo de Log4j, herramienta ágil y flexible para la gestión de Logs en Java |
| Java Security | Entiende y aplica las posibilidades que da Java para mantener la seguridad |
| Tutorial JConsole | Aprende los conceptos básicos de monitorización de procesos Java con JConsole |
| JavaFX | Tutorial de JavaFX, librería gráfica moderna para construcción de GUIs en móvil, escritorio y web. |
| Estructuras de datos en Java | Explicación y ejemplos de las estructuras de datos más importantes: listas, pila, cola, arbol. |
| Javaapi | Conjunto de clases, interfaces, métodos y paquetes que forman parte de la plataforma Java estándar |
| Algoritmo Huffman | Método eficiente para codificar datos, asignando códigos más cortos a los caracteres más frecuentes |