Comment obtenir le fichier de clés à partir de clé usb en Java
J'ai un SafeNet 5100 eToken déjà avec un certificat valide en elle que j'utilise pour accéder à une application web de mon entreprise qui l'exige (multi-factor authentication).
Je suis de la création d'une application de bureau pour accéder à ce site web. Je suis déjà en mesure d'ajouter le site web du certificat de l' TrustStore
et d'obtenir mon certificat dans un KeyStore
.
Ce que j'ai obtenu jusqu'à présent est:
System.setProperty("javax.net.ssl.trustStore", "U:\\Certificados\\efau.truestore");
System.setProperty("javax.net.ssl.trustStoreType", "jks");
System.setProperty("javax.net.ssl.trustStorePassword", "oiadad");
KeyManagerFactory kFac;
SSLContext sslContext;
SSLSocketFactory sockFactory = null;
KeyStore ks;
try {
//load keystore present in windows and print aliases found (only one, so nextElement always prints same information (name of certificate inside usb token I want to open))
ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
ks.load(null, null);
System.out.println(ks.aliases().nextElement());
System.out.println(ks.aliases().nextElement());
//try to load my certificate specifically from all certificates and passes necessary token password to it
InputStream in = IOUtils.toInputStream(ks.aliases().nextElement(), "UTF-8");
System.out.println(in);
ks.load(in, password);
//print certificate to check if I have it
System.out.println(ks.getCertificate(ks.aliases().nextElement()));
//get ssl context and key manager factory
sslContext = SSLContext.getInstance("SSL", "SunJSSE");
kFac = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kFac.init(ks,null);
sslContext.init(kFac.getKeyManagers(), null, null);
sockFactory = sslContext.getSocketFactory();
//start connection with website
HttpsURLConnection conn = (HttpsURLConnection)new URL(<my-https-url>).openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setSSLSocketFactory(sockFactory);
int responseCode = conn.getResponseCode();
System.out.println("RESPONSE: " + responseCode);
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e1) {
e1.printStackTrace();
} catch (KeyManagementException e1) {
e1.printStackTrace();
}
Lorsque j'exécute ce code j'obtiens:
javax.net.ssl.SSLHandshakeException: Received fatal alert: decrypt_error
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.net.HttpURLConnection.getResponseCode(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
at receita.system.monitoring.Ping.main(Ping.java:313)
Et j'ai cette erreur lorsque je tape le mot de passe correct pour le jeton et quand je tape un mauvais, donc je pense que je ne suis jamais en lui passant le mot de passe dans le bon sens.
Pourquoi reçois-je une exception?
--------- Mise à jour ---------
J'ai créé un fichier de config avec les informations suivantes pointant vers mon PKCS11.dll bibliothèque:
name = Aladdin
library = C:/WINDOWS/system32/eTPKCS11.dll
Et dans la fonction principale-je ajouter:
SunPKCS11 newProvider = new SunPKCS11("u:/Certificados/etpkcs11.cfg");
Provider a = newProvider;
Security.addProvider(a);
KeyStore ks;
try {
ks = KeyStore.getInstance("PKCS11");
...
}
Et maintenant j'ai ceci comme erreur:
java.security.KeyStoreException: PKCS11 not found
at java.security.KeyStore.getInstance(Unknown Source)
at receita.system.monitoring.Ping.main(Ping.java:292)
Caused by: java.security.NoSuchAlgorithmException: PKCS11 KeyStore not available
at sun.security.jca.GetInstance.getInstance(Unknown Source)
at java.security.Security.getImpl(Unknown Source)
... 2 more
J'ai aussi essayé de modifier le fichier de clés.getInstance:
ks = KeyStore.getInstance("PKCS11", a);
et puis, j'obtiens cette erreur:
java.security.KeyStoreException: PKCS11 not found
at java.security.KeyStore.getInstance(Unknown Source)
at receita.system.monitoring.Ping.main(Ping.java:292)
Caused by: java.security.NoSuchAlgorithmException: no such algorithm: PKCS11 for provider SunPKCS11-Aladdin
at sun.security.jca.GetInstance.getService(Unknown Source)
at sun.security.jca.GetInstance.getInstance(Unknown Source)
at java.security.Security.getImpl(Unknown Source)
... 2 more
--------- Mise À Jour 2 (Code De Travail) ---------
Mon dernier code de travail est:
System.setProperty("javax.net.ssl.trustStore", "U:\\Certificados\\efau.truestore");
System.setProperty("javax.net.ssl.trustStoreType", "jks");
System.setProperty("javax.net.ssl.trustStorePassword", "oiadad");
KeyManagerFactory kFac;
SSLContext sslContext;
SSLSocketFactory sockFactory = null;
SunPKCS11 providerMSCAPI = new SunPKCS11("u:/Certificados/etpkcs11.cfg");
Provider a = providerMSCAPI;
Security.addProvider(a);
KeyStore ks;
try {
ks = KeyStore.getInstance("PKCS11");
ks.load(null, password);
InputStream in = IOUtils.toInputStream(ks.aliases().nextElement(), "UTF-8");
ks.load(in, password);
sslContext = SSLContext.getInstance("SSL", "SunJSSE");
kFac = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kFac.init(ks,null);
sslContext.init(kFac.getKeyManagers(), null, null);
sockFactory = sslContext.getSocketFactory();
HttpsURLConnection conn = (HttpsURLConnection)new URL(/*<my-url>*/).openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setSSLSocketFactory(sockFactory);
int responseCode = conn.getResponseCode();
InputStream inputstream = conn.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
String line = null;
String htmlResponse = "";
while ((line = bufferedreader.readLine()) != null) {
htmlResponse += line + "\n";
}
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e1) {
e1.printStackTrace();
} catch (KeyManagementException e1) {
e1.printStackTrace();
}
Et je ou définir le débogage argument dans exécuter les configurations:
-Djava.security.debug=sunpkcs11
Ou de l'ensemble de la fente dans le .fichier cfg:
name=SafeNet
library=C:\Windows\System32\eTPKCS11.dll
slot=4
Je ne sais pas, comment puis-je vérifier? Dans SafeNet eToken 5100 je vois: API & support des standards PKCS#11 V2.20, Microsoft CAPI, PC/SC, X. 509 v3 de stockage des certificats SSL v3, IPsec/IKE identifiant informatique (CCID) 1.0
eh bien, il n'y a PKCS#11 mentionné, donc oui. Vérifier quelque chose comme
cryptoki.dll
ou similaire.
OriginalL'auteur t.pimentel | 2014-05-14
Vous devez vous connecter pour publier un commentaire.
La SunMSCAPI mise en œuvre n'est pas parfait (par exemple, si vous avez des certificats avec le même "nom convivial", certaines sont inaccessibles, car il est également l'unique clé utilisée pour le fichier de clés alias). Je ne suis pas sûr de la façon dont il fonctionne avec des jetons matériels.
Depuis votre jeton semble soutenir PKCS#11, vous pourriez aussi bien faire usage de l'Oracle JRE la prise en charge directe pour
PKCS11
fichier de stockage des clés.Essentiellement, votre jeton pilote devrait venir avec une DLL de la mise en œuvre de l'interface PKCS#11, et vous avez besoin de point de Java (comme décrit dans le PKCS#11 du guide). Pour plus de flexibilité, il peut être plus pratique d'installer le fournisseur de manière dynamique (voir le paragraphe qui commence par "Pour installer le fournisseur de manière dynamique, [...]".
Suite à vos commentaires, vous pourriez peut-être utiliser la méthode d'essai et d'erreur (par la capture de ces exceptions) pour trouver l'emplacement de droite. Au lieu d'utiliser un fichier de configuration, vous pouvez charger la configuration à partir d'une chaîne.
Si vous ajoutez
"slot=...\n"
à la chaîne de configuration et l'utilisation d'une boucle pour essayer différentes valeurs jusqu'à ce qu'il cesse de lancer des exceptions, il pourrait fonctionner. Vous devrez peut-être supprimer les prestataires de services de sécurité où il a échoué, ou de changer le nom. (Je ne dis pas que c'est une méthode propre à le faire.)Par ailleurs, si vous ne voulez pas dur de votre mot de passe (bien sûr!) ou de le charger à partir d'un fichier de configuration, vous pouvez utiliser un callback virage comme ceci:
Votre gestionnaire de rappel pourrait être "
new com.sun.security.auth.callback.DialogCallbackHandler()
". Je ne conseillons généralement à l'aide de toute lacom.sun.*
ousun.*
des paquets car ils ne font pas partie du public de l'API Java, mais vous êtes en utilisantsun.security.pkcs11.SunPKCS11
ici, de sorte que votre code ne sera liée à cette famille de Jre de toute façon.Il semble que votre DLL n'était pas chargé correctement. Vous pourriez peut-être essayer avec un autre morceau de logiciel pour voir si ça marche (Firefox et Thunberbird également en charge PKCS#11). Il est également possible que votre DLL est en 32 bits et que vous utilisez une JVM 64 bits (dans ce cas, FF pourrait fonctionner si c'est 32 bits aussi). À l'aide de
-Djava.security.debug=sunpkcs11
peut aussi vous donner plus de détails. Vous pouvez aussi avoir besoin de spécifier un "slot" dans votre configuration.Merci beaucoup @Bruno, j'avais essayé pointant vers le fichier cfg pour slot=0 à 3, et cela n'avait pas fonctionné, la mienne était en
slot=4
. Lorsque j'ai utilisé-Djava.security.debug=sunpkcs11
il a trouvé dans le premier essai. Maintenant, je dois garder ou le-Djava.security.debug=sunpkcs11
ou spécifier leslot=4
. Savez-vous si il y a de toute façon d'automatiser le logement à trouver si je n'ai pas à spécifier un logement et n'ont pas besoin de garder de l'indicateur de débogage? (Je vais mettre à jour ma réponse avec la version finale du code de travail et .fichier cfg)Je viens de remarquer cette réponse à une autre question, qui peut être utile.
OriginalL'auteur Bruno
Essayer le code ci-dessous pour obtenir le fichier de clés à partir de clé usb à l'aide de java
class Test {
public static void main(String args[]) throws IOException, GeneralSecurityException, DocumentException, CertificateVerificationException{
//Créer une instance de SunPKCS11 fournisseur de
OriginalL'auteur ARAVIND