Help with Encrypted Token in HTTP Bridge API - Example Request Needed

Hello everyone,

I’m currently working with the Nuki Bridge HTTP API and trying to use the encrypted token functionality, as described in the documentation. However, I am struggling to understand exactly how this works, particularly with regard to generating and using the nonce.

The documentation explains that the nonce should be provided in the API request, but it’s not clear how this nonce is generated or retrieved. Could someone please provide a more detailed explanation or an example of how to properly implement an API request with an encrypted token?

A specific working example (in any language) would be extremely helpful!

Thank you in advance for your help.

Best regards,
Tim

Hi Tim,

The nonce is a random 24-byte value so it has to be generated randomly by you.
It then needs to be passed to the request as well.

I’ve just checked the online documentation and noticed that the stylesheet somehow cut the full URL which is:
http://192.168.1.50:8080/info?ctoken=a7f6b4df6758b92445bd5470b755b43ba41cf50af8b3f6e19368348ddfb1686291555dfd90b31f9333&nounce=119c38fb6d7d707b8a45f14e688b74b8c4c1acf33643c71a

We’ll fix this in the online documentation.
Please refer to the PDF variant for now.

best,
Marc

Hi Marc,

thanks for your help. It makes much more sense now!

I tried in PHP now. But without luck: HTTP 401 Unauthorized
Maybe I will try it with another language later…

<?php

// Define the IP address and port of the Nuki Bridge
$bridge_ip = '192.168.1.99'; // Replace with the IP of your Nuki Bridge
$bridge_port = '8080'; // The default port the Nuki Bridge listens on

// Nuki API Token and Nonce initialization
$api_token = '123456'; // Your unique API token for authentication
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); // Generate a random 24-byte nonce

// Generate the current timestamp in the required UTC format (YYYY-MM-DDTHH:MM:SSZ)
$timestamp = date('Y-m-d\TH:i:s\Z'); // 'Z' indicates the time is in UTC

// Re-generate a 24-byte random value for the nonce (required by XSalsa20-Poly1305)
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); // Nonce ensures each encryption is unique

// Create the secret key by hashing the API token with SHA-256
$secret_key = hash('sha256', $api_token, true); // This creates a 32-byte key from the token

// Prepare the message for encryption, which in this case is just the timestamp
$message = $timestamp; // The timestamp acts as the plaintext message to be encrypted

// Encrypt the message using XSalsa20-Poly1305 with the generated nonce and secret key
$encrypted_message = sodium_crypto_secretbox($message, $nonce, $secret_key); // Encrypts the timestamp

// Convert the encrypted message and nonce to hexadecimal format for safe URL inclusion
$encrypted_message_hex = bin2hex($encrypted_message); // Convert the ciphertext to hex
$nonce_hex = bin2hex($nonce); // Convert the nonce to hex

// Build the URL with the encrypted token and nonce as query parameters
$url = "http://$bridge_ip:$bridge_port/info?ctoken=$encrypted_message_hex&nonce=$nonce_hex";

// Output the generated URL as a clickable link
echo "<a href='".$url."'>Nuki-Link</a>";

?>

The documentation is a bit misleading here.
The message to encrypt is not just the timestamp it contains the timestamp and a random number.
The random number is a 2-byte number greater than 0 (so 1 - 65535; the example in the documentation uses 4711).
In your example the $message to be encrypted then would be $timestamp,4711 instead of just $timestamp.

Got it! Thank you Marc! I think the documentation needs more examples :wink:

<?php

// Bridge IP-Adresse und Port
$bridge_ip = '192.168.1.99';
$bridge_port = '8080';

// Lock ID aka. nukiId
$lockId = '11A22BBB';

// Nuki API Token
$api_token = '123456';

// Nonce
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);

// Timestamp in UTC-Format
date_default_timezone_set('UTC');
$timestamp = date('Y-m-d\TH:i:s\Z');

// Random int 1-65535
$random = mt_rand(1, 65535);

// Message
$message = "$timestamp,$random"; // Hier wird nur der Timestamp verwendet

// Generate Secret Key SHA-256-Hash
$secret_key = hash('sha256', $api_token, true);

// Verschlüsselung der Nachricht (Timestamp)
$encrypted_message = sodium_crypto_secretbox($message, $nonce, $secret_key);

// In Hex umwandeln für die URL
$encrypted_message_hex = bin2hex($encrypted_message);
$nonce_hex = bin2hex($nonce);

// URLs für die Nuki-API erstellen
$info_url = "http://$bridge_ip:$bridge_port/info?ctoken=$encrypted_message_hex&nonce=$nonce_hex";
$lock_url = "http://$bridge_ip:$bridge_port/lockAction?nukiId=$lockId&action=2&ctoken=$encrypted_message_hex&nonce=$nonce_hex";
$unlock_url = "http://$bridge_ip:$bridge_port/lockAction?nukiId=$lockId&action=1&ctoken=$encrypted_message_hex&nonce=$nonce_hex"; 

// Ausgabe auf der Webseite
echo "<h1>Nuki Lock Control</h1>";
echo "<p><a target='_blank' href='$info_url'>Get Lock Info</a></p>";
echo "<p><a target='_blank' href='$unlock_url'>Unlock</a></p>";
echo "<p><a target='_blank' href='$lock_url'>Lock</a></p>";

?>

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.