Generalmente servidores web basados en Java como Tomcat utilizan keytool ,
una utilidad Java, para crear las claves públicas, privadas y los
certificados asociados con este par de claves.
Los certificados se
utilizan como firmas digitales , que proporciona una autenticación
segura cuando se conectan los clientes a un servidor.
Keytool genera
un almacen de claves , que tienen certificados de seguridad.
Los Keystores
pueden utilizar el formato P12 o JKS .
P12 archivos son casi
universalmente compatibles, pero el formato es extremadamente complejo.
Es posible utilizar keytool para convertir P12 a JKS , un formato más
sencillo sólo se puede acceder a través de las aplicaciones Java.
Aqui las Instrucciones :
1.- Haga clic en " Inicio". Escriba " cmd" en el cuadro de búsqueda y luego presionar "Enter " para abrir el símbolo del sistema .
2.-Tipo "cd /" sin las comillas en la aplicación de línea de comandos y presione "Enter " para acceder a la carpeta raíz.
3.- Escriba "cd " seguido por el pleno del ruta de acceso que une al directorio donde se guarda el almacén de claves
4.-Escriba lo siguiente en el símbolo del sistema para convertir P12 a JKS :
keytool- importkeystore - srckeystore keystore.p12 - srcstoretype PKCS12 - deststoretype keystore.jks JKS - destkeystore
Pulse " Enter" después de cada comando para convertir P12 a JKS en
Keytool .
Es posible que se le pida para crear una nueva contraseña para
el almacén de claves JKS , se recomienda que utilice la misma
contraseña del almacén de claves originales
Generar y convertir claves y certificados con OpenSSL
Usando los comandos expuestos en este artículo y con OpenSSL podemos
crear una clave pública y privada para usarlo con ssh o para cifrar y
descifrar mensajes, un certificado autofirmado que podremos usar en un
servidor de aplicaciones para usar un protocolo seguro y también
convertir las claves y certificados a uno de los formatos aceptados por
la aplicación que usemos.
Para un uso personal como enviar correos o archivos cifrados o firmados digitalmente usar GnuPG
es una buena opción. En Internet los servidores también se aprovechan
del uso de criptografía para realizar comunicaciones seguras entre el
usuario y el servidor.
Para hacer uso en un servidor de una comunicación https donde los
datos viajan cifrados y sin que otras partes salvo el usuario y el
servidor puedan acceder a los datos necesitamos un certificado digital.
Un certificado es un archivo que contiene la clave pública sirviéndonos
para verificar su autenticidad. Un certificado autofirmado es un
certificado firmado con la misma clave privada asociada a la clave
pública que contiene el certificado. Un certificado autofirmado es
suficiente para un entorno de pruebas pero en un servidor para
proporcionar confianza a los usuarios deberemos solicitar que una
autoridad de certificados que nos firme con su clave nuestro
certificado, si el usuario confía en esa autoridad de certificado puede
de esta manera confiar en nuestro certificado y clave pública. Varias
entidades de registro de dominios o halojamiento web ofrecen la compra
de certificados SSL, en el artículo Certificado SSL, de empresa, «wildcard» y de validación extendida comento con un poco más detalle los varios tipos de certificados y algunas opciones donde obtenerlos o comprarlos.
Dependiendo del tipo de certificado que solicitemos y nos entregue la
autoridad de certificado el usuario podrá ver que está simplemente
accediendo a un servidor con conexión segura, ver los detalles de
nuestro certificado y en algunos casos el usuario podrá ver en la barra
de direcciones en verde el nombre de la entidad, que puede darle al
usuario más confianza y ver que realmente está accediendo al servidor
correcto y no a uno que esté intentando suplantar una identidad. En este
último caso la barra de direcciones no tendría en verde el nombre de la
entidad, esto es algo que como usuarios debemos comprobar al acceder a
determinados sitios de forma segura.
Con la herramienta OpenSSL y los siguientes comandos podemos generar claves y certificados y realizar las conversiones entre formatos que necesitemos.
Dependiendo de la autoridad de certificado el certificado puede estar
en diferentes formatos, dependiendo del servidor donde tengamos idea de
usarlo podemos necesitar convertirlo a otro formato. También podemos
usar OpenSSL para hacer las conversiones.
| $ cat localhost.key localhost.crt > localhost.pem |
| $ openssl x509 -in localhost.crt -out localhost.pem |
| $ openssl x509 -inform der -in localhost.cer -out localhost.pem |
| $ openssl x509 -outform der -in localhost.pem -out localhost.der |
Convertir un certificado en formato PEM y una clave privada a PKCS#12 (.pfx .p12)
$ openssl pkcs12 -export -out localhost.p12 -inkey localhost.key -in localhost.crt
| $ openssl pkcs12 -in localhost.p12 -out localhost.pem -nodes |
Convertir PKCS#12 a keystore JKS
| $ keytool -importkeystore -destkeystore localhost.keystore -srckeystore localhost.p12 -srcstoretype pkcs12 |
Aqui unos ejemplos:
| openssl genrsa -out localhost.key 8192 |
| openssl req -new -key localhost.key -out localhost.csr |
| openssl req -new -x509 -days 1825 -key localhost.key -out localhost.crt |
| cat localhost.key localhost.crt > localhost.pem |
| openssl x509 -in localhost.crt -out localhost.pem |
| openssl x509 -inform der -in localhost.cer -out localhost.pem |
| openssl x509 -outform der -in localhost.pem -out localhost.der |
| openssl pkcs12 -export -out localhost.p12 -inkey localhost.key -in localhost.crt |
| openssl pkcs12 -in localhost.p12 -out localhost.pem -nodes |
| keytool -importkeystore -destkeystore localhost.keystore -srckeystore localhost.p12 -srcstoretype pkcs12 |
| openssl rsa -in localhost.key -pubout > localhost.pub |
Otra forma enerar y convertir claves y certificados con OpenSSL
En primer lugar, asegúrese de que usted tiene OpenSSL instalado. Muchos sistemas operativos ya lo han instalado como he encontrado con Mac OS X.
Los dos comandos siguientes convertir el archivo pfx a un formato que puede ser abierto como un Java PKCS12 almacén de claves:
openssl pkcs12 -in mypfxfile.pfx -out mypemfile.pem
openssl pkcs12 -export -in mypemfile.pem -out mykeystore.p12 -name "MyCert"
Tenga en cuenta que el nombre proporcionado en el segundo comando es el alias de tu clave en el nuevo almacén de claves.
Referencia
Usted
puede verificar el contenido del almacén de claves utilizando el
programa de utilidad keytool de Java con el siguiente comando:
keytool -v -list -keystore mykeystore.p12 -storetype pkcs12
Por último, si necesita usted puede convertir esto en un
almacén de claves JKS importando el almacén de claves creado
anteriormente en un nuevo almacén de claves:
keytool -importkeystore -srckeystore mykeystore.p12 -destkeystore clientcert.jks -srcstoretype pkcs12 -deststoretype JKS
Exportar e Importar con Java Keytool
Informacion de Referencia
Exportar su certificado a un archivo
Si desea respaldar su certificado para utilizar en el mismo u otro
servidor web también con Java solo necesita copiar el archivo .keystore a
un medio extraible.
Si desea exportar su certificado para importar en otro servidor web
sin Java deberá descargar e instalar un programa externo para poder
hacerlo ya que la herramienta keytool no cuenta con un comando para
extraer la clave privada del .keystore.
Alguno de los programas que le permitirán hacer la exportación de la clave privada son:
KeyTool-IUI,
Portecle,
Keystore Explorer
Importar su certificado desde un archivo
Para utilizar su archivo .pfx o .p12 como keystore para tomcat debe ejecutar el siguiente comando:
keytool -import -alias tomcat -keystore archivo.p12
Su keystore se encuentra ahora listo para ser configurado en tomcat modificando el archivo server.xml de la siguiente forma:
keystoreType="PKCS12"
keystoreFile="archivo.p12"
keystorePass=Contraseña
Convertir su certificado de .pfx o .p12 a .jks
Deberá contar con openssl y alguno de los programas que le permitirán convertir el formato de su certificado como por ejemplo:
KeyTool-IUI,
Portecle,
Keystore Explorer
Cualquiera de estos programas tienen la opción de abrir un .pfx o
.p12 y guardarlo como .jks o .keystore cambiando el formato de manera
sencilla. En nuestra experiencia, todos ellos fallan en importar el
archivo en formato .pfx o .p12 si existe la más mínima diferencia en
formatos.
Si estos programas fallan en abrir su .pfx o .p12 deberá seguir estos
pasos para convertir su certificado en un formato que estos programas
puedan abrir.
(Puede descargar openssl para Windows de
aqui)
Extraer su clave privada y convertirla
openssl pkcs12 -in archivo.pfx -nocerts -nodes -out clavepriv.pem
openssl rsa -in clavepriv.pem -out convertpriv.pem
Extraer sus certificados
openssl pkcs12 -in archivo.pfx -nokeys -out cert.pem
Generar keystore
Ahora debe crear un nuevo keystore vacío utilizando alguno de los
programas mencionados e importar la clave privada y el certificado
extraídos, ya sea por separado (KeyTool-IUI) o concatenando los
certificados al archivo de la clave (Portecle)
Concatenar archivos
Windows
copy convertpriv.pem+cert.pem completo.pem
Linux
cat convertpriv.pem cert.pem > completo.pem
Como convertir un Keystore JKS al formato PKCS12 (.p12)
Para convertir un keystore JKS (.jks) a un archivo PKCS12 (p.12), ejecute el siguiente comando:
NOTA: Este comando es compatible con versiones de JDK/JRE 1.6 o mayores. Keytool es una herramienta de terceros.
keytool -importkeystore -srckeystore [MY_KEYSTORE.jks] -destkeystore [MY_FILE.p12]
-srcstoretype JKS - deststoretype PKCS12 -deststorepass [PASSWORD_PKCS12]
Lista de parametros:
MY_KEYSTORE.jks: ruta del archivo keystore que desea convertir.
MY_FILE.p12: ruta del archivo PKCS12 (.p12 o extension .pfx) que se crear.
PASSWORD_PKCS12: la contraseña del archivo PKCS12.
Para verificar el contenido del archivo PKCS12, ejecute el siguiente comando:
keytool -list -v -keystore MY_FILE.p12 -storetype pkcs12
Java Archivo .JKS Creación de un .PFX
Convertir de Formatos de Certificado de .PFX al .JKS
Tenga en cuenta que el objetivo de estas instrucciones es para
mostrar cómo separar los certificados SSL y la llave privada para
generar un archivo .PFX y combinarlos en un Keystore "Almacén de Llaves"
de Java.
Esta operación requirirá las dos programas Keytool y OpenSSL, y una utilidad de Weblogic específicas también.
Convertir PFX al JKS En Weblogic
PFX es un formato de certificados SSL que se utilice en Windows que
combina ambos el archivo de todos los certificados SSL de la cadena de
confianza que contine el archivo de la llave pública y la llave privada
asociada en un solo archivo .PFX.
Con el fin de convertir sus archivos de certificado en un formato
que se puede utilizar por un servidor basado en Java, usted tendrá que
extraer primero los certificados y la llave privada de su archivo PFX
mediante el programa OpenSSL, y luego importar el CERT a su Keystore
"Almacén de Llaves" usando el programa Keytool.
- En segundo lugar, ejecute el siguiente comando de OpenSSL para extraer sus certificados y la llave privada del archivo .PFX:
openssl pkcs12-in-out suDominio.pfx certificado_temporario.crt -nodes
- Ahora debería tener un archivo llamado
certificado_temporario.crt. Abra este archivo con un editor de texto
(como WordPad) y verá la llave privada aparece en primer lugar, seguido
por los archivos de su certificado:
----- BEGIN RSA PRIVATE KEY -----
(Bloque de Texto Cifrado)
----- END RSA PRIVATE KEY -----
- Cortar y pegar todo la llave privada, incluyendo el BEGIN y
END etiquetas a un archivo de texto y guardarlo como su_dominio_com.key
- Los certificados que queda en su certificado_temporario.crt será
en el siguiente orden, Certificado de Servidor, Certificado Intermedio,
Certificado Raíz, dependiendo de su exportación PFX podría haber entre 2
y 4 certificados por separado dentro de este fichero.
- Con tal que haya exportado el certificado correctamente, tendrá
toda lo necesario para guardar el certificado. Asegúrese de que la llave
privada se quitó del archivo, y luego seguir adelante y guarde este
archivo como su_dominio_com.pem.
- Si usted tiene acceso para iniciar sesión en su cuenta
DigiCert, seguir adelante e iniciar sesión en, haga clic en el número de
pedido y descargue el archivo TrustedRoot.crt.
- Si no, vaya de nuevo en el archivo vaya a abrir el archivo
certificado_temporario.crt en un editor de texto y copie el segundo
certificado incluso las etiquetas BEGIN CERTIFICATE y END CERTIFICATE en
un archivo nuevo y nombre este archivo TrustedRoot.crt.
- Usted puede asegurarse de que haya elegido el archivo correcto,
verificando que su TrustedRoot.crt se emitió por la misma organización. Nota:
Debido al hecho de que DigiCert frecuentamente emite certificados
firmado por unas otras autoridades de certificación para mejorar la
compatibilidad en varias tipos de servidores y aplicaciones de cliente y
servidor,
la información de su certificado raíz puede ser diferente de lo que
se muestra en la imagen de abajo.
- Cree una Almacén de Llaves de Autoridad Confiada-
Ejecutar las siguientes dos líneas como un comando (en una linea) en Keytool:
keytool -import -trustcacerts -file TrustedRoot.crt -alias servidor
-Keystore nuevo_almacen_confiado.jks -storepass NUEVACONTRASEÑA
Usted debe ingresar su contraseña después de -storepass en el código de encima.
- A continuación, se creará un Identidad Almacén de Certificados, Ejecute el siguiente comando:
-
java utils.ImportPrivateKey -keystore nuevo_almacen_identidad.jks -storepass
CONTRASEÑA -storetype JKS -keypass NUEVACONTRASEÑA -alias
servidor -certfile certificado_temporario.crt -keyfile su_dominio_com.key
-Keyfilepass PFXCONTRASEÑA
Entre su propia contraseña para el storepass-y-keypass atributos,
por encima, y la contraseña de PFX que se habrían creado cuando el
archivo PFX fue creado.
Ahora debe tener dos archivos, nuevo_almacen_confiado.jks y
nuevo_almacen_identidad.jks. Estos archivos deben estar listos para
estar habilitado para SSL en su servidor basado en Java.
Autenticación de cliente SSL en web services con Axis2
Normalmente uso Axis2 para crear mis clientes de web services; es
bastante sencillo ya que solamente hay que ejecutar el script wsdl2java
pasando el WSDL del web service y se genera una clase que contiene todo
lo necesario para invocar los métodos publicados en el servicio.
Recientemente, me topé con un web service que en pruebas funcionó muy
bien pero resulta que en producción había que activar SSL (o sea
https://blabla en el URL en vez de solamente
http://blabla)
y además tuve que implementar un esquema muy poco usual (aunque sea un
estándar): autenticación de cliente con PKI (Public Key Infrastructure -
Infraestructura de Llave Pública).
El funcionamiento de SSL por lo general es que solamente el servidor
se autentica con el cliente, y luego el cliente se autentica de alguna
forma específica a la aplicación. La manera en que funciona la
autenticación del servidor en una conexión SSL es via PKI; el servidor
utiliza un certificado X509 que contiene su información, una fecha de
expiración, una llave pública (RSA por lo general) y algunos datos del
emisor de dicho certificado. En PKI se maneja el concepto de
cadena de confianza,
que consiste en que para poder aceptar el certificado de alguien más
como válido, es necesario conocer al emisor o emisores de dicho
certificado, hasta llegar al certificado raíz; si todos son considerados
válidos y conocidos por el cliente, entonces se puede considerar válido
el certificado del servidor.
Con Axis2 o cualquier otra herramienta para web services, todo este
mecanismo de autenticar al servidor se maneja ya de forma automática. De
hecho quien se encarga es el mismo JRE, porque con el ambiente Java ya
vienen incluidos los certificados raíz más populares, por lo que
cualquier certificado emitido por ellos será aceptado como válido
(siempre y cuando cumpla las otras condiciones, como que esté vigente,
etc).
Pero en SSL también el servidor puede autenticar a los clientes de la
misma forma, es decir, solicitando al cliente su certificado X509 para
validarlo. Esto ya no se maneja de manera tan transparente en Java; una
opción para lograr esto es tener el certificado cliente y la
correspondiente llave privada, almacenados en el KeyStore del usuario
que corre el programa que quiere hacer la conexión que requiere
autenticación de cliente. Pero entonces hay que estar configurando el
KeyStore de cada cliente, y eso puede ser problemático, o bien puede ser
que ni siquiera tengamos permiso de modificar ese KeyStore y por lo
tanto hay que usar un KeyStore privado.
Esto último fue mi caso: tengo una aplicación que invoca distintos
web services y solamente uno de ellos me pide este esquema, por lo que
no quiero modificar todo el KeyStore porque hay que hacerlo en
desarrollo y luego en producción y cualquier otra persona que quiera
invocar el web service tiene que hacer lo mismo. De modo que preferí
hacer un KeyStore privado para este web service. En Axis2, necesitamos
primero que nada crear una fábrica de sockets para el HttpClient que usa
el cliente del web service. De modo que hay que implementar la interfaz
org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory.
En mi caso, recibí el certificado y la llave privada en un archivo de
tipo PKCS#12, un formato que permite almacenar precisamente una serie de
llaves privadas y sus correspondientes certificados, protegido todo por
un password. Afortunadamente, Java permite leer este tipo de archivos
como un KeyStore. Simplemente hay que hacer lo siguiente:
String password = "el password del archivo PKCS12"
java.security.KeyStore ks = KeyStore.getInstance("PKCS12");
InputStream stream = //obtener de alguna manera un InputStream para el contenido del archivo PKCS12
ks.load(stream, password.toCharArray());
stream.close();
Ya que tenemos el KeyStore, necesitamos crear una KeyManagerFactory con el mismo:
Finalmente, ya que tenemos el KeyManagerFactory, debemos crear un
SSLContext que es con el que vamos a crear los sockets que necesita el
web service para enviar y recibir datos:
javax.net.ssl.SSLContext ssl = SSLContext.getInstance("SSL"); //Otra opcion es TLS
ssl.init(kmf.getKeyManagers(), null, null);
//El segundo parametro es una lista de TrustManagers, si pasamos null se usan los de default de Java
//El tercer parametro es un SecureRandom, si pasamos null si usa el default de Java
El objeto SSLContext es el que se debe usar en los métodos para crear
sockets de nuestra implementación de SecureProtocolSocketFactory. La
implementación es bastante directa, simplemente en cada método hay que
devolver un socket creado por el SSLContext con los parámetros
recibidos, por ejemplo:
Con esto apenas tenemos lo necesario para poder crear sockets SSL con
un contexto que permite autenticar al cliente si el servidor lo
requiere. Ahora tenemos que registrar este SecureProtocolSocketFactory
con nuestro web service, para el protocolo https (podríamos ponerle el
nombre que sea al protocolo; siempre y cuando usemos ese protocolo en el
URL, se va a usar nuestra fábrica de sockets). Si el web service lo
generamos usando Axis2 ADB con el programa wsdl2java (yo usé Axis2 1.5)
entonces:
NuestraSubclaseDeSecureProtocolSocketFactory fabrica = //esta la debemos tener ya lista
org.apache.commons.httpclient.protocol.Protocol proto = new Protocol("https", fabrica, 443);
//El protocolo tiene el nombre, la fabrica de sockets, y el puerto default a donde deben conectarse
miWebServiceStub._getServiceClient().getOptions().setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, proto);
Con lo anterior, si le pasamos al web service un URL que comience con
https:// entonces se va a usar nuestra fábrica de sockets, la cual
tiene el SSLContext que contiene el certificado y llave privada del
archivo PKCS12 para poder autenticarse con el server. Si el servidor
tiene un certificado válido emitido por una de las autoridades
certificadas reconocidas por nuestra instalación de Java, ya estamos
listos para invocar el web service via SSL.
Adicionalmente, si el servidor usa un certificado auto-firmado, al
invocar el web service vamos a obtener un error porque Java no reconoce
el certificado del servidor; en este caso, hay que hacer algo de trabajo
adicional. Necesitamos obtener el certificado del servidor, y guardarlo
en un archivo de KeyStore. Por seguridad, no recomiendo usar el
KeyStore default del usuario, sino usar uno separado. Para ello
necesitamos un archivo con el certificado y luego lo importamos a un
nuevo KeyStore con la herramienta keytool (esto no es tan relevante para
este post, simplemente hay que ver la documentación del programa
keytool; al final tendremos un archivo tipo JKS protegido por un
password).
Una vez que tenemos el archivo, debemos crear un TrustManagerFactory,
de preferencia en el mismo lugar donde creamos el KeyManagerFactory
(dentro de nuestra fábrica de sockets, antes de crear el SSLContext):
String pass2 = "el password del keystore que contiene el certificado del servidor";
javax.net.ssl.TrustManagerFactory tmf = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks2 = KeyStore.getInstance("JKS");
InputStream stream2 = //obtener un InputStream al archivo tipo JKS que generamos con keytool y que contiene el certificado auto-firmado del servidor
ks2.load(stream2, pass2.toCharArray());
stream2.close();
tmf.init(ks2);
//Modificamos el inicializador de nuestro SSLContext, el segundo parametro ya tiene valor
ssl.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
Con esto, ya tenemos un SSLContext que crea sockets para conexiones
SSL donde se reconoce únicamente el certificado auto-firmado del
servidor y que se van a autenticar con el certificado y llave privada
del archivo PKCS12.
Estuve peleándome un buen rato con esto porque no hay mucha
documentación, espero le sirva a alguien en el futuro. Aplica para
Axis2, lo hice con 1.5 pero supongo que funciona con algunas versiones
anteriores.
De hecho esto funciona para autenticar a un cliente con cualquier
servidor SSL; en el caso de web services hay que encapsular todo esto en
la implementación de SecureProtocolSocketFactory pero en caso de usar
SSL puro, el código será muy similar aunque vaya encapsulado en algún
componente distinto.