[Solved] How to get r and s from an ASN.1 DER encoded ECDSA signature

User avatar
davmoz
Posts: 2
Joined: Wed Jan 18, 2023 10:55 am

[Solved] How to get r and s from an ASN.1 DER encoded ECDSA signature

Postby davmoz » Fri Jan 20, 2023 5:55 pm

Hi,

I'm currently trying to get the r and s from my ANS.1 DER signature, signed by my ATECC608B. I need these to build a 64-byte signature and base64 encode it to use in my jwt. I have attempted this, but the base-64 signature I'm getting back contains (invalid?) characters/symbols such as / and +. Here is how I'm signing my 32-byte (MBEDTLS_MD_SHA256) hash:

Code: Select all

ret = mbedtls_pk_sign(&pkey, MBEDTLS_MD_SHA256, hash, 0, signature, MBEDTLS_MPI_MAX_SIZE, olen,
                          mbedtls_ctr_drbg_random, &ctr_drbg);
And this is how I'm initilizing my r and s:

Code: Select all

unsigned char *p = (unsigned char *)signature;
const unsigned char *end = signature + *olen;
size_t len;

mbedtls_mpi r, s;

mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);

if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
                                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0)
{
    ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    goto cleanup;
}

if (p + len != end)
{
    ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA +
            MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
    goto cleanup;
}

if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 ||
    (ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0)
{
    ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    goto cleanup;
}
And this is how I'm retrieving the 32-byte r and s respectivly:

Code: Select all

unsigned char r_str[32];
unsigned char s_str[32];
size_t r_len = 32;
ret = mbedtls_mpi_write_binary(&r, r_str, r_len);
ret = mbedtls_mpi_write_binary(&s, s_str, r_len);
Finally, I'm combining these and encoding them to base 64 as following:

Code: Select all

unsigned char r_s_bin[64];
size_t r_s_len = 0;

memcpy(r_s_bin, r_str, 32);
memcpy(r_s_bin + 32, s_str, 32);

unsigned char r_s_b64[2048];
size_t r_s_b64_len = 2048;

(void)atcab_base64encode((uint8_t *)r_s_bin, 64, (char *)r_s_b64, &r_s_b64_len);
ESP_LOGI(TAG, "Base64 encoded ECDSA signature (%i): %s", r_s_b64_len, r_s_b64);
Here is how a typical signature currently looks like (base-64 encoded):

Code: Select all

znSBPTFzIHZ7piKsjaHWEizMi/05ygIHBhmoM+lI8aumUrv5maz9lPaG2xxynF9WO6nLGk2fwCgQReARuOTF+A==
Would appreciate any advice/pointers! :?
I also created an issue on github, which led me to this approach.
https://github.com/espressif/esp-idf/issues/10562
I am testing my signature at https://jwt.io/

Have a great evening!

User avatar
davmoz
Posts: 2
Joined: Wed Jan 18, 2023 10:55 am

Re: How to get r and s from an ASN.1 DER encoded ECDSA signature

Postby davmoz » Sun Jan 22, 2023 2:35 pm

It turns out that my base64 encoded signature was not url-safe. Solved by replacing + and / with - and _. :oops:

Who is online

Users browsing this forum: Google [Bot] and 82 guests