So I was able to make some progress:
I started with the key_pair.der
and the pub_key.raw
files, that I was able to create with:
File::create("key_pair.der")?.write_all(&pkcs8_bytes)?;
File::create("pub_key.raw")?.write_all(&peer_public_key_bytes)?;
Then I used openssl
to view the public key part:
openssl pkey -inform DER -in key_pair.der -pubout -outform DER | hd
and compared it against the raw public key:
hd pub_key.raw
The delta is:
30 59 30 13 06 07 2a 86 48 ce 3d 02 01 06 08 2a
86 48 ce 3d 03 01 07 03 42 00
Which corresponds to:
SEQUENCE (2 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.10045.2.1 ecPublicKey (ANSI X9.62 public key type)
OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named elliptic curve)
BIT STRING (520 bit) ...
So to create a proper DER file from the raw public key I wrote:
let der_head = &[
0x30, 0x59, // SEQUENCE (2+89) 2 elem
0x30, 0x13, // SEQUENCE (2+19) 2 elem
0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, // OID 1.2.840.10045.2.1
0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, // OID 1.2.840.10045.3.1.7
0x03, 0x42, 0x00 // BIT STRING (2+66)
];
let mut der_file = File::create("pub_key.der").unwrap();
der_file.write_all(der_head).unwrap();
der_file.write_all(peer_public_key_bytes).unwrap();
And I verified that this file is indeed a valid DER file that looks similar to the one generated with openssl
, and was able to read it with openssl
:
openssl pkey -inform DER -pubin -in pub_key.der -text
Finally lets check that verify the signature with openssl
:
Save the message and the signature with:
File::create("message")?.write_all(&MESSAGE)?;
File::create("message.sig")?.write_all(&sig_bytes)?;
Convert the pub_key.der
into PEM format:
openssl pkey -inform DER -pubin -in pub_key.der -outform PEM -out pub_key.pem
And verify the signature:
openssl dgst -verify pub_key.pem -signature message.sig message
If there is an easier way to do this, I will happily take it.