Using ECC508 Chip of the MKR1000 to sign data and verify it on a webserver using openssl

I try to use the ECC508 Chip on the MKR1000 to sign information I want to send to a webserver.
I think that is the simplest way to assure the integrity of the submitted information.

I was able to lock the chip and generate a new private/public key pair and export the PEMof the public key using Sandeep Mistrys example LINK
It produces a PEM using a prime256v1 curve. Which is great because it is supported by openssl.

I then wanted to use Sandeeps signing example to sign the information. LINK

But I'm don't realy get it. And hope someone here already found a way to use it or has a hint for me to do it otherwise.

  • Why can I only sign 64 byte chunks?
  • From my understanding signing needs also hashing (e.g. SHA256 which is also implemented in hardware), but it produces 32 bytes from any input.
  • What is needed to get the signed data verified by e.g., openssl on the server side?

I tried to firstly reproduce signatures with open ssl to compare the output to what I get from the ECCX08 signature code. So i generated a new key pair using openssl for the same curve.

I took the example input (0x00, 0x01 ... 0x3e, 0x3f), put it into a text file and turned it into a binary file using:

$ xxd -r -p input.txt input.bin
$ hexdump -C input.bin
00000000  00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f  |................|
00000010  10 11 12 13 14 15 16 17  18 19 1a 1b 1c 1d 1e 1f  |................|
00000020  20 21 22 23 24 25 26 27  28 29 2a 2b 2c 2d 2e 2f  | !"#$%&'()*+,-./|
00000030  30 31 32 33 34 35 36 37  38 39 3a 3b 3c 3d 3e 3f  |0123456789:;<=>?|
00000040

Then i used openssl dgst to sign and verify it:

$ openssl dgst -sha256 -sign prime256v1.key -out sign.sign input.bin
$ openssl dgst -sha256 -verify prime256v1.pubkey.pem -signature sign.sign input.bin
Verified OK

But its output is 70 byte instead of 64 byte or even 32 byte, which I don't understand. Because I only get 64 Bits out of the ECCX08 sign command.

I also tried to sign and verify by openssel pkeyutl:

$ openssl pkeyutl -sign -in input.bin -inkey prime256v1.key -out sign2.sign
$ openssl pkeyutl -verify -in input.bin -pubin -inkey prime256v1.pubkey.pem -sigfile sign2.sign
Signature Verified Successfully 

Also this gets an output of 70 Byte. sign.sign and sign2.sign are different by the way. And the openssl dgst command can't verify openssl pkeyutl commands output and vice versa.
But for sure both can't verify what comes out of the sign example from ECCX08.h

I also thought about hasing the input in the Arduino first. But the output of the hash would be 32 Byte with SHA256 and not 64 Byte, so what to feed into the sign function of ECCX08.h. It says it needs an input of exactly 64 Byte and the output is also expected to be exactly 64 Byte.

So having no further documentation beside the code comments in the examples of ECCX08.h and found no tutorial or post in the forums, I hope someone here can show me some direction.

What exact command gives you output of 70 bytes?

signing is not encrypting a document. You just want to establish that something did not get modified

so you start by calculating a hash of your document.
A hash is a fixed length binary data representation of your document which has specific attributes, one being that if you modify just one bit in your document the hash will be very different.

sha256 is such a hash algorithm and the 256 means you get 256 bits out representing the signature of the document. 256 bits is 32 bytes.

then that's where the crypto comes into play. You encode with the algorithm of your choice those 32 bytes and this is what is sent along with the document. The document is in clear text, and you send the encoded hash as a signature. The recipient knows how to decode the hash with a public key (so gets the original 32 bytes) and can calculate the hash as the document is in clear text. if both match the document has not been tempered with.

