2009-02-11 16 views
17

Tengo un archivo pkcs12. Necesito usar esto para conectarme a una página web usando el protocolo https. Me encontré con algo de código, donde con el fin de conectarse a una página web segura i necesidad de establecer las siguientes propiedades del sistema:Cómo conectarse a un sitio web seguro usando SSL en Java con un archivo pkcs12?

System.setProperty("javax.net.ssl.trustStore", "myTrustStore"); 
System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); 
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12"); 
System.setProperty("javax.net.ssl.keyStore", "new_cert.p12"); 
System.setProperty("javax.net.ssl.keyStorePassword", "newpass"); 

tengo el archivo p12 (pkcs12). Todo lo que necesito es un archivo de almacén de confianza.

que extrae los certificados usando:

openssl.exe pkcs12 -in c:/mykey.p12 -out c:/cert.txt -nokeys -clcerts 

Ahora convertido el archivo cert PEM der

openssl.exe x509 -in c:/cert.txt -outform DER -out c:/CAcert.der 

Ahora añadir el archivo der a un almacén de claves

keytool -import -file C:/Cacert.der -keystore mytruststore 

Ahora tengo el almacén de confianza, pero cuando lo uso, obtengo el siguiente error

Exception in thread "main" java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl) 

Actualización: Después de eliminar ciertas propiedades y establecer sólo la "trustStore", "trustStorePassword" y la propiedad "trustStoreType", me dio la siguiente excepción

java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty 

por favor ayuda.

+0

Si pudieras publicar más del rastro de pila (información de los marcos de pila, no solo el mensaje de excepción) lo echaré un vistazo. – erickson

+0

Otra cosa que debe verificar es que la ubicación de su tienda de confianza esté correctamente especificada; si se especifica javax.net.ssl.trustStore pero no existe, se crea un almacén fiduciario vacío sobre la marcha. Su nuevo mensaje de error lo hace sonar como si esto pudiera estar sucediendo. – erickson

Respuesta

18

Para cualquiera encontrarse con una situación similar que era capaz de resolver el problema anterior de la siguiente manera:

  1. regenerar su archivo pkcs12 de la siguiente manera:

    openssl pkcs12 -in oldpkcs.p12 -out keys -passout pass:tmp 
    openssl pkcs12 -in keys -export -out new.p12 -passin pass:tmp -passout pass:newpasswd 
    
  2. Importe el certificado de CA de servidor en un TrustStore (ya sea el suyo o el almacén de claves de java en $JAVA_HOME/jre/lib/security/cacerts, contraseña: changeit).

  3. establezca las siguientes propiedades del sistema:

    System.setProperty("javax.net.ssl.trustStore", "myTrustStore"); 
    System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); 
    System.setProperty("javax.net.ssl.keyStoreType", "pkcs12"); 
    System.setProperty("javax.net.ssl.keyStore", "new.p12"); 
    System.setProperty("javax.net.ssl.keyStorePassword", "newpasswd"); 
    
  4. prueba ur url.

Cortesía @http://forums.sun.com/thread.jspa?threadID=5296333

+0

Escribir una respuesta a su propia pregunta y aceptarla es un poco cuestionable si me pregunta. Un poco como votarte a ti mismo (que por supuesto no es posible) – Fredrik

+32

@Fredrik - me parece perfectamente razonable. Creo que probablemente haya algo en las preguntas frecuentes. –

4

Parece que está extrayendo su certificado del almacén de claves PKCS # 12 y creando un nuevo almacén de claves Java (con el tipo "JKS"). No es estrictamente necesario proporcionar una contraseña del almacén de confianza (aunque el uso de uno le permite probar la integridad de sus certificados raíz).

Por lo tanto, pruebe su programa con solo establezca las siguientes propiedades de SSL. La lista que se muestra en su pregunta está sobreespecificada y puede estar causando problemas.

System.setProperty("javax.net.ssl.trustStore", "myTrustStore"); 
System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); 

Además, el uso de los archivo PKCS # 12 directamente como el almacén de confianza debería funcionar, siempre y cuando el certificado de CA se detecta como una entrada "de confianza". Pero en ese caso, también deberá especificar la propiedad javax.net.ssl.trustStoreType como "PKCS12".

Pruebe solo con estas propiedades. Si obtiene el mismo error, sospecho que su problema no es el almacén de claves. Si aún ocurre, publique más trazas de la pila en su pregunta para reducir el problema.


