nCore key hash example
This example demonstates calculating a key hash using the nShield implementation, and then manually.
-
The input to the hash includes the full domain parameters for the elliptic curve used, even though the key is represented (in nShield terms) as a named curve.
-
Different ECC key types (
ECPublic
,ECDSAPublic
,ECDHPublic
, etc) have differentHASHPREFIX
values
#!/opt/nfast/python3/bin/python3
import choosealg
import hashlib
keydata = choosealg.KeyData(['ECPublic',
'NISTP256',
0,
0x08f81421c7e89597d9b5a2bbd536f7305bcbd669194a281338cdb613bb0f9fd1,
0x2d5b7759bd9e3fcd4aea4f4853f2aaeac675aa165947e3438044f6e57ccd89c4
])
print("Public key material:")
print(keydata)
print()
print("Hash calculated by nShield implementation:")
keyhash = choosealg.calchash(keydata, choosealg.KeyHashMech('SHA1Hash'))
print(keyhash.data.hash)
print()
def S(x):
"""The representation of the integer x in little-endian form
in exactly 4 bytes."""
return x.to_bytes(4, 'little')
def B(x):
"""The representation of the integer x in little-endian form,
zero-padded to a multiple of 64 bytes."""
xbytes = (x.bit_length() + 7) // 8
return x.to_bytes(((xbytes + 63) // 64) * 64, 'little')
# Header string
input = b"nFast KeyHash\0"
# HASHPREFIX identifies key type
input += b"EC00\0"
# Curve type is prime
input += S(0)
# Field type is prime
input += S(0)
# Field bit size
input += S(256)
# Field modulus
input += B(0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff)
# Curve parameters a, b
input += B(0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc)
input += B(0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b)
# Subgroup generator G.x, G.y
input += B(0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296)
input += B(0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5)
# Subgroup order r (or sometimes n)
input += B(0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551)
# Cofactor h
input += B(1)
# Point coordinates
input += B(keydata.data.Q.x)
input += B(keydata.data.Q.y)
# Trailer
input += b"invented by nCipher 1997\0"
print("Input to hash function:")
input_hex = input.hex()
for i in range(0, len(input_hex), 64):
print(input_hex[i:i+64])
print()
print("Hash calculated manually:")
print(hashlib.sha1(input).hexdigest())
The output is as follows:
Public key material: KeyData.type= ECPublic .data.curve.name= NISTP256 .Q.flags= 0x0 .x= 0x8f81421c7e89597d9b5a2bbd536f7305bcbd669194a281338cdb613bb0f9fd1 .y= 0x2d5b7759bd9e3fcd4aea4f4853f2aaeac675aa165947e3438044f6e57ccd89c4 Hash calculated by nShield implementation: 6ac2377c eaac44ea b378518d 1b6f4ebf 0d4d0dec Input to hash function: 6e46617374204b657948617368004543303000000000000000000000010000ff ffffffffffffffffffffff00000000000000000000000001000000ffffffff00 00000000000000000000000000000000000000000000000000000000000000fc ffffffffffffffffffffff00000000000000000000000001000000ffffffff00 000000000000000000000000000000000000000000000000000000000000004b 60d2273e3cce3bf6b053ccb0061d65bc86987655bdebb3e7933aaad835c65a00 0000000000000000000000000000000000000000000000000000000000000096 c298d84539a1f4a033eb2d817d0377f240a463e5e6bcf847422ce1f2d1176b00 00000000000000000000000000000000000000000000000000000000000000f5 51bf376840b6cbce5e316b5733ce2b169e0f7c4aebe78e9b7f1afee242e34f00 0000000000000000000000000000000000000000000000000000000000000051 2563fcc2cab9f3849e17a7adfae6bcffffffffffffffff00000000ffffffff00 0000000000000000000000000000000000000000000000000000000000000001 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000d1 9f0fbb13b6cd3813284a1969d6cb5b30f736d5bba2b5d99795e8c72114f80800 00000000000000000000000000000000000000000000000000000000000000c4 89cd7ce5f6448043e3475916aa75c6eaaaf253484fea4acd3f9ebd59775b2d00 0000000000000000000000000000000000000000000000000000000000000069 6e76656e746564206279206e436970686572203139393700 Hash calculated manually: 6ac2377ceaac44eab378518d1b6f4ebf0d4d0dec