Device Security

This page describes the device security features available in akenza

Securing devices is one of the main concerns when rolling out an IoT deployment and requires careful consideration in order to minimize the attack surface.

akenza offers the following security features:

  • Device credentials with JWTs: Per-device public/private key authentication using JSON Web Tokens (JWTs, RFC 7519)

  • Uplink secret: A shared key per device connector that is passed via header or URL parameter for HTTP and CoAP and the password field for MQTT

Device Credentials with JWTs

This authentication method is based on public/private key authentication using JSON Web Tokens and limits the attack surface because a compromised key only affects a single device and not the whole fleet. As JWTs define an expiration, any compromised key will only be valid for a limited duration.

Currently, this authentication method is only available for MQTT devices.

Device provisioning process

The "provisioner" (typically the hardware manufacturer) is required to create a public/private key pair that is distributed to the device during the provisioning process.

  1. Create a new key pair (public/private key)

  2. Distribute the key to the device and securely store it

  3. Upload the public key to akenza

  4. Authenticate with a JSON Web token that is signed by the private key, while establishing an MQTT connection

  5. Start sending telemetry and receiving commands

Notably, the key can be stored on the device before the device has been created in akenza.

Security Standards

akenza provides support for both RSA and Elliptic Curve signed tokens.

Algorithms

The following algorithms are supported:

  • JWT RS256 (RSASSA-PKCS1-v1_5 using SHA-256 RFC 7518 sec 3.3)

  • JWT ES256 (ECDSA using P-256 and SHA-256 RFC 7518 sec 3.4), defined in OpenSSL as the prime256v1 curve

The RSA algorithm has a wider adoption, however keys and signatures tend to be large (~1-2 kB) and the algorithm has higher resource requirements (key length and CPU).

The Elliptic Curve algorithm is well supported but not as widely used as RSA. The generated keys and signatures are significantly smaller compared to RSA, which can be useful for devices with constrained resources.

Key Strength

A minimum of 112 bits of security is required by akenza (also refer to the NIST recommendations, section 5.6.2, pages 55-56). This translates to a minimum 2048-bit key size for RS256.

ES256 has a preset level of 128 bits of security (the key size is fixed).

Public Key Format

The following key formats are supported in akenza

  • RSA PEM: An RSA public key encoded in base64.

  • RSA X509 PEM: An RSA PEM key, encoded in base64, wrapped in an X.509 certificate.

  • ES256 PEM: A public key for the ECDSA algorithm (using P-256 and SHA-256), encoded in base64.

  • ES256 X509 PEM: An ES256 PEM key, encoded in base64, wrapped in a X.509 certificate.

Key rotation

akenza supports multiple active keys (up to 3 per device) to allow for uninterrupted rotation. If more than one key is in use, the JWT must include the fingerprint of the key used to sign the JWT (kid claim).

Generating and Signing JWTs

The JWT needs to be generated with the following reserved claim fields and signed using the private key. Refer to our Tutorials for practical examples on how to generate private/public keys and sign a JWT.

Required JWT contents:

  • kid must be the fingerprint of a public key or certificate associated with the device. The kid is optional if there’s only one public key or certificate associated with a device

  • alg required, contains the appropriate signing algorithm based on signature

  • aud required, must be in the following format: https://akenza.io/devices/{deviceId}(for enterprise deployments the base url of the deployment needs to be used instead of akenza.io)

  • exp required, a valid date in the future. A 10-minute clock-skew allowance applies.

  • iat optional, a valid date in the past. A 10-minute clock-skew allowance applies.

The expiration (exp) and issued at (iat) claims are relevant to check whether the JWT is valid during uplink processing. In no cases should the device use an (almost) never expiring JWT, as it could be used to send unauthorized data.

Other claims (standard and custom ones) can be set, but will have no impact on the uplink processing.

MQTT

uplink topic: /up/device/id/{deviceId}

downlink topic: /down/device/id/{deviceId}

The MQTT authentication needs to include the following properties:

  • username arbitrary username (not used). depending on framework this needs to be set in order for the password to be sent as well

  • password must be a valid JWT signed with the private key

  • clientId must be the deviceId

HTTP

Not supported yet.

CoAP

Not supported yet.

Best Practices

  • keep the private key secret

  • use TLS 1.2 when communicating on ports 8883

    • Verify that the server certificate

    • Perform regular security-related firmware updates to keep server certificates up-to-date

  • each device should have a unique public/private key pair

This form of authentication is the easiest. It is most commonly used for HTTP-based integrations.

When a data flow is created, the device connector specifies the secret to use as password when making an uplink.

Authenticating an uplink with basic auth requires the device connector id and the uplink secret. If the device connector is assigned, via data flow, to the device and the uplink secret matches, the uplink request is authenticated.

HTTP

URL: /v3/capture?deviceId={deviceId}&topic=default&...

Authentication: HTTP header secret with value {uplinkSecret} or as a url param

NOTE: The uplink secret should, whenever possible, be sent as a header, but can also be sent as a query-param named secret. Using the HTTP header is greatly preferred, as it doesn’t expose the uplink-secret in the URL.

MQTT

uplink topic: up/{uplinkSecret}/id/{deviceId}

downlink topic: /down/{uplinkSecret}/id/{deviceId}

The MQTT authentication needs to include the following properties:

  • username must be the device connector id

  • password must be the uplink secret

  • clientId can be anything/left blank

CoAP

url: udp://{host}:{port}?deviceId={deviceId}&secret={secret}&topic={topic}&...

Last updated