org.thingsboard.gateway.extensions.mqtt.client.conf.credentials.CertPemClientCredentials.java Source code

Java tutorial

Introduction

Here is the source code for org.thingsboard.gateway.extensions.mqtt.client.conf.credentials.CertPemClientCredentials.java

Source

/**
 * Copyright  2017 The Thingsboard Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.thingsboard.gateway.extensions.mqtt.client.conf.credentials;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.util.StringUtils;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileReader;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;

@Data
@Slf4j
public class CertPemClientCredentials implements MqttClientCredentials {

    private static final String TLS_VERSION = "TLSv1.2";
    private final JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter()
            .setProvider("BC");

    private String caCert;
    private String privateKey;
    private String cert;
    private String password;

    @Override
    public void configure(MqttConnectOptions clientOptions) {
        clientOptions.setSocketFactory(getSocketFactory());
    }

    private SSLSocketFactory getSocketFactory() {
        try {
            Security.addProvider(new BouncyCastleProvider());

            TrustManagerFactory trustManagerFactory = createAndInitTrustManagerFactory();
            KeyManagerFactory keyManagerFactory = createAndInitKeyManagerFactory();

            SSLContext context = SSLContext.getInstance(TLS_VERSION);
            context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);

            return context.getSocketFactory();
        } catch (Exception e) {
            log.error("[{}:{}:{}:{}] Creating TLS factory failed!", caCert, cert, privateKey, password, e);
            throw new RuntimeException("Creating TLS factory failed!", e);
        }
    }

    private KeyManagerFactory createAndInitKeyManagerFactory() throws Exception {
        X509Certificate certHolder = certificateConverter.getCertificate((X509CertificateHolder) readPEMFile(cert));

        Object keyObject = readPEMFile(privateKey);

        char[] passwordCharArray = "".toCharArray();
        if (!StringUtils.isEmpty(password)) {
            passwordCharArray = password.toCharArray();
        }

        JcaPEMKeyConverter keyConverter = new JcaPEMKeyConverter().setProvider("BC");

        KeyPair key;
        if (keyObject instanceof PEMEncryptedKeyPair) {
            PEMDecryptorProvider provider = new JcePEMDecryptorProviderBuilder().build(passwordCharArray);
            key = keyConverter.getKeyPair(((PEMEncryptedKeyPair) keyObject).decryptKeyPair(provider));
        } else {
            key = keyConverter.getKeyPair((PEMKeyPair) keyObject);
        }

        KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        clientKeyStore.load(null, null);
        clientKeyStore.setCertificateEntry("cert", certHolder);
        clientKeyStore.setKeyEntry("private-key", key.getPrivate(), passwordCharArray,
                new Certificate[] { certHolder });

        KeyManagerFactory keyManagerFactory = KeyManagerFactory
                .getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(clientKeyStore, passwordCharArray);
        return keyManagerFactory;
    }

    private TrustManagerFactory createAndInitTrustManagerFactory() throws Exception {
        X509Certificate caCertHolder = certificateConverter
                .getCertificate((X509CertificateHolder) readPEMFile(caCert));

        KeyStore caKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        caKeyStore.load(null, null);
        caKeyStore.setCertificateEntry("caCert-cert", caCertHolder);

        TrustManagerFactory trustManagerFactory = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(caKeyStore);
        return trustManagerFactory;
    }

    private Object readPEMFile(String filePath) throws Exception {
        PEMParser reader = new PEMParser(new FileReader(filePath));
        Object fileHolder = reader.readObject();
        reader.close();
        return fileHolder;
    }
}