J'ai un fichier pkcs12. J'ai besoin de l'utiliser pour me connecter à une page Web à l'aide du protocole https. Je suis tombé sur un code dans lequel, pour me connecter à une page Web sécurisée, je dois définir les propriétés système suivantes:
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");
J'ai le fichier p12 (pkcs12). Tout ce dont j'ai besoin est un fichier de magasin de clés de confiance.
J'ai extrait les certificats en utilisant:
openssl.exe pkcs12 -in c:/mykey.p12 -out c:/cert.txt -nokeys -clcerts
Maintenant converti le fichier cert PEM en der
openssl.exe x509 -in c:/cert.txt -outform DER -out c:/CAcert.der
Ajouter maintenant le fichier der à un magasin de clés
keytool -import -file C:/Cacert.der -keystore mytruststore
Maintenant, j'ai le fichier de clés certifiées, mais lorsque je l'utilise, l'erreur suivante s'affiche
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)
Mettre à jour: Après avoir supprimé certaines propriétés et défini uniquement les propriétés "trustStore", "trustStorePassword" et "trustStoreType", j'ai obtenu l'exception suivante.
Java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
S'il vous plaît aider.
Pour toute personne rencontrant une situation similaire, j'ai pu résoudre le problème ci-dessus comme suit:
Régénérez votre fichier pkcs12 comme suit:
openssl pkcs12 -in oldpkcs.p12 -out keys -passout pass:tmp
openssl pkcs12 -in keys -export -out new.p12 -passin pass:tmp -passout pass:newpasswd
Importez le certificat de l'autorité de certification depuis le serveur dans un magasin de souvenirs (le vôtre ou le magasin de clés Java dans $Java_HOME/jre/lib/security/cacerts
, mot de passe: changeit
).
Définissez les propriétés système suivantes:
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");
Test ur url.
Courtesy @ http://forums.Sun.com/thread.jspa?threadID=5296333
Je ne peux pas commenter à cause du seuil de 50 points, mais je ne pense pas que la réponse fournie dans https://stackoverflow.com/a/537344/1341220 soit correcte . Ce que vous décrivez en réalité, c'est comment vous insérez des certificats de serveur dans le magasin de clés par défaut des systèmes:
$Java_HOME/jre/lib/security/cacerts, password: changeit)
Cela fonctionne, certes, mais cela signifie que vous n'avez pas vraiment spécifié de magasin de clés de confiance local pour votre projet, mais que vous avez accepté le certificat de manière universelle dans votre système.
En fait, vous n'utilisez jamais votre propre fichier de clés de confiance que vous avez défini ici:
System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
Il semble que vous extrayiez votre certificat du magasin de clés PKCS # 12 et que vous créez un nouveau magasin de clés Java (de type "JKS"). Vous n'êtes pas obligé de fournir un mot de passe de magasin de données de confiance (bien que son utilisation vous permette de tester l'intégrité de vos certificats racine).
Alors, essayez votre programme avec seulement les propriétés SSL suivantes. La liste affichée dans votre question est sur spécifiée et peut être à l'origine de problèmes.
System.setProperty("javax.net.ssl.trustStore", "myTrustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
De plus, l'utilisation du fichier PKCS # 12 directement en tant que magasin de confiance devrait fonctionner, à condition que le certificat de l'autorité de certification soit détecté comme une entrée "de confiance". Mais dans ce cas, vous devrez également spécifier la propriété javax.net.ssl.trustStoreType
sous la forme "PKCS12"
.
Essayez avec ces propriétés seulement. Si vous obtenez la même erreur, je soupçonne que votre problème n'est pas le magasin de clés. Si cela se produit toujours, postez davantage de traces de la pile dans votre question afin de réduire le problème.
La nouvelle erreur, "le paramètre trustAnchors doit être non vide", pourrait être due à la définition de la propriété javax.net.ssl.trustStore
sur un fichier qui n'existe pas; si le fichier ne peut pas être ouvert, un magasin de clés vide est créé, ce qui entraînerait cette erreur.
Ceci est un exemple pour utiliser UNIQUEMENT le fichier p12 ce n'est pas optimazed mais ça marche . Le fichier pkcs12 a été généré par OpenSSL par moi . Exemple comment charger un fichier p12 et en construire une zone de confiance ....__ Il émet des certificats à partir d'un fichier p12 et ajoute de bons certificats à 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);
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;
}
Les étapes suivantes vous aideront à résoudre votre problème.
Étapes: Developer_identity.cer <= à télécharger chez Apple Mykey.p12 <= votre clé privée
Commandes à suivre:
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 dernière p12 dont nous aurons besoin est le fichier iphone_dev.p12 et la phrase secrète.
utilisez ce fichier comme votre p12 puis essayez. C'est bien la solution :)
Cet exemple montre comment vous pouvez superposer SSL sur un socket existant, en obtenant le certificat client à partir d'un fichier PKCS # 12. Cela convient lorsque vous devez vous connecter à un serveur en amont via un proxy et que vous souhaitez gérer vous-même le protocole complet.
Cependant, une fois que vous avez le contexte SSL, vous pouvez l’appliquer à une connexion 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();
Je me rends compte que cet article est peut-être obsolète, mais je voudrais quand même demander à smithsv de corriger son code source. Il contient de nombreuses erreurs. le code source tel que je pense devrait être:
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 );
}
}