当前位置: 首页 > 知识库问答 >
问题:

java中MQTT的TLS/SSL连接

施飞雨
2023-03-14

我正在研究MQTT协议。我配置了它的服务器,并使用端口1883上的Mosquito库用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.how可以在java代码中生成这些证书?

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

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

共有2个答案

云浩然
2023-03-14
    //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);
            }
    }
年嘉禧
2023-03-14

好的,我想您没有理解证书身份验证是如何工作的。

它有两个部分(证明经纪人是它所说的人,然后证明连接的客户是谁)

首先,代理将拥有1个向世界标识它的证书。您将蚊子配置为在启动时使用此证书,并且无需更改它。此证书将由CA签名。

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

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

至于用java创建证书,我建议您看看这个问题

当您发出新证书时,无需重新启动蚊子。

 类似资料:
  • 我需要帮助,因为我对Kafka和mqtt一无所知。我正在使用docker compose创建Mosquitto broker和Kakfa之间通信的架构 我还使用confluent Kafka Connect MQTT(https://www.confluent.io/hub/confluentinc/kafka-connect-mqtt) 它对于1883端口上的通信工作得很好,但当我尝试在8883

  • 我正试图通过MQTT发布服务器发布事件。在提供程序URL中提到了tls://URL:port 当我试图执行时,它会给出以下错误:。我使用的是apache jmeter 5.0和MQTT jar版本:mqtt-jmeter-0.0.1-snapshot java.lang.IllegalArgumentException:tls://...:1887 at org.eclipse.paho.clie

  • 我无法通过TLS/SSL(FTPS)服务器连接到FTP。我正在使用SimpleFTP库,通过我可以连接没有SSL的FTP服务器,但不能连接FTPS。 它在第2行(ftp.connect)给出了这个错误, SimpleFTP连接到FTP服务器时收到未知响应: 220---------欢迎使用Pure-FTPd[privsep][TLS]--------- 并且正在使用下面的代码

  • 0个 我正在尝试从Java连接到邮件服务器。我已经能够使用相同的代码成功地从Java连接到许多邮件服务器,包括Gmail、Rackspace、GoDaddy和其他,但是无论我尝试什么设置,这个都不起作用。 此操作失败,javax.mail.MessaginException:无法将套接字转换为TLS;嵌套异常为:javax.net.ssl.SSLException:无法识别的ssl消息,纯文本连接

  • 我试图理解Retheart文档的这部分内容,但无法理解:https://softinstigate.atlassian.net/wiki/spaces/rh/pages/9207828/installation+and+setup#installationandsetup-5.1connectreshearttomongodbovertls/ssl 使用keytool创建导入mongod使用的公共

  • 问题内容: 我试图使用JDK 1.8和MySQL Connector / J版本5.1.23安全地连接到Amazon RDS,并且对MySQL Connector / J文档中 的说明感到困惑。 说明说明要在当前目录中创建信任库并导入服务器的CA证书。当我运行以下命令时,系统会要求我输入密码,但我不知道输入什么: 另一方面,Amazon的说明指出证书由证书颁发机构签名。SSL证书包括数据库实例终结