繁体   English   中英

AWS IOT 在 Android 中即时注册证书

[英]AWS IOT Just-in-Time Registration of Certificate in Android

我正在按照这篇文章整合 JITR。

https://aws.amazon.com/blogs/iot/just-in-time-registration-of-device-certificates-on-aws-iot/

我完成了所有这些步骤,并且能够通过命令行“mosquitto_pub”验证证书。

第一次运行“mosquitto_pub”命令时,它调用 lambda 函数对其进行授权并附加策略,第二次它成功地将消息发布到 IOT。

这是我正在使用的命令。

mosquitto_pub --cafile ../root.cert --cert hassanAndCACert.crt --key hassan.key -h <###>.iot.us-east-1.amazonaws.com
-p 8883 -q 1 -t  topic5 -i  123456789 --tls-version tlsv1.2 -m '{"hello":"3"}' -d

但是,当我尝试在 android SDK 中对此进行身份验证时,出现“握手”失败错误。 这是我得到的例外。

MqttException (0) - javax.net.ssl.SSLHandshakeException:握手在 org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38)at org.eclipse.paho.client.mqttv3.internal 失败。 ClientComms$ConnectBG.run(ClientComms.java:664)at java.lang.Thread.run(Thread.java:818)Caused by: javax.net.ssl.SSLHandshakeException: Handshake failedat com.android.org.conscrypt.OpenSSLSocketImpl。开始握手(OpenSSLSocketImpl.java:441)在 org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:93)在 org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run( ClientComms.java:650)... 1 moreCaused by: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0xb91e9b40: Failure in SSL library, usually a protocol errorerror:100c5416:SSL routines:ssl3_read_bytes:SSLV3_ALERT_CERTIFICATE_UNKNOWN (外部/ boringssl/src/ssl/s3_pkt.c:972 0xb9215530:0x00000001)at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(本地方法)a t com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:353)

有趣的是,如果设备证书已经激活并且我们尝试通过 android 发布消息,它就会成功发布。 唯一的问题是在第一次调用时验证证书。 如果我的代码有问题,它不应该发送针对激活证书的消息。

我在 mosquitto 调用和 android 代码之间看到的区别是 mosquitto 正在执行一个命令来连接和发布消息,而 AWS SDK 中的 PAHO-MQTT 需要在发布之前先连接,我在“连接”中遇到异常'. 我什至没有在 AWS 日志中得到任何日志。

可能的原因

SSL/TLS 握手可能因各种原因而失败,而不仅仅是证书验证问题。

它可能是为了:

  • 不共享相同的密码套件
  • 不共享 SSL 版本
  • 证书验证
  • 意图更改 TLS 版本
  • 其他问题

找出问题所在的最佳方法是安装Wireshark并查看握手消息。 然后根据从服务器发送到客户端的 SSL 警报消息,您可以获得有关 SSL 握手失败的更多信息,具体发生在何处。

可能的解决方案

有用的资源

制作您自己的 KeyStoreHelper 将 CA 证书放入您的 KeyStore,并使用它代替 AWS IoT SDK 的KeyStoreHelper

注意:我在下面的代码中省略了所有异常处理,createKeyPair()、createCSR()、parsePemObject() 和 signCSR() 是我的方法。

public class MyKeystoreHelper {

    public KeyStore createKeystoreJIT(String certId, String keystorePath,
        String keystoreName, String keystorePassword, HashMap<String, String> directory) {

        // Generate KeyPair
        KeyPair key = createKeyPair();

        // Generate CSR
        PKCS10CertificationRequest csr = createCSR(key, directory);

        // Read CA Private key
        PEMKeyPair pemKey = (PEMKeyPair)parsePemObject(context, PATH_TO_CAROOT_KEY_FILE);
        KeyPair caKey = new JcaPEMKeyConverter().getKeyPair(pemKey);

        // Read CA Cert
        X509CertificateHolder pemCert = (X509CertificateHolder)parsePemObject(context, PATH_TO_CAROOT_CERT_FILE);
        X509Certificate caCert = new JcaX509CertificateConverter().getCertificate(pemCert);
        X500Name issuer = pemCert.getIssuer();

        // Generate CA Signed CSR
        X509Certificate cert = signCSR(csr, caKey.getPrivate(), caCert, issuer);

        // Create Key Store
        saveKeystore(certId, cert, caCert, key.getPrivate(), keystorePath, keystoreName, keystorePassword); // <-- HERE!! Pass CA Cert

        KeyStore keystore = getKeystore(certId, keystorePath, keystoreName, keystorePassword);
        return keystore;

    }
    ....

