【问题标题】:TLS/SSL Connection for MQTT in javajava中MQTT的TLS/SSL连接
【发布时间】:2016-05-12 06:24:53
【问题描述】:

我正在研究 MQTT 协议。我配置了它的服务器,并使用它在端口 1883 上的 mosquitto 库在 java 中执行了通信。 现在我想让这种通信安全。我知道端口 8883 是为其基于 tls 的安全通信保留的。 它需要 X.509 证书。 为此,我找到了以下教程。

http://www.embedded101.com/Blogs/PaoloPatierno/entryid/366/mqtt-over-ssl-tls-with-the-m2mqtt-library-and-the-mosquitto-broker

但我的问题是

1.如何在java代码中生成这些证书?

2.我们如何一次使用多个证书。根据上面的教程,我们可以在服务器的 mosquitto.conf 文件中一次只指定一组证书。然后我们需要重新启动服务器。(即我不想这样做。)

3.我们如何让正在运行的服务器知道这些新生成的证书。除了在服务器的 conf 文件中指定之外,还有其他方法吗?

【问题讨论】:

  • 另外,我想知道我们可以在 java 中启动任何 mqtt 代理吗?
  • 为什么要使用多个证书?
  • 如果我将多个传感器用于不同的用例,并且每个传感器与同一代理上的不同主题进行通信。

标签: java ssl mqtt iot


【解决方案1】:

好的,我想你已经错过了证书身份验证的工作原理。

它有 2 个部分(证明代理是它所说的那个人,然后证明连接的客户端是谁)

首先,经纪人将拥有 1 个向全世界识别它的证书。您将 Mosquitto 配置为在启动时使用此证书,并且永远不需要更改它。该证书将由 CA 签署。

传感器(客户端)将拥有 CA 证书的副本,当它们连接到代理时将使用该副本来确保它是它声称的身份。

其次,如果您想使用客户端证书来识别单独的传感器,那么它们每个都需要一个证书。通常,这将由与代理证书相同的 CA 签名,因此代理可以验证客户是他们声称的身份。 Mosquitto 可以设置为使用证书 (use_identity_as_username true) 中的 CN 作为连接客户端的用户名,然后您可以使用 mosquitto_auth_plugin 跟踪证书中的 CN 并应用 ACL 来控制谁可以使用什么主题。

至于在java中创建证书我建议你看看这个question

颁发新证书时无需重新启动 Mosquitto。

【讨论】:

  • 好吧!@hardillb。但是你能解释一下mosquitto_auth_plugin吗?因为我找不到在 java eclipse 项目中使用它的方法。谢谢。
  • 您在 mosquitto 中配置它,然后您可以使用 java 中的 JDBC 将新用户/ACL 条目推送到您设置的数据库中
  • 好的。但我对所有这些事情都很陌生。您可以分享一些与此相关的开发人员指南或教程吗?我会很感激你的。
  • @hardillb.here 还有几个问题。在 mosquitto_auth_plugin 中,我们定义了保存用户名和密码以进行身份​​验证的后端数据库。我们如何保存证书。因为我正在为服务器创建 X509 rootCA,为客户端创建 X509 证书。我对此感到困惑。
  • 如果您有新问题,请发布新问题
