Внедрить диспетчер хранилища доверенных сертификатов на сервере для проверки одноранговых сертификатов X509 - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть двухсторонняя реализация SSL между несколькими клиентами и серверами, работающими на spring-boot. В хранилище доверенных сертификатов сервера я добавляю доменные сертификаты для клиента, поскольку у нас есть клиенты с аналогичными промежуточными и корневыми сертификатами, и мы хотим только аутентифицировать клиентов, чьи доменные сертификаты присутствуют в нашем хранилище доверенных сертификатов, или возвращать исключение (я знаю, что реализация SSL для проверки подлинности, и об этом следует позаботиться в части авторизации, но это является обязательным условием :(). Я хочу настроить реализацию хранилища доверенных сертификатов для проверки наличия сертификата домена, а не всей цепочки, если клиент отправляет только сертификат домена, в то же время проверяя Все остальные проверки выполняются как есть через реализацию хранилища доверенных сертификатов по умолчанию. Для этого я реализовал свой собственный TrustManager и перенес часть другой проверки в реализацию TrustStoreManager по умолчанию.

       char [] password = new String("abcde").toCharArray();
       String keyFilename = "some-path/server-truststore.jks";
       static Map<String,String> map = new HashMap<>();

       KeyStore trustStore= null;
       try {
           trustStore = KeyStore.getInstance("JKS");
       } catch (KeyStoreException e) {
           e.printStackTrace();
       }
       try {
           trustStore.load(new FileInputStream(keyFilename), password);
       } catch (IOException e) {
           e.printStackTrace();
       } catch (CertificateException e) {
           e.printStackTrace();
       }

       try {
            Enumeration<String> trustStoreEnum= trustStore.aliases();
            while(trustStoreEnum.hasMoreElements()){
                String nextElement= trustStoreEnum.nextElement();
                X509Certificate certificate = (X509Certificate)trustStore.getCertificate(nextElement);
                String key=certificate.getSubjectDN().getName().trim();
                map.put(key,certificate.getSerialNumber().toString());

            }


        } catch (KeyStoreException e) {
            e.printStackTrace();
        }

       TrustManagerFactory tmf = TrustManagerFactory
               .getInstance(TrustManagerFactory.getDefaultAlgorithm());

       try {
           tmf.init(trustStore);
       } catch (KeyStoreException e) {
           e.printStackTrace();
       }


       X509TrustManager x509Tm = null;

       for(TrustManager tm :tmf.getTrustManagers()){
           logger.info(tm.toString());
           x509Tm = (X509TrustManager) tm;
           break;
       }


       //Truststrore Manager implementation
       final X509TrustManager finalTm = x509Tm;

       TrustManager[] x509ExtendedTrustManager = new TrustManager[] {
               new X509TrustManager() {
                   @Override
                   public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                       return finalTm.getAcceptedIssuers();
                   }
                   @Override
                   public void checkClientTrusted(
                           java.security.cert.X509Certificate[] certs, String authType) throws CertificateException {
                       logger.info("client blah");
                       finalTm.checkClientTrusted(certs,authType);
                        for(X509Certificate x509Certificate: certs){
                            String certName=x509Certificate.getSubjectDN().getName().trim();
                            if(!(map.containsKey(certName) && map.get(certName).equals(x509Certificate.getSerialNumber().toString())))
                                throw new CertificateException("Certificate not present in truststore");

                        }


                   }
                   @Override
                   public void checkServerTrusted(
                           java.security.cert.X509Certificate[] certs, String authType) throws CertificateException {
                       logger.info("server blah");
                       finalTm.checkServerTrusted(certs, authType);

                   }

                   }

               };

Проблема в том, что эта реализация никогда не вызывается, хотя я установил ее в своем SSLContext на сервере, и вместо этого используется реализация менеджера склада доверенных сертификатов по умолчанию.

        try {

            SSLContext sc = SSLContext.getInstance("TLS");
            char [] password2 =
                    new String("changeit").toCharArray();
            String keyFilename2 = "/<some-path>/server-keystore.jks";

            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(new FileInputStream(keyFilename2), password2);

            KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
            kmf.init(ks, "changeit".toCharArray());

            KeyManager[] kms = kmf.getKeyManagers();

            sc.init(kms, x509ExtendedTrustManager, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            SSLContext.setDefault(sc);

        } catch (GeneralSecurityException e) {
            logger.error(e.getMessage());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


        logger.info("SSL context set");


    }

Я не уверен, так ли это, потому что мы не можем установить SSLContext для порта, который уже был инициализирован. Я хотел бы знать, есть ли лучший способ сделать это или мы можем инициализировать SSLContext на том же порту?

Заранее спасибо!

...