ibm-watson-iot / iot-java

Client libraries and samples for connecting to IBM Watson IoT using Java
https://internetofthings.ibmcloud.com
Eclipse Public License 1.0
54 stars 82 forks source link

Porting SSL library for android #135

Closed mbsysd00 closed 5 years ago

mbsysd00 commented 6 years ago

I followed the instructions to create a client certificate here and use them to authenticate android smartwatches to connect to the Watson IoT Platform.

Problem in here. How to porting SSL of AbstractClient.java to support android? I changed the KeyStore.getInstance ("JKS") to KeyStore.getInstance ("BKS") but I got an error log on server like this "Invalid userID () for auth device: ClientID = 'd: v718vj: M1: 1', ClientIP = 202.67 .XX.XXX "

    `static SSLSocketFactory getSocketFactory (final String caCrtFile, final String crtFile, 
        final String keyFile, final String password) throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException { 
    Security.addProvider(new BouncyCastleProvider());
    X509Certificate caCert = null;

    if(caCrtFile != null) {
        // load CA certificate
        PEMReader reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(caCrtFile)))));
        caCert = (X509Certificate)reader.readObject();
        reader.close();
    } else {
         ClassLoader classLoader = AbstractClient.class.getClassLoader();
         PEMReader reader = new PEMReader(new InputStreamReader(classLoader.getResource(SERVER_MESSAGING_PEM).openStream()));
            caCert = (X509Certificate)reader.readObject();
            reader.close();
    }

    PEMReader reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(crtFile)))));
    X509Certificate cert = (X509Certificate)reader.readObject();
    reader.close();

    // load client private key
    reader = new PEMReader(
            new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(keyFile))))
    );
    KeyPair key = (KeyPair)reader.readObject();
    reader.close();

    TrustManagerFactory tmf = null;
    if(caCert != null) {
        // CA certificate is used to authenticate server
        KeyStore caKs = KeyStore.getInstance("JKS"); // PROBLEM IN HERE
        //caKs.load(null, null);
        caKs.load(null, null);
        caKs.setCertificateEntry("ca-certificate", caCert);
        tmf = TrustManagerFactory.getInstance("PKIX");
        tmf.init(caKs);
    } 
    // client key and certificates are sent to server so it can authenticate us
    KeyStore ks = KeyStore.getInstance("JKS");  // PROBLEM IN HERE
    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("PKIX");
    kmf.init(ks, password.toCharArray());

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

    return context.getSocketFactory();
}`
miketran78727 commented 5 years ago

We will have a new property (Keystore-Type). Default is JKS if not specified. On Android devices, the keystore type is usually BKS. So, the user will set Keystore-Type = BKS

icraggs commented 5 years ago

Do we need a new configuration type, or can we infer it from the environment?

miketran78727 commented 5 years ago

Some Android devices may have PKCS12 as keystore type. So, get use Keystore.getDefaultType() we may get a correct answer. Not sure if we can rely on getDefaultType().

miketran78727 commented 5 years ago

I have found an example for creating BKS keystore for Android platform : https://docs.wso2.com/display/EMM200/Generating+a+BKS+File+for+Android

For my tests

I created 2 BKS files.

Tests:

Properties:

miketran78727 commented 5 years ago

The fix is now in master branch. It will be available in the next release.