The ATECC508A[0] is a cryptographic authentication chip developed by
MicroChip Technology. A PCB that makes the ATECC508A’s pins easily
accessible was developed by Pete Lewis at SparkFun (1).
In this tutorial,
the 64 byte uncompressed NIST P256 / Curve P-256 / secp256r1 /
prime256v1 public key represented by a hex array grouped by byte [for
a comparison see [2]).
An example public key is:
uint8_t publicKey[64] = {
0xF9, 0xC3, 0x6F, 0x89, 0x64, 0x62, 0x33, 0x78, 0xBD, 0xC0, 0x68, 0xD4, 0xBC, 0xE0, 0x7E, 0xD1,
0x7C, 0x8F, 0xA4, 0x86, 0xF9, 0xAC, 0x0C, 0x26, 0x13, 0xCA, 0x3C, 0x8C, 0x30, 0x6D, 0x7B, 0xB6,
0x1C, 0xD3, 0x67, 0x17, 0xB8, 0xAC, 0x5E, 0x4F, 0xEA, 0x8A, 0xD2, 0x3D, 0xC8, 0xD0, 0x78, 0x3C,
0x23, 0x18, 0xEE, 0x4A, 0xD7, 0xA8, 0x0D, 0xB6, 0xE0, 0x02, 0x6A, 0xD0, 0xB0, 0x72, 0xA2, 0x4F
};
When working with a few cryptography libraries both 3rd party, and those produced by the manufacturer of the ATECC508A, MicroChipTech, I discovered a library called CryptoAuthTools.
In a file called ecdh.py in the CryptoAuthTools library [3], I found out about the structure of the data:
# Convert device public key to a cryptography public key object
device_pub = ec.EllipticCurvePublicNumbers(
curve=ec.SECP256R1(),
x=int_from_bytes(device_pub[0:32], byteorder='big'),
y=int_from_bytes(device_pub[32:64], byteorder='big'),
).public_key(default_backend())
The public key is a point. From the literature, I infer this is the uncompressed form. In Practical Cryptography for Developers, “The public keys in the ECC are EC points - pairs of integer coordinates {x, y}, laying on the curve.
An example public key is:
uint8_t publicKey[64] = {
0xF9, 0xC3, 0x6F, 0x89, 0x64, 0x62, 0x33, 0x78, 0xBD, 0xC0, 0x68, 0xD4, 0xBC, 0xE0, 0x7E, 0xD1,
0x7C, 0x8F, 0xA4, 0x86, 0xF9, 0xAC, 0x0C, 0x26, 0x13, 0xCA, 0x3C, 0x8C, 0x30, 0x6D, 0x7B, 0xB6,
0x1C, 0xD3, 0x67, 0x17, 0xB8, 0xAC, 0x5E, 0x4F, 0xEA, 0x8A, 0xD2, 0x3D, 0xC8, 0xD0, 0x78, 0x3C,
0x23, 0x18, 0xEE, 0x4A, 0xD7, 0xA8, 0x0D, 0xB6, 0xE0, 0x02, 0x6A, 0xD0, 0xB0, 0x72, 0xA2, 0x4F
};
When working with a few cryptography libraries both 3rd party, and those produced by the manufacturer of the ATECC508A, MicroChipTech, I discovered a library called CryptoAuthTools.
In a file called ecdh.py in the CryptoAuthTools library [3], I found out about the structure of the data:
# Convert device public key to a cryptography public key object
device_pub = ec.EllipticCurvePublicNumbers(
curve=ec.SECP256R1(),
x=int_from_bytes(device_pub[0:32], byteorder='big'),
y=int_from_bytes(device_pub[32:64], byteorder='big'),
).public_key(default_backend())
The public key is a point. From the literature, I infer this is the uncompressed form. In Practical Cryptography for Developers, “The public keys in the ECC are EC points - pairs of integer coordinates {x, y}, laying on the curve.
Due
to their special properties, EC points can be compressed to just one
coordinate + 1 bit (odd or even). Thus
the compressed public key, corresponding to a 256-bit ECC private
key, is a 257-bit integer.”.
Further,
to broaden understanding and utilize more literature I can look at
the Koblitz curve behind Bitcoin, secp256k1
and
compare it to secp256rl. In Bjoernsen’s paper [4],
“The
main difference between secp256k1 and secp256r1 is that secp256k1 is
a Koblitz curve, while secp256r1 is a prime field curve. Koblitz
curves are generally known to be a few bits weaker than prime field
curves, but when talking about 256-bit curves, it has little impact.”
Both
secp256rl
and
secp256k1
are
elliptic curves. These
Elliptic
curves have
a Generator
point
G
and an Order n for
their key-pair.
An ECDSA key-pair consists of a private key which is an integer and a public key which is an elliptic curve point [7].
An ECDSA key-pair consists of a private key which is an integer and a public key which is an elliptic curve point [7].
The
relation between the public key and private key is (public key) =
(private key) * G .
P-256
is the same as secp256rl
according
to Mrinal
Wadhwa’s presentation [5]. The
curve parameters, including
the generator point and order n,
for secp256rl
are described in section D.1.2.3
and
D.2.3 Curve
P-256 in the FIPS PUB 186-4 : Digital Signature Standard (DSS) (page
100 and 102) [6].
A
secp256rl public key can be encoded as
a uncompressed public key with a 0x04 prefix or a compressed public
key with an
0x03 or 0x02 prefix with the fast ecdsa library [8].
Due
to the nature of the ECC curve, only one coordinate from the public
key needs to be stored. It becomes a compressed public key. In
technical terms: “
The
public key EC point {x, y} can be compressed to just one of the
coordinates + 1 bit (parity). For the secp256k1 curve, the private
key is 256-bit integer (32 bytes) and the compressed public key is
257-bit integer (~ 33 bytes) [7].
The
difference between the public and private key is described:
“public key: A coordinate that corresponds to a private key, but does not need to be kept secret.
“public key: A coordinate that corresponds to a private key, but does not need to be kept secret.
A
public key can be calculated from a private key, but not vice versa.
A public key can be used to determine
if
a signature is genuine by using ECDSA to validate that a signature
was generated by the private key that corresponds
to
the public key that has been proffered, without requiring the private
key to be divulged. In Bitcoin, public keys are either compressed or
uncompressed. Compressed public keys are 33 bytes, consisting of a
prefix either 0x02 or 0x03, and a 256-bit integer called x.
Uncompressed keys are 65 bytes, consisting of constant prefix (0x04),
followed by two 256-bit integers called x and y (2 * 32 bytes). The
prefix of a compressed key allows for the y value to be derived from
the x value.” [9]
More information about ECC, including graphical explanations, can be found at [10].
I would like to do two things. One is to import the public key from the crpyto chip into a library hosted on my laptop. Two is to import the signed message and original message and verify it with the public key. I believe that a bridge to the answer to this starts with examining the "ECDSA Sign" and "ECDSA Verify Signature" sections in [7]
Early attempts at importing the public key with fastecdsa were unsuccessful. The points were not on the curve.
See:
https://gist.github.com/bshambaugh/6f0fe5a63f96b0e0a95b404cc103e9c4
Okay, it works now:
https://forum.sparkfun.com/viewtopic.php?f=102&t=53408&p=217284#p217284
The message and the signed message are as follows:
uint8_t message[32] = {
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
};
uint8_t signature[64] = {
0xD1, 0x84, 0x7E, 0x48, 0xD1, 0x40, 0x52, 0x87, 0xFF, 0x97, 0x49, 0x65, 0x66, 0x7D, 0x57, 0xE7,
0xF4, 0x38, 0xF2, 0x02, 0xA9, 0x8C, 0x9D, 0x17, 0x27, 0x5C, 0x59, 0x92, 0x2D, 0x12, 0x2B, 0xE7,
0xF9, 0x0D, 0x7A, 0x68, 0xB1, 0x6A, 0xB0, 0x5D, 0x47, 0x2C, 0x59, 0x1A, 0xDF, 0xC3, 0xCA, 0x77,
0x20, 0x4E, 0xC6, 0xAB, 0x8A, 0xC7, 0x99, 0x53, 0xE5, 0x14, 0xD2, 0x82, 0x04, 0x4F, 0x50, 0xB9
};
[0] http://ww1.microchip.com/downloads/en/DeviceDoc/20005928A.pdf
More information about ECC, including graphical explanations, can be found at [10].
I would like to do two things. One is to import the public key from the crpyto chip into a library hosted on my laptop. Two is to import the signed message and original message and verify it with the public key. I believe that a bridge to the answer to this starts with examining the "ECDSA Sign" and "ECDSA Verify Signature" sections in [7]
Early attempts at importing the public key with fastecdsa were unsuccessful. The points were not on the curve.
See:
https://gist.github.com/bshambaugh/6f0fe5a63f96b0e0a95b404cc103e9c4
Okay, it works now:
https://forum.sparkfun.com/viewtopic.php?f=102&t=53408&p=217284#p217284
The message and the signed message are as follows:
uint8_t message[32] = {
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
};
uint8_t signature[64] = {
0xD1, 0x84, 0x7E, 0x48, 0xD1, 0x40, 0x52, 0x87, 0xFF, 0x97, 0x49, 0x65, 0x66, 0x7D, 0x57, 0xE7,
0xF4, 0x38, 0xF2, 0x02, 0xA9, 0x8C, 0x9D, 0x17, 0x27, 0x5C, 0x59, 0x92, 0x2D, 0x12, 0x2B, 0xE7,
0xF9, 0x0D, 0x7A, 0x68, 0xB1, 0x6A, 0xB0, 0x5D, 0x47, 0x2C, 0x59, 0x1A, 0xDF, 0xC3, 0xCA, 0x77,
0x20, 0x4E, 0xC6, 0xAB, 0x8A, 0xC7, 0x99, 0x53, 0xE5, 0x14, 0xD2, 0x82, 0x04, 0x4F, 0x50, 0xB9
};
[0] http://ww1.microchip.com/downloads/en/DeviceDoc/20005928A.pdf
[1]
https://learn.sparkfun.com/tutorials/cryptographic-co-processor-atecc508a-qwiic-hookup-guide/
[2] https://cryptii.com/pipes/base64-to-hex
[2] https://cryptii.com/pipes/base64-to-hex
[3]
https://github.com/MicrochipTech/cryptoauthtools/blob/master/python/examples/ecdh.py#L101-L105
[4] http://koclab.cs.ucsb.edu/teaching/ecc/project/2015Projects/Bjoernsen.pdf
[4] http://koclab.cs.ucsb.edu/teaching/ecc/project/2015Projects/Bjoernsen.pdf