Saltar al contenido
Portada » Java security

Java security

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

AsuntoDescripción
Tutorial básico y sintaxisTutorial 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 LambdaAquí te enseñamos las nociones más importantes para arrancas con funciones lambda
PalíndromosPrograma de ejemplo para el uso de palíndromos en Java.
Máquina Virtual de JavaTe explicamos el funcionamiento de la máquina virtual de java (Java Virtual Machine – JVM)
JDK, JRE y JVMDiferencias entre el JDK, JRE y JVM.
Mejores libros Java en EspañolHazte con los mejores libros Java para aprender paso a paso y profundizar en las mejores prácticas
TensorFlowManejo del API de TensorFlow para la construcción de grafos de operaciones y su ejecución
Tutorial Log4jTutorial para el manejo de Log4j, herramienta ágil y flexible para la gestión de Logs en Java
Java SecurityEntiende y aplica las posibilidades que da Java para mantener la seguridad
Tutorial JConsoleAprende los conceptos básicos de monitorización de procesos Java con JConsole
JavaFXTutorial de JavaFX, librería gráfica moderna para construcción de GUIs en móvil, escritorio y web.
Estructuras de datos en JavaExplicación y ejemplos de las estructuras de datos más importantes: listas, pila, cola, arbol.
JavaapiConjunto de clases, interfaces, métodos y paquetes que forman parte de la plataforma Java estándar
Algoritmo HuffmanMétodo eficiente para codificar datos, asignando códigos más cortos a los caracteres más frecuentes