Skip to content

HTTPS & certificates

Compatible with: picoScan100

By default the REST API is served over plain HTTP on port 80. Activating HTTPS moves API traffic to port 443 and encrypts everything with TLS, protecting configuration commands and sensor data from eavesdropping and man-in-the-middle attacks, as required by standards such as IEC 62443 and the EU Cyber Resilience Act.

There is no separate enable/disable toggle: the device turns HTTPS on automatically when a valid certificate bundle is installed, and off when it is removed.

The four endpoints

Endpoint Method Auth Purpose
/api/httpsStatus GET none Read HTTPS enabled state and error code
/api/certificateBundleInfo GET none Inspect subject, issuer, validity dates, fingerprint
/api/setCertificateBundle POST Service Upload the PEM certificate bundle + private key
/api/removeCertificateBundle POST Service Remove the bundle (disables HTTPS)

Certificate requirements

Uploads that don't meet these are rejected with success: false.

Property Requirement
Port 443 (fixed)
Format X.509 PEM (.pem, .crt, .cer)
Minimum key size RSA > 3072 bits, or ECDSA > 250 bits, or Ed25519 / Ed448
Maximum chain length root CA → intermediate → leaf (3 levels); 2-level chain recommended
contentCertificateBundle 10 000 characters max
contentPrivateKey 4 000 characters max
Mutual TLS Not supported (server-side certificate only)

Three pieces of material are involved:

Certificate bundle (contentCertificateBundle): uploaded to the device. It contains the leaf (server) certificate first, then any intermediates; the root CA may optionally be appended. Private key (contentPrivateKey): uploaded alongside the bundle, and must match the leaf certificate's public key. CA certificate: kept on the client to verify the device during the TLS handshake. For a self-signed root CA, this is the root ca.pem.

Create a self-signed chain (OpenSSL)

A two-level hierarchy (self-signed root CA → leaf) is the recommended minimum. Replace 192.168.0.1 with your device IP.

# Root CA key + certificate
openssl genrsa -out ca.key 4096
openssl req -new -x509 -key ca.key -out ca.pem -days 365 \
  -subj "/CN=My Sensor Root CA/O=My Organisation/C=DE"
# Server key + CSR
openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr \
  -subj "/CN=My Sensor/O=My Organisation/C=DE"
# Sign the leaf with the device IP as a Subject Alternative Name
echo "subjectAltName=IP:192.168.0.1" > san.ext
openssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key \
  -CAcreateserial -out leaf.pem -days 365 -extfile san.ext
# Build the bundle (leaf + root CA)
cat leaf.pem ca.pem > server.pem                       # Linux / macOS
# Get-Content leaf.pem, ca.pem | Set-Content server.pem # Windows PowerShell

You end up with three files:

File Contents Used by
ca.pem Root CA certificate Clients (verify the server)
server.pem Leaf + root CA (PEM bundle) Device upload: contentCertificateBundle
server.key Leaf private key Device upload: contentPrivateKey

TLS clients match the certificate against the address they connect to. Without subjectAltName=IP:<device-ip>, verification fails. Add every address you'll use to reach the device.

Upload the bundle

POST /api/setCertificateBundle requires Service-level challenge-response. Both PEM blocks go in the data object as plain-text strings:

POST /api/setCertificateBundle
Content-Type: application/json
{
  "header": { "user": "Service", "realm": "<from challenge>",
              "nonce": "<from challenge>", "opaque": "<from challenge>",
              "response": "<computed SHA-256 response>" },
  "data": {
    "contentCertificateBundle": "<PEM bundle - leaf + optional chain>",
    "contentPrivateKey": "<PEM private key>"
  }
}

A success looks like:

{ "header": { "status": 0, "message": "Ok" },
  "data": { "success": true, "errorCode": { "error": "None" } } }

As soon as a valid bundle is accepted, HTTPS is live on port 443. The API stays reachable on both port 80 (HTTP) and 443 (HTTPS) until the bundle is removed.

Read status and connect

GET /api/httpsStatus              # enabled state + error code
GET /api/certificateBundleInfo    # subject, issuer, validity, fingerprint

Then use the API over TLS, trusting your ca.pem:

curl --cacert ca.pem https://192.168.0.1/api/DeviceIdent

On Windows, if the root CA is already trusted in the OS certificate store, clients use it automatically.

Remove the bundle

POST /api/removeCertificateBundle   # Service auth; disables HTTPS

Keep port 80 available while you validate the certificate. If an upload leaves HTTPS refusing connections, read httpsStatus over HTTP to see the error code, fix the certificate, and re-upload. See Cybersecurity for wider hardening guidance.

Related picoScan article