Problem with Command Authorization Authenticator

Hello,

I always get the Error Message 12 00 11 05 00 73 da after sending the authorization authenticator command.
The strange thing is, I have tried the values from the example in the API description and with this values I got the expected results. So I dont know what is the problem here.

I am using the ESP-3.0 and the libsodium library for encryption and hashing.

Here is my LOG:

I (3993) NUKI_PAIRING: Start pairing
I (4003) Prepare Write: : 01 00 03 00 27 a7
I (4023) GATTC_DEMO: write descr success
I (4053) GATTC_DEMO: ESP_GATTC_PREP_WRITE_EVT, write prepare event
I (4053) Execute Write: : execute write command function called
I (4083) GATTC_DEMO: ESPGATTC_EXEC_EVT, write executed event
I (4203) GATTC_DEMO: ESP_GATTC_NOTIFY_EVT, receive indicate value:
I (4203) GATTC_DEMO: 03 00 39 e7 5f b9 4b be c0 31 7f 8c fb 88 09 eb
I (4213) GATTC_DEMO: 50 97 51 45
I (4233) GATTC_DEMO: ESP_GATTC_NOTIFY_EVT, receive indicate value:
I (4233) GATTC_DEMO: 29 83 35 c0 e1 26 cd 48 cb 64 b5 7c 8c 26 53 53
I (4503) NUKI_PAIRING: Received public key from smartlock
I (5003) Prepare Write: : 03 00 8c aa 54 67 23 07 bf fd f5 ea 18 3f c6 07
I (5003) Prepare Write: : 15 8d 20 11 d0 08 ec a6 a1 08 86 14 ff 08 53 a5
I (5003) Prepare Write: : aa 07 b4 9e
I (5033) GATTC_DEMO: ESP_GATTC_PREP_WRITE_EVT, write prepare event
I (5033) Execute Write: : execute write command function called
I (5063) GATTC_DEMO: ESP_GATTC_NOTIFY_EVT, receive indicate value:
I (5063) GATTC_DEMO: 04 00 e8 8d f6 06 0d 05 72 71 ec 70 27 90 c7 77
I (5063) GATTC_DEMO: 0c f5 a1 a4
I (5063) GATTC_DEMO: ESPGATTC_EXEC_EVT, write executed event
I (5093) GATTC_DEMO: ESP_GATTC_NOTIFY_EVT, receive indicate value:
I (5093) GATTC_DEMO: 56 68 e1 c2 6d b3 fd 2e 50 bd 2c 25 6b fb a6 33
I (5513) NUKI_PAIRING: Received challenge for authorization authenticator
I (5563) PUBLIC KEY FOB: : 8c aa 54 67 23 07 bf fd f5 ea 18 3f c6 07 15 8d
I (5563) PUBLIC KEY FOB: : 20 11 d0 08 ec a6 a1 08 86 14 ff 08 53 a5 aa 07
I (5573) PUBLIC KEY NUKI: : 39 e7 5f b9 4b be c0 31 7f 8c fb 88 09 eb 50 97
I (5573) PUBLIC KEY NUKI: : 51 45 29 83 35 c0 e1 26 cd 48 cb 64 b5 7c 8c 26
I (5583) NONCE: : e8 8d f6 06 0d 05 72 71 ec 70 27 90 c7 77 0c f5
I (5593) NONCE: : a1 a4 56 68 e1 c2 6d b3 fd 2e 50 bd 2c 25 6b fb
I (5603) r: : 8c aa 54 67 23 07 bf fd f5 ea 18 3f c6 07 15 8d
I (5603) r: : 20 11 d0 08 ec a6 a1 08 86 14 ff 08 53 a5 aa 07
I (5613) r: : 39 e7 5f b9 4b be c0 31 7f 8c fb 88 09 eb 50 97
I (5623) r: : 51 45 29 83 35 c0 e1 26 cd 48 cb 64 b5 7c 8c 26
I (5623) r: : e8 8d f6 06 0d 05 72 71 ec 70 27 90 c7 77 0c f5
I (5633) r: : a1 a4 56 68 e1 c2 6d b3 fd 2e 50 bd 2c 25 6b fb
I (5643) AUTHENTICATOR: : cf 43 b0 31 c2 7b c5 09 84 84 5f e8 c8 7f 72 49
I (5643) AUTHENTICATOR: : ae fb 74 b3 4f 44 c6 c7 ca 0b e9 e6 c7 91 74 29
I (6153) Prepare Write: : 05 00 cf 43 b0 31 c2 7b c5 09 84 84 5f e8 c8 7f
I (6153) Prepare Write: : 72 49 ae fb 74 b3 4f 44 c6 c7 ca 0b e9 e6 c7 91
I (6153) Prepare Write: : 74 29 10 3b
I (6183) GATTC_DEMO: ESP_GATTC_PREP_WRITE_EVT, write prepare event
I (6183) Execute Write: : execute write command function called
I (6213) GATTC_DEMO: ESPGATTC_EXEC_EVT, write executed event
I (6333) GATTC_DEMO: ESP_GATTC_NOTIFY_EVT, receive indicate value:
I (6333) GATTC_DEMO: 12 00 11 05 00 73 da

