TLS-соединение от Java-клиента к брокеру MosQitto MQTT - PullRequest
0 голосов
/ 11 июня 2018

Я пытаюсь установить соединение tls с москитным брокером mqtt.я генерирую ключи и сертификаты следующим образом: https://mosquitto.org/man/mosquitto-tls-7.html

, тогда вот мой код:

public class App {
    public static void main(String[] args) {
        String serverUrl = "ssl://129.6.60.24:8883";
        String caFilePath = "./src/main/resources/ca.crt";
        String clientCrtFilePath = "./src/main/resources/brokerCertificate.crt";
        String clientKeyFilePath = "./src/main/resources/ca.key";
        String mqttUserName = "cpcc";
        String mqttPassword = "1qaz!QAZ1qaz";
        MqttClient client;

        try {
            client = new MqttClient(serverUrl, "TestBedBroker");
            client.setCallback(new SimpleMqttCallBack());
            MqttConnectOptions options = new MqttConnectOptions();
            options.setUserName(mqttUserName);
            options.setPassword(mqttPassword.toCharArray());
            SSLSocketFactory socketFactory = SslUtil.getSocketFactory(caFilePath, clientCrtFilePath, clientKeyFilePath, "1qaz!QAZ1qaz");
            options.setSocketFactory(socketFactory);
            System.out.println("starting connect the server...");
            client.connect(options);
            System.out.println("connected!");
            Thread.sleep(1000);
            client.disconnect();
            System.out.println("disconnected!");

        }
        catch (MqttException e) {
            e.printStackTrace();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

}

public class SslUtil {
    public static SSLSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, final String keyFile, final String password) throws Exception {
        Security.addProvider(new BouncyCastleProvider());

        // load CA certificate
        X509Certificate caCert = null;

        FileInputStream fis = new FileInputStream(caCrtFile);
        BufferedInputStream bis = new BufferedInputStream(fis);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        while (bis.available() > 0) {
            caCert = (X509Certificate) cf.generateCertificate(bis);
            // System.out.println(caCert.toString());
        }

        // load client certificate
        bis = new BufferedInputStream(new FileInputStream(crtFile));
        X509Certificate cert = null;
        while (bis.available() > 0) {
            cert = (X509Certificate) cf.generateCertificate(bis);
            // System.out.println(caCert.toString());
        }

        // load client private key
        PEMParser pemParser = new PEMParser(new FileReader(keyFile));
        Object object = pemParser.readObject();
        PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
        KeyPair key;
        if (object instanceof PEMEncryptedKeyPair) {
            System.out.println("Encrypted key - we will use provided password");
            key = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
        } else {
            System.out.println("Unencrypted key - no password needed");
            key = converter.getKeyPair((PEMKeyPair) object);
        }
        pemParser.close();

        // CA certificate is used to authenticate server
        KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
        caKs.load(null, null);
        caKs.setCertificateEntry("ca-certificate", caCert);
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
        tmf.init(caKs);

        // client key and certificates are sent to server so it can authenticate
        // us
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(null, null);
        ks.setCertificateEntry("certificate", cert);
        ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[] { cert });
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, password.toCharArray());

        // finally, create SSL socket factory
        SSLContext context = SSLContext.getInstance("TLSv1.2");
        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        return context.getSocketFactory();
    }
}

, но когда я запускаю свою программу, у меня есть:

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

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

...