    private boolean saveKeystore(String certId, X509Certificate cert, X509Certificate caCert,
        PrivateKey privatekey, String keystorePath, String keystoreName, String keystorePassword) {

        KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
        File keystoreFile = new File(keystorePath, keystoreName);

        if( ! keystoreFile.exists()) {
            createKeystore(keystorePath, keystoreName, keystorePassword);
        }

        FileInputStream fis = new FileInputStream(keystoreFile);
        keystore.load(fis, keystorePassword.toCharArray());
        fis.close();

        keystore.setCertificateEntry(certId, cert);
        keystore.setKeyEntry(certId, privatekey, keystorePassword.toCharArray(), new Certificate[] { cert, caCert }); // <-- HERE!! put CA Cert

        String caCertId = certId + "_CA";
        keystore.setCertificateEntry(caCertId, caCert);
        keystore.setKeyEntry(caCertId, privatekey, keystorePassword.toCharArray(), new Certificate[] { caCert });

        String keystoreFileAndPath;

        if(keystorePath.endsWith("/")) {
            keystoreFileAndPath = keystorePath + keystoreName;
        } else {
            keystoreFileAndPath = keystorePath + "/" + keystoreName;
        }

        FileOutputStream fos = new FileOutputStream(keystoreFileAndPath);
        keystore.store(fos, keystorePassword.toCharArray());
        fos.close();

        return true;

    }
     ....

    private KeyStore getMemoryKeystore(KeyStore customerKeystore, String certId, String customerKeystorePassword) {

        KeyStore memoryKeystore = KeyStore.getInstance(KeyStore.getDefaultType());
        memoryKeystore.load(null);

        X509Certificate cert = (X509Certificate) customerKeystore.getCertificate(certId);
        memoryKeystore.setCertificateEntry("cert-alias", cert);

        Key key = customerKeystore.getKey(certId, customerKeystorePassword.toCharArray());

        String caCertId = certId + "_CA";
        X509Certificate caCert = (X509Certificate) customerKeystore.getCertificate(caCertId); // Pull CA Cert
        memoryKeystore.setCertificateEntry("cacert-alias", caCert);

        memoryKeystore.setKeyEntry("key-alias", key, AWS_IOT_INTERNAL_KEYSTORE_PASSWORD.toCharArray(), new Certificate[] { cert, caCert }); // <-- HERE!!
        return memoryKeystore;

    }
    ....    
}

在连接和发布 MQTT 之前,获取链接在 KeyStore 中的 CSR 和 CA 证书,如下所示:

keystoreHelper = new MyKeystoreHelper(...);

if(keystoreHelper.isKeystorePresent(keystorePath, KEYSTORE_NAME)) {
    keystore = keystoreHelper.getKeystore(CERTIFICATE_ID, keystorePath, KEYSTORE_NAME, KEYSTORE_PASSWORD);
} else {
    // Create your own KeyStroe if it is not exist yet.
    HashMap<String, String> directory = getDirectory(); // X.500 directory items for CSR
    keystoreHelper.createKeystoreJIT(CERTIFICATE_ID, keystorePath, KEYSTORE_NAME, KEYSTORE_PASSWORD, directory);
    keystore = keystoreHelper.getKeystore(CERTIFICATE_ID, keystorePath, KEYSTORE_NAME, KEYSTORE_PASSWORD);
}

一旦您首次向端点发布任何消息,AWS IoT Core 将自动创建一个“事物”。

我希望这可以帮助你。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM