Last Updated on : 2024-05-16 06:43:15download
This topic describes how to enable the gateway to integrate with a third-party system.
The integration with a third-party system is disabled by default. It can be enabled on the mobile app.
After the feature is enabled, the app panel will show the device key used to encrypt data for identity authentication. Be sure to keep the device key safe.
The WebSocket protocol is used for the integration, with data encrypted using the AES-128-ECB algorithm. After establishing a WebSocket connection, both parties will authenticate each other’s identity before communication occurs. The data is encrypted using the session key negotiated during authentication.
The gateway generates a 16-byte random number nonce S and encodes it in base64 format.
The gateway sends the base64-encoded nonce S to the third-party application in a message of auth_required
type.
The third-party application receives the data, decodes nonce S using base64, calculates the HMAC with SHA-256, and encodes it in base64.
The third-party application generates a 16-byte random number nonce C and encodes it in base64 format.
The third-party application sends the base64-encoded nonce C and HMAC to the gateway in a message of auth
type.
The gateway receives the data, decodes nonce C using base64, calculates the HMAC with SHA-256, and encodes it in base64.
The gateway checks the HMAC from the third-party application. If verified, it will send the base64-encoded HMAC to the third-party application in a message of auth_ok
type.
The third-party application checks the HMAC from the gateway. If verification fails, the connection will be terminated.
The data is encrypted using the AES-128-ECB algorithm for transmission, with the key displayed on the app panel.
In this Python example, a WebSocket client connects to a gateway over LAN, performs identity authentication, and gets the list of devices connected to the gateway.
In the example, replace YOUR_IP_ADDRESS
with your gateway’s IP address and YOUR_SECRET_KEY
with your gateway key (the key shown on the app panel).
Example:
import websocket
import json
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import hashlib
import hmac
import base64
class LocalApi(object):
def __init__(self, url: str, key: bytes):
self.nonce_c = os.urandom(16)
self.nonce_s = None
self.key = key
self.url = url
self.ws = websocket.WebSocket()
self.cipher = AES.new(self.key, AES.MODE_ECB)
self.ws.connect(self.url)
def enc_msg(self, msg: bytes) -> bytes:
padded_msg = pad(msg, AES.block_size)
return self.cipher.encrypt(padded_msg)
def dec_msg(self, msg: bytes) -> bytes:
return unpad(self.cipher.decrypt(msg), AES.block_size)
def _auth_required(self, data):
self.nonce_s = base64.b64decode(data['data']['nonce'])
hmac_sha256 = hmac.new(self.key, self.nonce_s, hashlib.sha256)
hmac_hex = hmac_sha256.digest()
hmac_str = base64.b64encode(hmac_hex).decode('utf-8')
msg = json.dumps({
"type": "auth",
"data": {
"nonce": base64.b64encode(self.nonce_c).decode('utf-8'),
"hmac": hmac_str
}
})
self.ws.send(self.enc_msg(msg.encode()))
def _auth_ok(self, data):
self.key = bytes([a ^ b for a, b in zip(self.nonce_c, self.nonce_s)])
self.cipher = AES.new(self.key, AES.MODE_ECB)
self._get_devices()
def _get_devices(self):
msg = json.dumps({
"id": 1,
"type": "get_devices"
})
self.ws.send(self.enc_msg(msg.encode()))
def run(self):
while True:
ws_data = self.ws.recv()
data = json.loads(self.dec_msg(ws_data))
print(f"recv data: {data}")
if data['type'] == 'auth_required':
self._auth_required(data)
elif data['type'] == 'auth_ok':
self._auth_ok(data)
elif data['type'] == 'event':
pass
self.ws.close()
url = "ws://<YOUR_IP_ADDRESS>:8080"
key = b'<YOUR_SECRET_KEY>'
client = LocalApi(url, key)
client.run()
Log:
recv data: {'type': 'auth_required', 'data': {'nonce': 'nQ+UcvlKWSbPSoXic1o1Tg=='}}
recv data: {'type': 'auth_ok', 'data': {'hmac': '5uulS0qaM1aSE5ISvE4puEJ2rZ3kK1YIW/1yw+szTVw='}}
recv data: {'id': 1, 'type': 'result', 'success': True, 'result': ['000d6ffffe67e2ca-1', '000d6ffffe67e2ca']}
Is this page helpful?
YesFeedbackIs this page helpful?
YesFeedback