El nuevo error, "el parámetro trustAnchors no debe ser vacío", podría deberse a establecer la propiedad javax.net.ssl.trustStore a un archivo que no existe; si el archivo no se puede abrir, se creó un almacén de claves vacío, lo que daría lugar a este error.

+0

Establecí solo las propiedades que especificó, ahora recibo la siguiente excepción: "InvalidAlogrithmException: el parámetro trustAnchors debe estar vacío" – user27221

+0

Solo quiero agradecer esta respuesta porque no sabía que "usando el PKCS # 12 archivo directamente ya que la tienda de confianza debería funcionar "y esto resuelve mi propio problema – fabien7474

4

Este es un ejemplo de usar el archivo p12 Sólo que no es optimazed pero funciona. El archivo pkcs12 fue generado por OpenSSL por mí. Ejemplo cómo cargar el archivo p12 y construir zona Trust de ella ... Se emite certificados de archivo de p12 y añadir buenas certs a TrustStore

KeyStore ks=KeyStore.getInstance("pkcs12"); 
ks.load(new FileInputStream("client_t_c1.p12"),"c1".toCharArray()); 

KeyStore jks=KeyStore.getInstance("JKS"); 
jks.load(null); 

for (Enumeration<String>t=ks.aliases();t.hasMoreElements();) 
{ 
    String alias = t.nextElement(); 
    System.out.println("@:" + alias); 
    if (ks.isKeyEntry(alias)){ 
     Certificate[] a = ks.getCertificateChain(alias); 
     for (int i=0;i<a.length;i++) 
     { 
      X509Certificate x509 = (X509Certificate)a[i]; 
      System.out.println(x509.getSubjectDN().toString()); 
      if (i>0) 
       jks.setCertificateEntry(x509.getSubjectDN().toString(), x509); 
      System.out.println(ks.getCertificateAlias(x509)); 
      System.out.println("ok"); 
     } 
    } 
} 

System.out.println("init Stores..."); 

KeyManagerFactory kmf=KeyManagerFactory.getInstance("SunX509"); 
kmf.init(ks, "c1".toCharArray()); 

TrustManagerFactory tmf=TrustManagerFactory.getInstance("SunX509"); 
tmf.init(jks); 

SSLContext ctx = SSLContext.getInstance("TLS"); 
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 
0

Soy consciente de que este artículo puede ser anticuada, pero todavía me gustaría pida a smithsv que corrija su código fuente, contiene muchos errores, logré corregir la mayoría de ellos pero todavía no sé qué tipo de objeto podría ser x509. Aquí está el código fuente como creo que debería ser:

import java.io.FileInputStream; 
import java.security.KeyStore; 
import java.security.cert.Certificate; 
import java.util.Enumeration; 

import javax.net.ssl.KeyManagerFactory; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.TrustManagerFactory; 

public class Connection2 { 
    public void connect() { 
     /* 
     * This is an example to use ONLY p12 file it's not optimazed but it 
     * work. The pkcs12 file where generated by OpenSSL by me. Example how 
     * to load p12 file and build Trust zone from it... It outputs 
     * certificates from p12 file and add good certs to TrustStore 
     */ 
     KeyStore ks = KeyStore.getInstance("pkcs12"); 
     ks.load(new FileInputStream(cert.pfx), "passwrd".toCharArray()); 

     KeyStore jks = KeyStore.getInstance("JKS"); 
     jks.load(null); 

     for(Enumeration t = ks.aliases(); t.hasMoreElements();) { 
      String alias = (String)t.nextElement(); 
      System.out.println("@:" + alias); 
      if(ks.isKeyEntry(alias)) { 
       Certificate[] a = ks.getCertificateChain(alias); 
       for(int i = 0; i == 0;) 
        jks.setCertificateEntry(x509Cert.getSubjectDN().toString(), x509); 

       System.out.println(ks.getCertificateAlias(x509)); 
       System.out.println("ok"); 
      } 
     } 

     System.out.println("init Stores..."); 

     KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 
     kmf.init(ks, "c1".toCharArray()); 

     TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 
     tmf.init(jks); 

     SSLContext ctx = SSLContext.getInstance("TLS"); 
     ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 
    } 
} 
1

Este ejemplo muestra cómo puede capa SSL sobre un socket existente, obteniendo el certificado del cliente de un PKCS # 12 fil mi. Es apropiado cuando necesita conectarse a un servidor ascendente a través de un proxy, y desea manejar el protocolo completo por su cuenta.

