handshake_failure и UNKNOWN_CA после импорта второго .p12 в хранилище ключей - PullRequest
1 голос
/ 18 марта 2020

Я добавил сертификат .p12 в хранилище ключей (где до сих пор не было сертификата) с

keytool -importkeystore -noprompt -v -srckeystore FIRSTCert.p12  -srcstoretype PKCS12 -srcstorepass mySrcPassword -destkeystore keyStore.p12 -deststoretype PKCS12 -deststorepass myDestPassword -destkeypass myDestPassword

Я использовал keyStore.p12 в SOAP пользовательском интерфейсе с паролем myDestPassword, и все работало

СЕЙЧАС Я импортировал второй .p12 в свой существующий KeyStore с (такими же параметрами):

 keytool -importkeystore -noprompt -v -srckeystore SECONDCert.p12  -srcstoretype PKCS12 -srcstorepass 12345 -destkeystore keyStore.p12 -deststoretype PKCS12 -deststorepass myDestPassword -destkeypass myDestPassword

Импорт работал, но после того, как я попытался сделать SOAP вызов с обновленным keyStore .p12 (тот же wsdl и адрес, что и раньше) Я получил

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Кто-нибудь знает почему?

ОБНОВЛЕНИЕ:

Я также пытался используйте это хранилище ключей в приложении Java. Поведение то же самое. Я добавляю первый сертификат -> это работает. Я добавляю второй сертификат, но получаю ошибку, но теперь моя ошибка:

Exception in thread "main" java.lang.Exception:  myService.uploadParameters call FAILED with: com.sun.xml.internal.ws.client.ClientTransportException: HTTP-Transportfehler: javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca

UPDATE2 Здесь указано содержимое моего хранилища ключей

C:\>keytool -list -keystore KeyStore.p12 -storetype PKCS12
Keystore-Kennwort eingeben:

Keystore-Typ: PKCS12
Keystore-Provider: SunJSSE

Keystore enthält 2 Einträge

muster max (btt/beat2), 23.03.2020, PrivateKeyEntry,
Zertifikat-Fingerprint (SHA1): 03:A0:3C:0F:4A:91:1A:40:2D:C3:EC:A0:23:D5:E6:44:C5:29:34:DC
client_cert_muster, 23.03.2020, PrivateKeyEntry,
Zertifikat-Fingerprint (SHA1): 06:13:A2:8A:84:E8:F9:74:50:E8:BA:D3:79:9F:FB:5F:CB:09:1E:D0

Ответы [ 2 ]

0 голосов
/ 25 марта 2020

Thx @ Дэниел много за его помощь. Я наконец нашел способ. Я не знаю, правильно ли это, но это работает. Этот ответ поможет мне. Когда я запускаю приложение, я запускаю TLS только с Truststore:

  static void initTLS(String trustStore, String trustStorePW ){
    System.setProperty("https.protocols", "TLSv1.2")
    System.setProperty("javax.net.ssl.trustStore",trustStore)
    System.setProperty("javax.net.ssl.trustStorePassword", trustStorePW)    
  }

А теперь новое: перед каждым (SOAP) вызовом я выполняю initKeyStore:

static void initKeyStore( String aliasName ){
    String keyStorePW = "abc..."
    String keyStorePath = "path/to/keyStore"

    KeyStore keystore = KeyStore.getInstance("PKCS12");
    char[] pwdArray = keyStorePW.toCharArray();
    keystore.load(new FileInputStream(keyStorePath), pwdArray);
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmf.init(keystore, keyStorePW.toCharArray());

    final X509KeyManager origKm = (X509KeyManager)kmf.getKeyManagers()[0];  
    X509KeyManager km = new X509KeyManager() {

      @Override
      public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
         return aliasName
      }

      @Override
      public X509Certificate[] getCertificateChain(String alias) {
        return origKm.getCertificateChain(alias);
      }

      @Override
      public String[] getClientAliases(String keyType, Principal[] issuers) {
        return origKm.getClientAliases(keyType, issuers)
      }

      @Override
      public String[] getServerAliases(String keyType, Principal[] issuers) {
        return origKm.getServerAliases(keyType, issuers)
      }

      @Override
      public PrivateKey getPrivateKey(String alias) {
        return origKm.getPrivateKey(alias);
      }

      @Override
      public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
        return origKm.chooseServerAlias(keyType, issuers, socket );
      }
    }

    SSLContext sslContext = SSLContext.getInstance("TLS");
    KeyManager[] kms = [km] 
    sslContext.init(kms, null, null);
    HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

Paramter aliasName позволяет мне контролировать, какой сертификат .p12 будет храниться в хранилище ключей. Я думаю, что это довольно грязно, и мне придется оптимизировать этот код. Но, наконец, это работает.

0 голосов
/ 23 марта 2020

Мне кажется, проблема в том, что вы пытаетесь поместить две пары ключей в один и тот же .p12, и клиентам обычно требуется только часть publi c пары ключей, закодированная как сертификат X509. Кажется, он запутывается в том, что делать, когда в .p12 содержится более PrivateKeyEntry записи.

Чтобы получить файл PKCS12 только с сертификатами, попробуйте следующее:

keytool -exportcert -keystore FIRSTCert.p12 -storetype PKCS12 -storepass mySrcPassword -file firstcert.cer
keytool -exportcert -keystore SECONDCert.p12 -storetype PKCS12 -storepass 12345 -file secondcert.cer
keytool -importcert -keystore keyStore.p12 -storetype PKCS12 -storepass myDestPassword -file firstcert.cer
keytool -importcert -keystore keyStore.p12 -storetype PKCS12 -storepass myDestPassword -file secondcert.cer -alias mykey2

Теперь, когда вы делаете

keytool -list -keystore keyStore.p12 -storetype PKCS12 -storepass myDestPassword 


Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 2 entries

mykey, 23 march 2020, trustedCertEntry,
Certificate fingerprint (SHA-256): 26:FB:B4:8F:42:9C:48:5E:EE:8D:35:2E:A5:1C:79:EA:23:B5:36:50:47:62:4D:BC:D1:3D:26:61:04:1C:1A:32
mykey2, 23 march 2020, trustedCertEntry,
Certificate fingerprint (SHA-256): C1:06:CA:06:F1:29:80:72:16:1F:F6:72:04:39:16:17:31:E0:7A:5B:28:BB:41:4C:77:8E:94:F1:C5:8D:70:F8

, у него должно быть 2 записи, и они должны иметь тип trustedCertEntry. Это ваше хранилище доверенных сертификатов , и это должно быть единственным доверием, которое требуется вашему клиенту для установления соединения TLS.

Никогда не перемещайте полную пару ключей сервера с машины, если вы действительно не знаете, что делаете; он должен быть известен только серверу.

...