Home > Software design >  Verifying signature created using OpenSSL with BearSSL
Verifying signature created using OpenSSL with BearSSL

Time:01-12

I am trying to verify a ECDSA signature created with OpenSSL on an embedded device using BearSSL.

First I created a private key using OpenSSL and extracted the public key:

$ openssl ecparam -name secp256r1 -genkey -noout -out private.pem
$ openssl ec -in private.pem -pubout -out public.pem

Then I extracted the raw public key:

$ openssl ec -noout -text -inform PEM -in public.pem -pubin
read EC key
Public-Key: (256 bit)
pub:
    04:28:4b:54:a4:d4:92:6c:82:2d:da:8a:e1:be:4b:
    49:61:5d:91:2b:2d:f5:f2:66:f8:9b:d1:be:cb:fb:
    db:fc:4f:68:cf:52:68:55:36:53:0f:8e:8d:69:3f:
    40:3a:06:62:ad:5b:5a:66:e6:1d:31:c6:13:08:f3:
    4f:94:7b:59:7a

I have a text.txt that contains nothing but hello world and sign this using the following command:

$ cat text.txt
hello world
$ openssl dgst -sha256 -sign private.pem text.txt > signature

This now contains the signature in ASN1 format and is 72 bytes long as to be expected:

$ hexdump signature
0000000 4530 2002 ac54 51af 8ac0 cee8 dc74 4120
0000010 105c b65d a085 06c5 8e9f 1527 12f5 8e50
0000020 9d19 9b30 2102 a900 d2a5 343e 3a10 0bdd
0000030 e0a8 82f8 de2a 4f2d 51bf a775 bc42 2d2e
0000040 19c0 874f d85e 004b

Now to the embedded part. I include the data, signature and the public key first:

uint8_t text[] = "hello world\n";
size_t textlen = 12;

uint8_t signature[] = {
  0x45, 0x30, 0x20, 0x02, 0xac, 0x54, 0x51, 0xaf, 0x8a, 0xc0, 0xce, 0xe8, 0xdc, 0x74, 0x41, 0x20,
  0x10, 0x5c, 0xb6, 0x5d, 0xa0, 0x85, 0x06, 0xc5, 0x8e, 0x9f, 0x15, 0x27, 0x12, 0xf5, 0x8e, 0x50,
  0x9d, 0x19, 0x9b, 0x30, 0x21, 0x02, 0xa9, 0x00, 0xd2, 0xa5, 0x34, 0x3e, 0x3a, 0x10, 0x0b, 0xdd,
  0xe0, 0xa8, 0x82, 0xf8, 0xde, 0x2a, 0x4f, 0x2d, 0x51, 0xbf, 0xa7, 0x75, 0xbc, 0x42, 0x2d, 0x2e,
  0x19, 0xc0, 0x87, 0x4f, 0xd8, 0x5e, 0x00, 0x4b };

static const uint8_t public_bytes[] = {
  0x04, 0x28, 0x4b, 0x54, 0xa4, 0xd4, 0x92, 0x6c, 0x82, 0x2d, 0xda, 0x8a, 0xe1, 0xbe, 0x4b,
  0x49, 0x61, 0x5d, 0x91, 0x2b, 0x2d, 0xf5, 0xf2, 0x66, 0xf8, 0x9b, 0xd1, 0xbe, 0xcb, 0xfb,
  0xdb, 0xfc, 0x4f, 0x68, 0xcf, 0x52, 0x68, 0x55, 0x36, 0x53, 0x0f, 0x8e, 0x8d, 0x69, 0x3f,
  0x40, 0x3a, 0x06, 0x62, 0xad, 0x5b, 0x5a, 0x66, 0xe6, 0x1d, 0x31, 0xc6, 0x13, 0x08, 0xf3,
  0x4f, 0x94, 0x7b, 0x59, 0x7a };

static const br_ec_public_key public_key = {
  .curve = BR_EC_secp256r1,
  .q = (void *)public_bytes,
  .qlen = sizeof(public_bytes)
};

Also, out of paranoia, I compared the md5 sum of both the text.txt and my string before going any further as a quick check:

$ md5sum text.txt
6f5902ac237024bdd0c176cb93063dc4  text.txt
uint8_t sum[br_md5_SIZE];
br_md5_context md5ctx;
br_md5_init(&md5ctx);
br_md5_update(&md5ctx, text, textlen);
br_md5_out(&md5ctx, sum); // sum is the same as md5sum command output

I told OpenSSL to use sha256 previously to hash the payload for the signing process using ECDSA, so I am doing the same in BearSSL now and try to verify the signature using secp256r1:

br_sha256_context sha256ctx;
br_sha256_init(&sha256ctx);
br_sha256_update(&sha256ctx, text, textlen);
br_sha256_out(&sha256ctx, hash);

uint32_t result = br_ecdsa_i15_vrfy_asn1(&br_ec_prime_i15, hash, sizeof(hash), &public_key, signature, sizeof(signature));

My expectation would be that the verify works, as I give it the same hash, hash function, curve, the corresponding public key and the signature. However, this doesn't work. I am probably missing something obvious but can't work it out.

CodePudding user response:

The signature file contents shown as

$ hexdump signature
0000000 4530 2002 ac54 51af 8ac0 cee8 dc74 4120
...

is displayed as 16-bit values.

The signature in the C program is defined as an array of 8-bit values

uint8_t signature[] = {
  0x45, 0x30, 0x20, 0x02, 0xac, 0x54, 0x51, 0xaf, 0x8a, 0xc0, 0xce, 0xe8, 0xdc, 0x74, 0x41, 0x20,
...
};

Depending on the byte order this may or may not be correct. Does 4530 correspond to 45, 30 or 30, 45?

With little-endian byte-order, the hex dump

4530 2002 ...

would correspond to

uint8_t signature[] = {
  0x30, 0x45, 0x02, 0x20, ...
};

I suggest to display the hex dump as 8-bit values, e.g. by using

od -t x1 signature

and, if necessary, fix the array initialization in the C code.

  •  Tags:  
  • Related