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!
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.
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.