web-dev-qa-db-fra.com

Avertissement: aucun certificat approprié n'a été trouvé - poursuite sans authentification du client

L’équipe à laquelle je suis confronté rencontre le problème suivant lorsque je tente une poignée de main commune en utilisant HTTPS

main, READ: TLSv1.2 Handshake, length = 30
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA1withRSA, SHA1withDSA, SHA1withECDSA, SHA256withRSA, Unknown (hash:0x4, signature:0x2), SHA256withECDSA, SHA384withRSA, Unknown (hash:0x5, signature:0x2), SHA384withECDSA
Cert Authorities:
<Empty>
main, READ: TLSv1.2 Handshake, length = 4
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>

Ma classe Java est une suite

public class ClientCustomSSL {

    @SuppressWarnings("deprecation")
    public final static void main(String[] args) throws Exception {
        // Trust own CA and all self-signed certs
        final String CLIENT_KEYSTORE = "yourkeystore.jks";
        final String CLIENT_TRUSTSTORE = "catruststore.jks";
        final char[] KEYPASS_AND_STOREPASS_VALUE = "Hello1".toCharArray();


        System.setProperty("https.protocols", "TLSv1");

        //SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keystore, keyPassword)(YK,"Hello1".toCharArray(),"Hello1".toCharArray()).loadTrustMaterial(CA, "Hello1".toCharArray(), (TrustStrategy) new TrustSelfSignedStrategy()).build();

        KeyStore clientTrustStore = getStore(CLIENT_TRUSTSTORE, KEYPASS_AND_STOREPASS_VALUE);
        KeyStore clientKeyStore = getStore(CLIENT_KEYSTORE, KEYPASS_AND_STOREPASS_VALUE);  


        SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(clientKeyStore, "Hello1".toCharArray()).loadTrustMaterial(clientTrustStore,(TrustStrategy) new TrustSelfSignedStrategy()).build();
       CloseableHttpClient httpclient = HttpClients.custom().setSSLContext(sslContext).build();

        System.out.println("SSLCONETXT   **** " + sslContext.getProvider());
        try {

            HttpGet httpget = new HttpGet("https://myserver:10220");

            CloseableHttpResponse response = httpclient.execute(httpget);

            try {
                System.out.println("Inside TRY blcok"); 
                HttpEntity entity = response.getEntity();
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                EntityUtils.consume(entity);

            } catch (Exception e) {
                e.getMessage();
                e.printStackTrace();
            }
            finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }


    public static KeyStore getStore(final String storeFileName, final char[] password) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException 
    {
        final String Java_KEYSTORE = "jks";
        final KeyStore store = KeyStore.getInstance(Java_KEYSTORE);
        URL url = ClientCustomSSL.class.getClassLoader().getResource(storeFileName);
        String workingDir = System.getProperty("user.dir");
        System.out.println("Current working directory : " + workingDir);

        System.out.println("Value of URL *** " + url);
        InputStream inputStream = url.openStream();
        try {
            store.load(inputStream, password);
} finally {
    inputStream.close();
}

return store;
}

}

Je prépare un fichier jar et je le teste sous UNIX

Utilisation de la commande suivante Java -Djavax.net.debug = ssl -cp snSSLclientTrustWithStoreCCC.jar

J'ai suivi post pourquoi Java n'envoie-t-il pas le certificat client lors de l'établissement de la liaison SSL? et également complété toutes les étapes mentionnées par Bruno.

Je ne suis pas sûr de ce qui me manque ici. toute aide serait appréciée 

7
P.K
  1. Le client n'a pas pu trouver de certificat dans son magasin de clés signé directement ou indirectement par l'un des signataires mentionnés dans le message CertificateRequest.
  2. La raison en est que le serveur n'a spécifié aucun signataire approuvé dans ce message.
  3. Ce qui à son tour signifie que le magasin de clés de confiance du serveur est vide.
5
user207421

C’est en fait un domaine où les spécifications TLS 1.0 et TLS 1.1/1.2 diffèrent.

En particulier, le texte suivant a été ajouté à Section 7.4.4 (Demande de certificat) dans TLS 1.1 :

Si la liste certificate_authorities est vide, le client PEUT envoyer tout certificat du type ClientCertificateType approprié, sauf indication contraire est un arrangement externe contraire.

Ainsi, des autorités de certification vides signifient simplement que le client est libre d'envoyer tout certificat au serveur, ce qui peut être accepté ou non par les règles internes du serveur.

1
peak

Dans mon cas, le problème est que je passais null comme mot de passe lors du chargement de mon magasin de clés:

KeyStore keyStore = KeyStore.getInstance("PKCS12")
InputStream inputStream = new FileInputStream('/path/to/mykeystore.p12')

try {
    keyStore.load(inputStream, null); // <-- PROBLEM HERE!
}
finally {
    inputStream.close();
}

Cela n'a généré aucun message d'erreur, mais il n'a pas réussi à charger la clé du client et le certificat .

La solution était de passer le mot de passe:

keyStore.load(inputStream as InputStream, 'mypassword'.toCharArray());
0
Sam