В Java, какой самый простой способ создать SSLContext только с файлом PEM? - PullRequest
0 голосов
/ 25 апреля 2018

Я использовал CertBot LetsEncrypt для генерации файлов PEM бесплатно.На других языках легко запустить HTTPS-сервер, используя всего пару строк кода и файлы PEM / key.Решения, которые я нашел до сих пор в Java, слишком сложны, и я ищу что-то более простое.

  1. Я не хочу использовать командную строку Java "keytool".Я просто хочу перетащить мои файлы PEM / key в мое затмение и программно запустить HTTPS-сервер, используя SSLContext.
  2. Я не хочу включать массивные внешние библиотеки, такие как BouncyCastle.См. Следующую ссылку для предполагаемого решения с использованием BouncyCastle: Как создать SSLSocketFactory из сертификата PEM и ключа без преобразования в хранилище ключей?

Есть ли лучший / более простой способ сделатьэто?

Ответы [ 2 ]

0 голосов
/ 02 мая 2018
  • Это временное решение, потому что приведенный ниже код позволяет вам принять любой сервер, поэтому вам следует тщательно проверять код, когда вы пробуете решения такого типа.

  • Этот код вообще не нуждается в сертификате.

  • Вопрос заключается в том, почему вы пытаетесь избежать этого процесса, если запрашиваемое дело не использует небезопасный сервер?


logger.info("Starting instance ");
        TrustManager[] tm = new TrustManager[]{new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers(){return new X509Certificate[]{};}
            public void checkClientTrusted(X509Certificate[] chain, String authType) {logger.info(" checkClientTrusted");}
            public void checkServerTrusted(X509Certificate[] chain, String authType) {logger.info(" checkServerTrusted");}

        }};

        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, tm , new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
0 голосов
/ 01 мая 2018

Следующий код в целом показывает, как создать SSLContext для HTTPS-сервера путем анализа файла PEM, который имеет несколько записей, например, несколько сертификатов и один RSA PRIVATE KEY.Однако он неполон, поскольку обычная Java 8 не может проанализировать данные закрытого ключа RSA PKCS # 1.Поэтому кажется, что ваше желание сделать это без какой-либо библиотеки невозможно.Требуется как минимум BouncyCastle для анализа данных PKCS # 1 (а затем можно использовать PEM-анализатор BouncyCastle).

private SSLContext createSslContext() throws Exception {
    URL url = getClass().getResource("/a.pem");
    InputStream in = url.openStream();
    String pem = new String(in.readAllBytes(), StandardCharsets.UTF_8);
    Pattern parse = Pattern.compile("(?m)(?s)^---*BEGIN ([^-]+)---*$([^-]+)^---*END[^-]+-+$");
    Matcher m = parse.matcher(pem);
    CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
    Decoder decoder = Base64.getMimeDecoder();
    List<Certificate> certList = new ArrayList<>(); // java.security.cert.Certificate

    PrivateKey privateKey = null;

    int start = 0;
    while (m.find(start)) {
        String type = m.group(1);
        String base64Data = m.group(2);
        byte[] data = decoder.decode(base64Data);
        start += m.group(0).length();
        type = type.toUpperCase();
        if (type.contains("CERTIFICATE")) {
            Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(data));
            certList.add(cert);
        } else if (type.contains("RSA PRIVATE KEY")) {
            // TODO: load and parse PKCS1 data structure to get the RSA private key  
            privateKey = ...
        } else {
            System.err.println("Unsupported type: " + type);
        }

    }
    if (privateKey == null)
        throw new RuntimeException("RSA private key not found in PEM file");

    char[] keyStorePassword = new char[0];

    KeyStore keyStore = KeyStore.getInstance("JKS");
    keyStore.load(null, null);

    int count = 0;
    for (Certificate cert : certList) {
        keyStore.setCertificateEntry("cert" + count, cert);
        count++;
    }
    Certificate[] chain = certList.toArray(new Certificate[certList.size()]);
    keyStore.setKeyEntry("key", privateKey, keyStorePassword, chain);

    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(keyStore);
    KeyManagerFactory kmf = KeyManagerFactory.getInstance("RSA");
    kmf.init(keyStore, keyStorePassword);
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
    return sslContext;
}
...