In order to hijack the transmission, the attacker (man in the middle) would get the document (easy as it's in clear text), can modify the document can calculate the new hash but if the private key is unknown to the attacker, he cannot generate the necessary signature.

Both the openssl commands of my test to compare results generate output of more that 64 Byte. See:

$ openssl dgst -sha256 -sign prime256v1.key -out sign.sign input.bin
$ hexdump -C sign.sign
00000000  30 46 02 21 00 8b 38 52  fe dc cb 80 b1 f1 a4 ba  |0F.!..8R........|
00000010  c3 c5 a0 b6 58 9b b3 1e  28 f9 0a 03 ed 20 12 54  |....X...(.... .T|
00000020  84 23 1e 11 aa 02 21 00  b7 90 02 43 34 a1 76 5c  |.#....!....C4.v\|
00000030  16 20 b0 c3 93 af 4f a7  ba f3 ca 8b 22 3d 94 f0  |. ....O....."=..|
00000040  9f bf 3f 53 55 5b 71 88                           |..?SU[q.|
00000048

$ openssl pkeyutl -sign -in input.bin -inkey prime256v1.key -out sign2.sign
$ hexdump -C sign2.sign
00000000  30 45 02 20 53 f3 d1 56  b5 4f 53 67 d8 0a e2 0c  |0E. S..V.OSg....|
00000010  01 66 b4 8f 65 4d 74 53  67 b9 4e 11 d3 3b b3 1b  |.f..eMtSg.N..;..|
00000020  bb b2 b0 46 02 21 00 d3  2d 6c 6e 85 fd fd 53 c9  |...F.!..-ln...S.|
00000030  dd 68 45 23 23 c9 76 2e  03 f1 db 85 89 23 14 41  |.hE##.v......#.A|
00000040  79 df 5c 4b fe 5f 48                              |y.\K._H|
00000047

As explained, I first tried to do it only with openssl to compare the output.

My Idea is to gater some sensor information in the MKR1000, put it together (e.g., as a concatenated string or json) and send it to a server via http POST request. I want to also add the signature of that string (encrypted by boards private key) so I can validate the info to be sure it is coming from that board and was not altered.

The sign command was straigt put from the ECCX08.h example:

const byte input[64] = {
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
};

const int slot = 0;

[...]

 // retrieve the public key
  byte publicKey[64];
  ECCX08.generatePublicKey(slot, publicKey);

  // print the public key
  Serial.print("Public key of slot ");
  Serial.print(slot);
  Serial.print(" is:   ");
  printBufferHex(publicKey, sizeof(publicKey));

  // calculate the signature, input MUST be 64-byte array
  byte signature[64];
  ECCX08.ecSign(slot, input, signature);

  // print the signature
  Serial.print("Signature using slot ");
  Serial.print(slot);
  Serial.print(" is: ");
  printBufferHex(signature, sizeof(signature));

  Serial.println();

In my case you get the serial output of:

Signature using slot 0 is: 9A61435E1E81E63B02AC129DDDD1997B0DDD3C4B520530DAD0076222A02EF5B0DA9F877538185B96E5363FDCC00CB63AAA66D410F11A907EB81150AB6401BA6B

My pubkey is:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7eD1YJO+t68diltTlzu7ydgBdJTUFwVTH7r7HIbd
FkoWfKfu5amBYqDWVcojnH4OjKySpqkTjUGd5Uy3wleOqA==
-----END PUBLIC KEY-----

I also found out, that the signing commands reported above vary, when I repeatedly use them, what also confuses me. But the verify alwasy works, so I think there is some kind of additional information than just the encrypted hash in the output.

Right, I know that. Something like ECDSA does both (the corresponding method of the ECCX08 library is called ecdsaVerify btw.). Its gererates a hash of an stream or file and then encrypts that hash by assymetric cryptography (in this case derived from an eliptic curve).
The other end does also hash the stream or file and bilds its own hash. Decrypting the crypted hash from the other side sould lead to the same hash. Otherwise it was modified. And beeing able to decrypt by the public key in the first place lets you know, hat it was encrypted by the right person. That is the difference to your picture, as it doesn't use symmetric block cipher like AES but asymetric chiper. You have a different key for encryption and decryption and the private key always stays secure. That is why it is not possibe to export the private key from the chip. Receiver only gets the public key, which is enough to decrypt the hash and compare it to hash generated on receivers side.

Thats why I was expecting 32 byte and was confused about the fixed input size of 64 byte. The documentation does not say anithing about, that it is also hashing (what I was wondering about also) because then I would like to know the used algorithm which is not documented.
It also has an example for sha256 hash. There you also have fixed chucks of up to 64 byte input. And you need to update the algorithem in 64 byte chunks for bigger imput. (methods are int ECCX08Class::beginSHA256(), int ECCX08Class::updateSHA256(const byte data[]) and int ECCX08Class::endSHA256(byte result[])) but less input is no problem. So if sign function would also hash, it should have something similar like that.

Thank you for reassuring, that I got the concept right.

My point is, that I need to get the signing part done by the MRK1000 and the verifying part done by the server (likely by using openssl). And since I understand openssl faily good, I want to know how the ECC508 chip can be used, because it claims to have anything I need. But the way it is used in the example, I don't understand it

using https is probably the simplest way

Yes, but it only assueres the servers identiy. Or you would use mutual TLS.
By using a signed hash I wanted to get both.
Having to send credentials within an https request is not as secure in my thaught. because credentials need to be stored in a way that can be expored while the pivate key can not be exported.

My target is rather the confidentiality but the integrity and authenticity of the submitted information.

hum HTTPS over SSL/TLS is designed to provide encryption in transit too and you know where you connect

I know where I (the MRK1000) connects, but the server does not know who connects.

I want, that the info comes from who I expect it to come and is not altered on the way.

Don't get me wrong. I apprechiate your sugestions.

But I see that the ECCX08 library claims to deliver ECDSA and that is what I want for my project. I have a prolem and ECDSA seems to be a good and easy solution for it.

I just don't understand how to correctly use it or if I misunderstood what ECCX08 library can deliver.

no worries - just thinking out of the box.

I'm not ready to lock the chip on my MKR1000 so can't really check it out :wink:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.