Esencialmente, sin embargo, una vez que tenga el contexto de SSL, se puede aplicar a un HttpsURLConnection, etc, etc.

KeyStore ks = KeyStore.getInstance("PKCS12"); 
InputStream is = ...; 
char[] ksp = storePassword.toCharArray(); 
ks.load(is, ksp); 
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 
char[] kp = keyPassword.toCharArray(); 
kmf.init(ks, kp); 
sslContext = SSLContext.getInstance("SSLv3"); 
sslContext.init(kmf.getKeyManagers(), null, null); 
SSLSocketFactory factory = sslContext.getSocketFactory(); 
SSLSocket sslsocket = (SSLSocket) factory.createSocket(socket, socket 
    .getInetAddress().getHostName(), socket.getPort(), true); 
sslsocket.setUseClientMode(true); 
sslsocket.setSoTimeout(soTimeout); 
sslsocket.startHandshake(); 
5

que no puedo comentar debido a la 50pts umbral, pero no creo que la respuesta proporcionada en https://stackoverflow.com/a/537344/1341220 es correcta. Lo que en realidad se está describiendo es cómo insertar los certificados de servidor en el almacén de confianza predeterminado sistemas:

$JAVA_HOME/jre/lib/security/cacerts, password: changeit) 

Esto funciona, de hecho, sino que significa que en realidad no especifica un almacén de confianza local para su proyecto, sino más bien aceptadas el certificado universialmente en su sistema.

En realidad nunca use su propio almacén de confianza que ha definido aquí:

System.setProperty("javax.net.ssl.trustStore", "myTrustStore"); 
System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); 
+0

Entiendo tu punto. Pero, me pregunto, ¿la declaración 'System.setProperty' cambia el almacén de confianza predeterminado o no? Has mencionado en tu respuesta que no es posible usar el trust store definido en el código ya que él/ella ya usa el predeterminado. ¿Es eso realmente cierto? Entonces, ¿qué sentido tiene 'System.setProperty' si la tienda predeterminada no es modificable? – Salman

0
URL url = new URL("https://test.domain:443"); 
String keyStore = "server.p12" 
String keyStorePassword = "changeit";  
String keyPassword = "changeit";  
String KeyStoreType= "PKCS12";  
String KeyManagerAlgorithm = "SunX509";  
String SSLVersion = "SSLv3";  
public HttpURLConnection getHttpsURLConnection(URL url, String keystore, 
    String keyStorePass,String keyPassword, String KeyStoreType 
    ,String KeyManagerAlgorithm, String SSLVersion) 
    throws NoSuchAlgorithmException, KeyStoreException, 
     CertificateException, FileNotFoundException, IOException, 
     UnrecoverableKeyException, KeyManagementException { 
    System.setProperty("javax.net.debug","ssl,handshake,record"); 

    SSLContext sslcontext = SSLContext.getInstance(SSLVersion); 
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerAlgorithm); 
    KeyStore ks = KeyStore.getInstance(KeyStoreType); 
    ks.load(new FileInputStream(keystore), keyStorePass.toCharArray()); 
    kmf.init(ks, keyPassword.toCharArray()); 

    TrustManagerFactory tmf = TrustManagerFactory 
      .getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
    tmf.init(ks); 
    TrustManager[] tm = tmf.getTrustManagers(); 

    sslcontext.init(kmf.getKeyManagers(), tm, null); 
    SSLSocketFactory sslSocketFactory = sslcontext.getSocketFactory(); 
    HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory); 
    HttpsURLConnection httpsURLConnection = (HttpsURLConnection)uRL.openConnection(); 

    return httpsURLConnection; 
} 
1

Los siguientes pasos le ayudarán a ordenar su problema hacia fuera.

Pasos: developer_identity.cer < = descargar desde Apple mykey.p12 = < Sus privadas clave

comandos a seguir:

openssl x509 -in developer_identity.cer -inform DER -out developer_identity.pem -outform PEM 

    openssl pkcs12 -nocerts -in mykey.p12 -out mykey.pem 

    openssl pkcs12 -export -inkey mykey.pem -in developer_identity.pem -out iphone_dev.p12 

p12 final que vamos a requerir es iphone_dev.p12 archivo y la contraseña.

utilice este archivo como su p12 y luego inténtelo. Esta es la solución. :)

Cuestiones relacionadas