Here is my Code:

static uint8_t public_key_fob[32] = {0x8C, 0xAA, 0x54, 0x67, 0x23, 0x07, 0xBF, 0xFD, 0xF5, 0xEA, 0x18, 0x3F, 0xC6, 0x07, 0x15, 0x8D, 0x20, 0x11, 0xD0, 0x08, 0xEC, 0xA6, 0xA1, 0x08, 0x86, 0x14, 0xFF, 0x08, 0x53, 0xA5, 0xAA, 0x07};
static uint8_t private_key_fob[32] = {0xF8, 0x81, 0x27, 0xCC, 0xF4, 0x80, 0x23, 0xB5, 0xCB, 0xE9, 0x10, 0x1D, 0x24, 0xBA, 0xA8, 0xA3, 0x68, 0xDA, 0x94, 0xE8, 0xC2, 0xE3, 0xCD, 0xE2, 0xDE, 0xD2, 0x9C, 0xE9, 0x6A, 0xB5, 0x0C, 0x15};

static void calculate_authenticator(uint8_t* output_buffer, uint8_t* message, uint16_t message_length) {
	crypto_auth_hmacsha256(output_buffer, message, message_length, pairing_ctx.shared_secret);
}

uint16_t create_authorization_authenticator_payload(uint8_t* output_buffer, uint8_t* received_data) 
{
	uint8_t* nonce = &received_data[2];
	uint16_t command_length = 36;
	write_uint16LE(output_buffer, authorization_authenticator_cmd, 0);

	//Shared key calculation
	uint8_t dh_key[32]; //crypto_scalarmult_BYTES
	int ret = crypto_scalarmult_curve25519(dh_key, private_key_fob, public_key_nuki);
	
	if(ret == -1)
	{
		ESP_LOGE("NUKI Authorization", "Error in Crypto Scalarmult");
		return 0;
	}
	
	unsigned char _0[16];
	memset(_0, 0, 16);
	const unsigned char sigma[16] = "expand 32-byte k";
	crypto_core_hsalsa20(pairing_ctx.shared_secret, _0, dh_key, sigma);

	const uint16_t r_length = 32 + 32 + PAIRING_NONCEBYTES; 
	uint8_t r[32 + 32 + PAIRING_NONCEBYTES]; 
	memcpy(r, public_key_fob, 32);
	memcpy(&r[32], public_key_nuki, 32);
	memcpy(&r[32 + 32], nonce, PAIRING_NONCEBYTES);
	uint8_t authenticator[32];
	calculate_authenticator(authenticator, r, r_length);
	memcpy(&output_buffer[2], authenticator, 32);
	crc_payload(output_buffer, command_length);
	
	esp_log_buffer_hex("PUBLIC KEY FOB: ", public_key_fob, 32);
	esp_log_buffer_hex("PUBLIC KEY NUKI: ", public_key_nuki, 32);
	esp_log_buffer_hex("NONCE: ", nonce, 32);
	esp_log_buffer_hex("r: ", r, r_length);
	esp_log_buffer_hex("AUTHENTICATOR: ", authenticator, 32);
	
	return command_length;
}

