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 different HASHPREFIX 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