This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

ECC wrong public key is generated

Hi, I want to produce a shared secret key between a Smartphone and a NRF52 in order to encrypt data later with AES-128 (example of key sharing: here).

To do that i need to implement a ECDH (Elliptic Curve Diffie Hellman) in application level (not in protocol stack) because BLE 4.0 and 4.2 don't implement this key sharing on the same way.

I have read in infocenter that the nrf_crypto library supports only NIST p-256 curve, and i can already generate private and public key with my android application and derivate the shared key using this type of curve (example here)

On NRF side, i've installed all the libraries (nrf_crypto.h, ecc.h...) and micro_ecc_lib_nrf52.lib and i'am using these differents functions :

nrf_crypto_init (void)    
nrf_crypto_public_key_compute (uint32_t curve, nrf_crypto_key_t const *p_sk, nrf_crypto_key_t *p_pk)   

So, I have try to declare the curve and differents types of keys :

#define  SECP256R1    0x04 

uint8_t privatekey[32] = { 0x11, 0x11, 0x24, 0x50, 0x38, 0xb6, 0xed, 0x60, 0xc3, 0x60, 0x12, 0x50, 0x00, 0xd2, 0x25, 0x0f, 0xee, 0x37, 0xbf, 0x00, 0x02, 0x6b, 0x50, 0x92, 0x80, 0x32, 0x42, 0x2e, 0xd6, 0x68, 0xde, 0xdf }; // random private key NRF
uint8_t publicNRF[64] = { 0x00, 0x00...}  ; //public key NRF initilalized at 0x00

then the nrf_crypto_key_t:

static const nrf_crypto_key_t crypto_key_privatekey =
{
    .p_le_data = (uint8_t *) privatekey,
    .len = sizeof(privatekey)
};

static nrf_crypto_key_t crypto_key_publicNRF =
{
    .p_le_data  = (uint8_t *) publicNRF,
    .len = sizeof(publicNRF)
};

and then the functions crypto in main:

int main (void)
{
   ...
      nrf_crypto_init ();
      nrf_crypto_public_key_compute(SECP256R1, &crypto_key_privatekey, &crypto_key_publicNRF); //generate a 64 bytes public key from a 32 bytes private key
   ...
}

the function nrf_crypto_key_compute return me NRF_SUCCESS and fill public key with these values :

X: 02700CA6E1285C640EBA51B34724C6ED7647CEBDCA6828C987913361350DA017
Y: 59D31A28EB7D14A10237CA6468C852F70CFD8753565136FF6FFB40FA25EE01D7

using the private key: 1111245038b6ed60c360125000d2250fee37bf00026b50928032422ed668dedf (dec:7719605451653719210803119225407308115048817886466044753560789111057171406559)

But when i'm computing the public key using this website and curve secp256r1 It generate these public keys values:

X: D104BAEF260CCB567EEEE50B67ADB544F8D607034532CF57A44AFFA526034602
Y: B07B48B83E940C94AC3FE11C398BE0307A518EFE59B3F9443852E02787226067

So, my question is why these keys are differents, is there a problem while computing public key with ECC ?

Thanks you in advance

Parents
  • Yeah, it Works but it's a bit difficult !!! But i've found an easier version, i've reverse the private key AND the public key to obtain the same result from this site but we must compute key shared key with no inversion on the public and private key. I've use this function :

    static void reverse(uint8_t* p_arr, uint32_t len) // inverse Big-Endian
    

    { uint32_t i;

    for (i = 0; i < len/2 ; i++)
    {
        uint8_t tmp = p_arr[i];
        p_arr[i] = p_arr[len - i - 1];
        p_arr[len - i - 1] = tmp;
    }
    

    }

    thanks you very much !

Reply
  • Yeah, it Works but it's a bit difficult !!! But i've found an easier version, i've reverse the private key AND the public key to obtain the same result from this site but we must compute key shared key with no inversion on the public and private key. I've use this function :

    static void reverse(uint8_t* p_arr, uint32_t len) // inverse Big-Endian
    

    { uint32_t i;

    for (i = 0; i < len/2 ; i++)
    {
        uint8_t tmp = p_arr[i];
        p_arr[i] = p_arr[len - i - 1];
        p_arr[len - i - 1] = tmp;
    }
    

    }

    thanks you very much !

Children
  • Hello, i face the same problem to calculate to public key. I use the website you given to calculate the key, but the input and output should be displayed in decimalism. How can i switch my key from hexadecimal to decimalism? The number is so large that my calculator not working. Could you tell me the method to calculate it?Thank you !

  • Hi, i'm agree with you, even the type uint64_t is limited to 18446744073709551615. The easiest way is to calculate this is to use only hexadecimal but if you really want to use decimal you must divide the Hexadecimal result in 8 bytes parts (uint64_t) and print them apart. I've implemented this solution with hexadecimal in my projet and it works really well ! In addition you can check your result with an hexa to decimal converter like this link text and comparte the key generated from the ECDH website you given.

Related