servicio - keytool java
¿Cómo puedo conectarme a un sitio web seguro usando SSL en Java con un archivo pkcs12? (8)
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 las siguientes propiedades de SSL configuradas. 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, usar el archivo PKCS # 12 directamente como debería funcionar el almacén de confianza, siempre que el certificado de CA se detecte como una entrada "de confianza". Pero en ese caso, también deberá especificar la propiedad javax.net.ssl.trustStoreType
como "PKCS12"
.
Pruebe con estas propiedades solamente. 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 debe ser no vacío", podría deberse a la configuración de la propiedad javax.net.ssl.trustStore
en 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.
Tengo un archivo pkcs12. Necesito usar esto para conectarme a una página web usando el protocolo https. Encontré un código donde para conectarme a una página web segura necesito establecer 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_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.
Extraje los certificados usando:
openssl.exe pkcs12 -in c:/mykey.p12 -out c:/cert.txt -nokeys -clcerts
Ahora convirtió el archivo cert PEM a der
openssl.exe x509 -in c:/cert.txt -outform DER -out c:/CAcert.der
Ahora agregando 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, aparece 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 solo la propiedad "trustStore", "trustStorePassword" y "trustStoreType", obtuve la siguiente excepción
java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
Por favor ayuda.
Para cualquier persona que se encuentre en una situación similar, pude resolver el problema anterior de la siguiente manera:
Vuelva a generar 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
Importe el certificado de CA del servidor a una Tienda de TrustS (ya sea suya o del almacén de claves de Java en
$JAVA_HOME/jre/lib/security/cacerts
, password:changeit
).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");
Prueba tu url.
Cortesía @ http://forums.sun.com/thread.jspa?threadID=5296333
Este ejemplo muestra cómo puede aplicar capas a SSL sobre un socket existente, obteniendo el certificado del cliente de un archivo PKCS # 12. 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 tiene el contexto SSL, puede aplicarlo 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();
Este es un ejemplo para usar SOLAMENTE el archivo p12, no está optimizado pero funciona. El archivo pkcs12 fue generado por OpenSSL por mí. Ejemplo de cómo cargar un archivo p12 y crear una zona Trust desde él ... Emite certificados del archivo p12 y agrega buenos 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);
Me doy cuenta de que este artículo puede estar desactualizado, pero aún así me gustaría pedirle a Smithsv que corrija su código fuente, contiene muchos errores, logré corregir la mayoría pero aún no sé qué tipo de objeto podría ser x509. Aquí está el código fuente, como creo, 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 );
}
}
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;
}
Los siguientes pasos lo ayudarán a resolver su problema.
Pasos: developer_identity.cer <= descargar de Apple mykey.p12 <= Su clave privada
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
La p12 final que necesitaremos es el archivo iphone_dev.p12 y la frase de contraseña.
usa este archivo como tu p12 y luego prueba. Esta es, de hecho, la solución. :)
No puedo hacer ningún comentario debido al límite de 50 puntos, pero no creo que la respuesta proporcionada en https://.com/a/537344/1341220 sea correcta. Lo que en realidad está describiendo es cómo inserta los certificados del servidor en el almacén de confianza predeterminado del sistema:
$JAVA_HOME/jre/lib/security/cacerts, password: changeit)
Esto funciona, de hecho, pero significa que realmente no especificó un local de confianza en su proyecto, sino que aceptó el certificado de forma universal en su sistema.
En realidad, nunca usas tu propio almacén de confianza que definiste aquí:
System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");