Securing Connection Through Certificate-Based Bi-directional Authentication using OpenSSL¶
This section helps you to quickly get started with using certificate-based authentication to secure the connection between the device and the cloud with OpenSSL.
Prerequisites¶
You have already completed the steps of creating models, products, and devices by referring to Connecting Smart Devices to EnOS Cloud and Connecting Non-smart Devices to EnOS Cloud via Edge. When creating, pay attention to the following special configurations of this tutorial:
Creating an EnOS Edge Product
You need to enable Certificate-Based Authentication when you create the edge product. The default certificate validity period and maximum certificate validity period can use the default values. As shown in the figure below:

The inverter product does not need to have Certificate-Based Authentication enabled because the inverter connects to EnOS Cloud through EnOS Edge. You only need to enable the authentication for the connection between the Edge and the Cloud.
Creating an Edge Device
Create an edge device instance named Edge01_Certificate
based on the product that you just created.

In the device list, click View , and note down the device triplet (Product Key, Device Key, and Device Secret) of Edge01_Certificate, which will be used to create the certificate request file.
Creating a Sub-Device
Refer to Step 3 in Connecting Smart Devices to EnOS Cloud to create an inverter device, and configure the following values for the device:
Basic Information:
Product: Inverter_Product
Device Name: INV002
Time Zone/City: UTC+14:00
Attributes:
Inverter Type: 1:String
Capacity: 20
Step 1: Creating Certificate Signing Request (CSR) File ¶
The private key to be created is named: edge.key
. The CSR file to be created is named: edge.csr
. For detailed steps, refer to Creating your Certificate Signing Request (CSR) File
Step 2: Invoking EnOS API to Request for Certificate ¶
After the CSR file edge.csr
is created, invoke the relevant EnOS API to request for the certificate.
Add the following Maven dependency in your POM to use EnOS API:
<dependency> <groupId>com.envisioniot</groupId> <artifactId>enos-dm-api-pojo</artifactId> <version>0.2.23</version> </dependency>
Use the following code snippet to call EnOS API to apply for a certificate
import com.envision.apim.poseidon.config.PConfig;
import com.envision.apim.poseidon.core.Poseidon;
import com.envisioniot.enos.connect_service.v2_1.cert.ApplyCertificateRequest;
import com.envisioniot.enos.connect_service.v2_1.cert.ApplyCertificateResponse;
import com.envisioniot.enos.connect_service.vo.DeviceIdentifier;
import java.io.*;
import java.security.*;
import java.security.cert.CertificateException;
public class applyCert {
// ISSUE_AUTHORITY indicates the certificate type. Possible values are RSA and ECC.
public static final String ISSUE_AUTHORITY = "ECC";
// VALID_DAY indicates the validity period of the certificate.
public static final Integer VALID_DAY = 300;
/**
* Information needed for device authentication: the device key, product key of the device.
*/
public static final String DEVICE_KEY = "xIhSzeP6lh";
public static final String PRODUCT_KEY = "rHbNES3c";
/**
* The access key and secret key of an application registered on EnOS, used for calling EnOS API. You can find the keys in Application Registration on EnOS Application Portal > Developer Console.
*/
public static final String ACCESS_KEY = "2e0b21b7-1b51-46a5-b501-c3824331b8df";
public static final String SECRET_KEY = "46e715d8-3c38-4cb6-9d65-b0bdad1ffe89";
// The URL of the API gateway. You can find it in Help > Environment Information in EnOS Application Portal > Developer Console.
public static final String API_GATEWAY_URL = "https://apim-ppe1.envisioniot.com";
/**
* Organization ID. Mouse over the OU name to obtain it in EnOS Application Portal > Developer Console.
*/
public static final String ORG_ID = "o15724268424841";
/**
* The following parameters are used to save the generated files:
* SAVE_CSR_FILE_PATH: The CSR file
* SAVE_DEVICE_CERT_FILE_PATH: The certificate requested
* SAVE_ROOT_CERT_FILE_PATH: The root certificate
*/
public static final String SAVE_CSR_FILE_PATH = "edge.csr";
public static final String SAVE_DEVICE_CERT_FILE_PATH = "edge.pem";
public static final String SAVE_ROOT_CERT_FILE_PATH = "cacert.pem";
private static void applyCertToDevice() throws IOException {
// Read the generated CSR file
String certificateRequest = readFile(SAVE_CSR_FILE_PATH);
// Configure the parameter of the request to bind the certificate to the device
ApplyCertificateRequest applyCertificateRequest = createApplyCertParam(certificateRequest);
// Make a request using EnOS API
ApplyCertificateResponse certRsp =
Poseidon.config(PConfig.init().appKey(ACCESS_KEY).appSecret(SECRET_KEY).debug())
.url(API_GATEWAY_URL)
.getResponse(applyCertificateRequest, ApplyCertificateResponse.class);
// Obtain the certificate and the root certificate of the device
if (certRsp.success()) {
// Save the device certificate
saveFile(certRsp.getData().getCert(), SAVE_DEVICE_CERT_FILE_PATH);
// Save the root certificate
saveFile(certRsp.getData().getCaCert(), SAVE_ROOT_CERT_FILE_PATH);
}
}
/**
* Read CSR file
*/
private static String readFile(String path) {
try (InputStream inputStream = new FileInputStream(path);
Reader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader reader = new BufferedReader(inputStreamReader)) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
private static ApplyCertificateRequest createApplyCertParam(String certificateRequest) {
ApplyCertificateRequest applyCertificateRequest = new ApplyCertificateRequest();
applyCertificateRequest.setCsr(certificateRequest);
/*
* Make sure the value of ISSUE_AUTHORITY is consistent with the CSR certificate type.
*/
applyCertificateRequest.setIssueAuthority(ISSUE_AUTHORITY);
/*
* Make sure the validity period of the certificate is less than the maximum validity period of the device.
*/
applyCertificateRequest.setValidDay(VALID_DAY);
/*
* Device identity
*/
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
/*
* Use one of the following methods to identify a device:
* ASSET_ID
* PRODUCT_KEY + DEVICE_KEY
*/
deviceIdentifier.setKey(PRODUCT_KEY, DEVICE_KEY);
applyCertificateRequest.setDevice(deviceIdentifier);
applyCertificateRequest.setOrgId(ORG_ID);
return applyCertificateRequest;
}
public static void main(String[] args) throws NoSuchAlgorithmException, CertificateException, SignatureException, InvalidKeyException, IOException, KeyStoreException {
//Generate certificate
applyCertToDevice();
}
/*
* Save the certificate
*/
public static void saveFile(String fileContent, String filePath) throws IOException {
File fp = new File(filePath);
try (OutputStream os = new FileOutputStream(fp)) {
os.write(fileContent.getBytes());
}
}
}
Step 3: Generating JKS File for Connecting Device to EnOS Cloud¶
Run the following commands to generate the edge.jks
file with keytool, which is a built-in Java tool whose PATH is %JAVA_HOME%\bin\keytool
.
a. Checking the file¶
[root@DemoMachine cert]# ll
total 12
-rw-r--r-- 1 root root 1395 Nov 28 19:51 cacert.pem
-rw-r--r-- 1 root root 1858 Nov 28 19:51 edge.key
-rw-r--r-- 1 root root 1416 Nov 28 20:08 edge.pem
b. Exporting the certificate and private key as a .p12 file¶
[root@DemoMachine cert]# openssl pkcs12 -export -in edge.pem -inkey edge.key -out edge.p12 -name edge -CAfile cacert.pem -caname cacert
Enter pass phrase for edge.key:
Enter Export Password:
Verifying - Enter Export Password:
c. Checking the generated .p12 file¶
[root@DemoMachine cert]# ll
total 16
-rw-r--r-- 1 root root 1395 Nov 28 19:51 cacert.pem
-rw-r--r-- 1 root root 1858 Nov 28 19:51 edge.key
-rw-r--r-- 1 root root 2654 Nov 28 20:19 edge.p12
-rw-r--r-- 1 root root 1416 Nov 28 20:08 edge.pem
d. Importing the .p12 file into the keystore¶
[root@DemoMachine cert]# keytool -importkeystore -deststorepass 123456 -destkeypass 123456 -destkeystore edge.jks -srckeystore edge.p12 -srcstoretype PKCS12 -srcstorepass 123456 -alias edge
Importing keystore edge.p12 to edge.jks...
Warning:
The JKS keystore uses a proprietary format. You are recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore edge.jks -destkeystore edge.jks -deststoretype pkcs12".
e. Checking the JKS file¶
[root@DemoMachine cert]# ll
total 20
-rw-r--r-- 1 root root 1395 Nov 28 19:51 cacert.pem
-rw-r--r-- 1 root root 2356 Nov 28 20:20 edge.jks
-rw-r--r-- 1 root root 1858 Nov 28 19:51 edge.key
-rw-r--r-- 1 root root 2654 Nov 28 20:19 edge.p12
-rw-r--r-- 1 root root 1416 Nov 28 20:08 edge.pem
f. Verifying that the JSK has one trusted certificate entry¶
[root@DemoMachine cert]# keytool -list --keystore edge.jks
Enter keystore password:
Keystore type: jks
Keystore provider: SUN
Your keystore contains 1 entry
edge, Nov 28, 2018, PrivateKeyEntry,
Certificate fingerprint (SHA1): 38:16:5A:1F:1D:68:44:44:FE:56:1A:84:36:31:85:CB:14:5B:9C:5E
Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore edge.jks -destkeystore edge.jks -deststoretype pkcs12".
g. Import the cacert root certificate into the keystore¶
[root@DemoMachine cert]# keytool -import -trustcacerts -alias cacert -file cacert.pem -keystore edge.jks -storepass 123456
Owner: EMAILADDRESS=ca@eniot.io, CN=EnOS CA, OU=EnOS CA, O=EnOS, L=Shanghai, ST=Shanghai, C=CN
Issuer: EMAILADDRESS=ca@eniot.io, CN=EnOS CA, OU=EnOS CA, O=EnOS, L=Shanghai, ST=Shanghai, C=CN
Serial number: 8c54a99157c8ef28
Valid from: Mon Nov 19 18:20:27 CST 2018 until: Thu Nov 16 18:20:27 CST 2028
Certificate fingerprints:
MD5: 4E:BF:2A:53:85:1E:21:97:70:72:AD:DF:A5:79:51:3F
SHA1: 96:BC:6B:F0:15:CD:BB:03:52:12:A2:C6:C4:BD:20:69:71:4A:75:C2
SHA256: 81:B0:E3:01:D3:2B:48:E7:CF:CC:BC:07:9A:AD:49:74:EF:92:97:A1:D4:46:E2:4E:56:94:14:32:A7:09:FA:9F
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
Extensions:
#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: AE 4F F7 AF A7 19 7B 0B AE 2E 79 0F B4 7B E5 AE .O........y.....
0010: 8C F4 54 0D ..T.
]
]
#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
CA:true
PathLen:2147483647
]
#3: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: AE 4F F7 AF A7 19 7B 0B AE 2E 79 0F B4 7B E5 AE .O........y.....
0010: 8C F4 54 0D ..T.
]
]
Trust this certificate? [no]: yes
Certificate was added to keystore
Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore edge.jks -destkeystore edge.jks -deststoretype pkcs12".
h. Verify that the JKS has two trusted certificate entries¶
[root@DemoMachine cert]# keytool -list --keystore edge.jks
Enter keystore password:
Keystore type: jks
Keystore provider: SUN
Your keystore contains 2 entries
cacert, Nov 28, 2018, trustedCertEntry,
Certificate fingerprint (SHA1): 96:BC:6B:F0:15:CD:BB:03:52:12:A2:C6:C4:BD:20:69:71:4A:75:C2
edge, Nov 28, 2018, PrivateKeyEntry,
Certificate fingerprint (SHA1): 38:16:5A:1F:1D:68:44:44:FE:56:1A:84:36:31:85:CB:14:5B:9C:5E
Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore edge.jks -destkeystore edge.jks -deststoretype pkcs12".
[root@DemoMachine cert]#
Step 4: Using SDK to Connect to EnOS¶
You can use either MQTT SDK or HTTP SDK to connect.
MQTT SDK ¶
Add MQTT SDK dependency in the pom.xml file of the Java project. The version of the MQTT SDK must be 2.2.5 or later.
<dependency>
<groupId>com.envisioniot</groupId>
<artifactId>enos-mqtt</artifactId>
<version>2.2.16</version>
</dependency>
Refer to step 4 of Connecting Non-smart Devices to EnOS Cloud via Edge, but replace the “EnOS Edge Online Connection” sample code in step 4 with the following:
public static boolean IS_ECC_CONNECT = true; //The value of this parameter is false for RSA certificate and true for ECC certificate.
public static final String DEVICE_KEY = "yourDeviceKey";
public static final String PRODUCT_KEY = "yourProductKey";
public static final String DEVICE_SECRET = "yourDeviceSecret";
public static final String JKS_PASSWORD = "yourJksPassword";
public static final String JKS_FILE_NAME = "edge.jks";
public static final String SSL_CONNECT_URL = "ssl://MqttBrokerUrl:18883";
private static void connectEnos() {
DefaultProfile defaultProfile = new DefaultProfile(SSL_CONNECT_URL, PRODUCT_KEY, DEVICE_KEY,DEVICE_SECRET);
// Configure the connection
defaultProfile.setConnectionTimeout(60).setKeepAlive(180).setAutoReconnect(false)
.setSSLSecured(true)
// Configure bi-directional authentication, the JKS file and password
.setSSLJksPath(JKS_FILE_NAME, JKS_PASSWORD)
// Configure whether to use ECC certificate to connect to EnOS
.setEccConnect(IS_ECC_CONNECT);
final MqttClient mqttClient = new MqttClient(defaultProfile);
mqttClient.connect(new ConnCallback() {
@Override
public void connectComplete(boolean reconnect) {
System.out.println("connect success");
}
@Override
public void connectLost(Throwable cause) {
System.out.println("connect lost");
}
@Override
public void connectFailed(Throwable cause) {
System.out.println("onConnectFailed : " + cause);
}
});
}
HTTP SDK¶
Add the following Maven dependency to your Java project. The version of the HTTP SDK must be 0.1.9 or later.
<dependency>
<groupId>com.envisioniot</groupId>
<artifactId>enos-http</artifactId>
<version>0.2.1</version>
</dependency>
Refer to step 4 of Connecting Non-smart Devices to EnOS Cloud via Edge, but replace the “EnOS Edge Online Connection” sample code in step 4 with the following:
public class HttpBiDirectionalAuthenticate {
// EnOS HTTP Broker URL, which can be obtained from Environment Information page in EnOS Application Portal > Developer Console
// ssl port 8443
static final String BROKER_URL = "https://broker_url:8443/";
// Device credentials, which can be obtained from Device Details page in EnOS Application Portal > Developer Console
static final String PRODUCT_KEY = "productKey";
static final String DEVICE_KEY = "deviceKey";
static final String DEVICE_SECRET = "deviceSecret";
private static String jksPath = "jskPath";
private static String jksPassword = "jskPassword";
/** Ecc cert flag
* if use ECC certificate, chose true
* if use RSA certificate, chose false */
static final boolean IS_ECC_CONNECT = false;
public static void main(String[] args) throws EnvisionException {
// construct a static device credential via ProductKey, DeviceKey and DeviceSecret
StaticDeviceCredential credential = new StaticDeviceCredential(
PRODUCT_KEY, DEVICE_KEY, DEVICE_SECRET);
// construct a http connection
SessionConfiguration configuration = SessionConfiguration
.builder()
.lifetime(30_000)
.sslSecured(true)
.isEccConnect(IS_ECC_CONNECT)
.jksPath(jksPath)
.jksPassword(jksPassword)
.build();
HttpConnection connection = new HttpConnection.Builder(BROKER_URL, credential)
.sessionConfiguration(configuration)
.build();
MeasurepointPostRequest request = buildMeasurepointPostRequest();
try
{
MeasurepointPostResponse response = connection.publish(request, null);
System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(response));
} catch (EnvisionException | IOException e)
{
e.printStackTrace();
}
}
private static MeasurepointPostRequest buildMeasurepointPostRequest()
{
// Measurepoints are defined in ThingModel
return MeasurepointPostRequest.builder()
.addMeasurePoint("Int_value", 100)
.addMeasurePoint("DI_value_01", 5)
.build();
}
}
Step 5: Starting Sample Program¶
Run the code snippet in the previous step after you have replaced the original one.
Step 6: Checking Device Connection Status¶
After you run the sample program, the edge device logs in and adds sub-devices into its topology, and proxies the sub-devices to connect to the cloud. The device connection status is shown in the following figure:

Step 7: Checking Device Data¶
Go to the console, select Device Management > Device Assets, click the icon go to Device Details, open the Measurement Points tab, select a measurement point, and click the View Data icon to check the historical data records.
In the device list, find the INV001 device and click the corresponding View
icon to enter Device Details page.
Click the Measurement Point tab, find the measurement point INV.GenActivePW, click View Data
to enter Data Insights page to view the latest data of measurement point.
You can also use TSDB Data Service to obtain the latest data of the measurement point.