This is an implementation of ECDSA signature verification with Curve P-256, based on a minimum subset of source files from the TinyCrypt cryptographic library, with nearly no modification (cf., diffs). It verifies the signature against a 256-bit hash digest of the payload message: a natural choice of the hash algorithm is SHA-256, and we will assume it.
The API contains only one function
/**
* @brief Verify an ECDSA-P256 signature on a SHA-256 digest
* @return returns TINYP256_OK if the signature is valid
* returns TINYP256_FAIL if an error occurred or the signature is
* invalid
*
* @param pubkey IN -- ECDSA-P256 public key. Must point to a 64-byte buffer
* containing an uncompressed point in affine coordinates (Qx, Qy)
* @param pubkey_len IN -- Size of public key buffer in bytes. Must be 64.
* @param digest IN -- The SHA-256 digest of the message to verify. Must point to a 32-byte buffer.
* @param digest_len IN -- Size of SHA-256 digest buffer in bytes. Must be 32.
* @param signature IN -- ECDSA-P256 signature value. Must point to a 64-byte buffer
* containing the raw (r, s) value
* @param signature_len IN -- Size of sig buffer in bytes. Must be 64.
*
*/
tinyp256_t tinyp256_verify(
const uint8_t *pubkey, uint16_t pubkey_len,
uint8_t *digest, uint16_t digest_len,
uint8_t *signature, uint16_t signature_len);
Tested with "OpenSSL 3.1.1 30 May 2023" (Homebrew) on macOS and "OpenSSL 1.1.1 11 Sep 2018" on Ubuntu/Linux.
-
Generate key pair
Generate private key
private.pem
openssl ecparam -name prime256v1 -genkey -noout -out private.pem
Get public key
public.pem
from private keyopenssl ec -in private.pem -pubout -out public.pem
-
Sign payload message, using SHA-256 as message digest
Suppose the payload message to sign is
msg.bin
. Get ECDSA-P256-SHA256 signaturemsg.sig.bin
openssl dgst -sha256 -sign private.pem -out msg.sig.bin msg.bin
Signature can be verified with OpenSSL using command
# See "Verification OK" upon success, "Verification Failure" otherwise openssl dgst -verify public.pem -keyform PEM -sha256 \ -signature msg.sig.bin -binary msg.bin
Sample files
private.pem
,public.pem
,msg.bin
andmsg.sig.bin
can be found in testdata/.
Obtain C-styled bytes arrays pointed to by pubkey
, digest
and signature
as
follows. Feed tinyp256_verify()
with them for signature verification.
-
Public key (
pubkey
)openssl ec -pubin -in public.pem -outform DER 2>/dev/null | xxd -i -s 27
-
SHA-256 hash digest (
digest
) of message to verifyopenssl dgst -sha256 -binary msg.bin | xxd -i
-
Signature (
signature
)openssl asn1parse -in msg.sig.bin -inform DER \ | awk -F':' '{print $4}' \ | awk 'NF > 0' \ | awk '{printf "%064s", $0}' \ | tr ' ' 0 \ | xxd -r -p \ | xxd -i
Note that we need to pad the
r
,s
values in hex with leading zeros so that they are 32-byte long, if needed - that's whatawk '{printf "%064s", $0} | tr ' ' 0
is for.
Sample byte arrays pubkey
, digest
and signature
can be found in
test_tinyp256.c. To test, in repository's directory root
make
./test_tinyp256