What could be the problem here?

Thanks for your Help!

Hi David,

The error you receive is P_ERROR_BAD_AUTHENTICATOR, because the Authenticator you’re sending is not correct.

Here is the calculation based on your data:

Your private key is F88127CCF48023B5CBE9101D24BAA8A368DA94E8C2E3CDE2DED29CE96AB50C15
The public key of the smart lock is 39E75FB94BBEC0317F8CFB8809EB50975145298335C0E126CD48CB64B57C8C26

So the common shared key calculated with dh1 and kdf1 both parameter is 19FA26E5CE9F2C55961EFB4F36A58E90E5E3625ACAC1131750EFF49CEA1FD548
I do not see this value somewhere in your log

Then the value r for the authenticator is prepared by appending both public keys and the challenge which results in 8CAA54672307BFFDF5EA183FC607158D2011D008ECA6A1088614FF0853A5AA0739E75FB94BBEC0317F8CFB8809EB50975145298335C0E126CD48CB64B57C8C26E88DF6060D057271EC702790C7770CF5A1A45668E1C26DB3FD2E50BD2C256BFB
This is appearing in your log as well, so that part is ok.

And in the last step, the authenticator of r is calculated of this value and the common shared key.
The result is 8474C07FDA3E66EAC4DF3F0300A299C1BB9F2BA47DD209D318FCC6524C4EA588
This differs from your result but probably because of the wrong common shared key

regards,
Marc

I checked the comon shared key calculated and my result is the same as yours.
19 fa 26 e5 ce 9f 2c 55 96 1e fb 4f 36 a5 8e 90 e5 e3 62 5a ca c1 13 17 50 ef f4 9c ea 1f d5 48

So I am confused of authenticator calculation… I thouth the algorithm here is HMAC-SHA256.
Then I get
AUTHENTICATOR = cf 43 b0 31 c2 7b c5 09 84 84 5f e8 c8 7f 72 49 ae fb 74 b3 4f 44 c6 c7 ca 0b e9 e6 c7 91 74 29

Did you used HMAC-SHA512 to calculate the authenticator? Because when I use this function and only take the first 32 bytes of the result I get:
AUTHENTICATOR = 84 74 c0 7f da 3e 66 ea c4 df 3f 03 00 a2 99 c1 bb 9f 2b a4 7d d2 09 d3 18 fc c6 52 4c 4e a5 88

But when I use SHA512 I also get the error P_ERROR_BAD_AUTHENTICATOR from the Nuki Smart Lock.
So what algorithm is correct HMAC-SHA256 or HMAC-SHA512 ?
Is the authenticator starting with 84… really correct ?

Thanks for your Help

David

Hi David,

Sorry, you’re absolutely right.
I’ve been using an outdated python example on my side and inserted your values.
That example has been using HMAC-SHA512 instead of HMAC-SHA256.

So all your calculation is right.

But, I’ve been trying to implement pairing with your private and public key and it just does not work which leads to the assumption, that the public key you’re using does not belong to the private key.

How did you calculate the public key 8CAA54672307BFFDF5EA183FC607158D2011D008ECA6A1088614FF0853A5AA07 out of your private key F88127CCF48023B5CBE9101D24BAA8A368DA94E8C2E3CDE2DED29CE96AB50C15?

Or how did you calculate the whole keypair?

Edit:
OK, I’ve got it. You swapped private and public key.
If I use your private key as public key and vice versa, pairing does work as expected.

regards,
Marc

Thank you. Now the pairing works as expected.