【解决方案2】:
    //add bcpkix-jdk15on-161, bcprov-jdk15on-1.52 and eclips pago-mqtt3.1 
    //lib in build path
    import java.io.*;
    import java.nio.file.*;
    import java.security.*;
    import java.security.cert.*;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import javax.net.ssl.*;
    import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
    import org.bouncycastle.jce.provider.*;
    import org.bouncycastle.openssl.*;
    import org.bouncycastle.openssl.PasswordFinder;
    import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
    import org.bouncycastle.util.io.pem.PemObject;
    import org.bouncycastle.util.io.pem.PemReader;
    import org.eclipse.paho.client.mqttv3.MqttClient;
    import org.eclipse.paho.client.mqttv3.MqttConnectOptions;

    public class SslUtil
    {

        @SuppressWarnings("deprecation")
        //It will return SSLSocketFactory
        public static SSLSocketFactory getSocketFactory (final String 
       caCrtFile, final String crtFile, final String keyFile,                                                     
                   final String password) throws Exception
        {
            try{
                Security.addProvider(new BouncyCastleProvider());

                X509Certificate caCert = 
                (X509Certificate)SslUtil.getCertificate(caCrtFile);
                X509Certificate cert = 
                (X509Certificate)SslUtil.getCertificate(crtFile);
                FileReader fileReader = new FileReader(keyFile);
                PEMParser parser = new PEMParser(fileReader);
                PEMKeyPair kp = (PEMKeyPair) parser.readObject();

                PrivateKeyInfo info = kp.getPrivateKeyInfo();

                PrivateKey rdKey = new JcaPEMKeyConverter().setProvider("BC")
                        .getPrivateKey(info);

                // 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(TrustManagerFactory.getDefaultAlgorithm());
                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", rdKey, 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");
                context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

                return context.getSocketFactory();
            }catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
       //Get MqttClient for Subscripe Pulish
        public static void mqttClient(String caCrtFile,String clientCrtFilePath,String clientKeyFilePath,String password){
            try{

            String serverUrl = "ssl://serverip:8883";
            MqttClient client = new MqttClient(serverUrl, "consumerId" , null);
//this MyCallback class extends mqtt there we have to override some function //like message arriver etc
            client.setCallback(new MyCallback());
            MqttConnectOptions options = new MqttConnectOptions();
            options.setConnectionTimeout(60);
            options.setKeepAliveInterval(60);
            options.setSocketFactory(SslUtil.getSocketFactory(caCrtFile, clientCrtFilePath, clientKeyFilePath, password));
            client.connect(options);
            client.subscribe("topic", 0);
            }catch (Exception e) {
                System.out.println("#Exception  :"+e.getMessage());
            }
        }
       //start execution
        public static void main(String[] args) throws Exception {
            String caCrtFile = "path Certification Authority";
            String clientCrtFilePath ="path for client crt file";
            String clientKeyFilePath ="path of client key";


            String password = "password while generating files";


        mqttClient(caCrtFile,clientCrtFilePath,clientKeyFilePath,password);
        //  getCertificate(caCrtFile);
        }

        //return certificate
        public static java.security.cert.X509Certificate getCertificate(String pemfile) throws Exception
        {
            java.security.cert.X509Certificate cert = null;
            try {
                FileReader fRd = new FileReader(pemfile);
                final PemReader certReader = new PemReader(fRd);
                final PemObject certAsPemObject = certReader.readPemObject();
                if (!certAsPemObject.getType().equalsIgnoreCase("CERTIFICATE")) {
                    throw new Exception("Certificate file does not contain a certificate but a " + certAsPemObject.getType());
                }
                final byte[] x509Data = certAsPemObject.getContent();
                final CertificateFactory fact = CertificateFactory.getInstance("X509");
                cert = (X509Certificate) fact.generateCertificate(new ByteArrayInputStream(x509Data));
                if (!(cert instanceof X509Certificate)) {
                    throw new Exception("Certificate file does not contain an X509 certificate");
                }

            } catch (FileNotFoundException e) {
                throw new IOException("Can't find file " + pemfile);
            }catch (Exception e) {
                System.out.println("#Exceotion :"+e.getMessage());
            }
            return cert;
        }

    //retuen keyPair Object form client key
        public KeyPair decodeKeys(byte[] privKeyBits,byte[] pubKeyBits) 
              throws InvalidKeySpecException, NoSuchAlgorithmException {
              KeyFactory keyFactory=KeyFactory.getInstance("RSA");
              PrivateKey privKey=keyFactory.generatePrivate(new 
              PKCS8EncodedKeySpec(privKeyBits));
              PublicKey pubKey=keyFactory.generatePublic(new 
              X509EncodedKeySpec(pubKeyBits));
              return new KeyPair(pubKey,privKey);
            }
    }

【讨论】:

    猜你喜欢
    • 2020-11-01
    • 2023-04-08
    • 1970-01-01
    • 2020-11-07
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 2013-07-26
    • 1970-01-01
    相关资源
    最近更新 更多