no more wild constants and rename ecdhSecret to ecdhSharedSecret

This commit is contained in:
jangko 2023-04-21 15:59:44 +07:00
parent 9bf2e1786b
commit 917888356e
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
6 changed files with 48 additions and 25 deletions

View File

@ -25,12 +25,16 @@ from nimcrypto/utils import burnMem
export secp256k1, results, rand
const
FullKeyLength* = 33
KeyLength* = SkEcdhSecretSize
## Ecdh shared secret key length without leading byte
## (publicKey * privateKey).x, where length of x is 32 bytes
FullKeyLength* = KeyLength + 1
## Ecdh shared secret with leading byte 0x02 or 0x03
KeyLength* = FullKeyLength - 1
## Shared secret key length without format marker
RawPublicKeySize* = SkRawPublicKeySize - 1
## Size of uncompressed public key without format marker (0x04)
RawSignatureSize* = SkRawRecoverableSignatureSize
RawSignatureNRSize* = SkRawSignatureSize
@ -46,9 +50,12 @@ type
## ...but ENR uses non-recoverable signatures!
SharedSecretFull* = object
## Representation of ECDH shared secret, with leading `y` byte
## (`y` is 0x02 when (publicKey * privateKey).y is even or 0x03 when odd)
data*: array[FullKeyLength, byte]
SharedSecret* = object
## Representation of ECDH shared secret, without leading `y` byte
data*: array[KeyLength, byte]
KeyPair* = distinct SkKeyPair
@ -234,28 +241,44 @@ func verify*(sig: SignatureNR, msg: openArray[byte], key: PublicKey): bool =
let hash = keccakHash(msg)
verify(sig, SkMessage(hash.data), key)
proc ecdhSecretHash(output: ptr byte, x32, y32: ptr byte, data: pointer): cint
proc ecdhSharedSecretHash(output: ptr byte, x32, y32: ptr byte, data: pointer): cint
{.cdecl, raises: [].} =
copyMem(output, x32, 32)
## Hash function used by `ecdhSharedSecret` below
# `x32` and `y32` are result of scalar multiplication of publicKey * privateKey.
# Both `x32` and `y32` are 32 bytes length.
# Take the `x32` part as ecdh shared secret.
# output length is derived from x32 length and taken from ecdh
# generic parameter `KeyLength`
copyMem(output, x32, KeyLength)
return 1
func ecdhSecret*(seckey: PrivateKey, pubkey: PublicKey): SharedSecret =
func ecdhSharedSecret*(seckey: PrivateKey, pubkey: PublicKey): SharedSecret =
## Compute ecdh agreed shared secret.
let res = ecdh[KeyLength](SkSecretKey(seckey), SkPublicKey(pubkey), ecdhSharedSecretHash, nil)
# This function only fail if the hash function return zero.
# Because our hash function always success, we can turn the error into defect
let res = ecdh[KeyLength](SkSecretKey(seckey), SkPublicKey(pubkey), ecdhSecretHash, nil)
doAssert res.isOk, $res.error
SharedSecret(data: res.get)
proc ecdhSecretFullHash(output: ptr byte, x32, y32: ptr byte, data: pointer): cint
proc ecdhSharedSecretFullHash(output: ptr byte, x32, y32: ptr byte, data: pointer): cint
{.cdecl, raises: [].} =
## Hash function used by `ecdhSharedSecretFull` below
# `x32` and `y32` are result of scalar multiplication of publicKey * privateKey.
# Leading byte is 0x02 if `y32` is even and 0x03 if odd. Then concat with `x32`.
# output length is derived from `x32` length + 1 and taken from ecdh
# generic parameter `FullKeyLength`
# output[0] = 0x02 | (y32[31] & 1)
output[] = 0x02 or (y32.offset(31)[] and 0x01)
copyMem(output.offset(1), x32, 32)
copyMem(output.offset(1), x32, KeyLength)
return 1
func ecdhSecretFull*(seckey: PrivateKey, pubkey: PublicKey): SharedSecretFull =
func ecdhSharedSecretFull*(seckey: PrivateKey, pubkey: PublicKey): SharedSecretFull =
## Compute ecdh agreed shared secret with leading byte.
let res = ecdh[FullKeyLength](SkSecretKey(seckey), SkPublicKey(pubkey), ecdhSharedSecretFullHash, nil)
# This function only fail if the hash function return zero.
# Because our hash function always success, we can turn the error into defect
let res = ecdh[FullKeyLength](SkSecretKey(seckey), SkPublicKey(pubkey), ecdhSecretFullHash, nil)
doAssert res.isOk, $res.error
SharedSecretFull(data: res.get)

View File

@ -150,7 +150,7 @@ proc authMessagePreEIP8(h: var Handshake,
outlen = 0
let header = cast[ptr AuthMessageV4](addr buffer[0])
var secret = ecdhSecret(h.host.seckey, pubkey)
var secret = ecdhSharedSecret(h.host.seckey, pubkey)
secret.data = secret.data xor h.initiatorNonce
let signature = sign(h.ephemeral.seckey, SkMessage(secret.data))
@ -190,7 +190,7 @@ proc authMessageEIP8(h: var Handshake,
doAssert(EIP8 in h.flags)
outlen = 0
var secret = ecdhSecret(h.host.seckey, pubkey)
var secret = ecdhSharedSecret(h.host.seckey, pubkey)
secret.data = secret.data xor h.initiatorNonce
let signature = sign(h.ephemeral.seckey, SkMessage(secret.data))
@ -364,7 +364,7 @@ proc decodeAuthMessageV4(h: var Handshake, m: openArray[byte]): AuthResult[void]
pubkey = ? PublicKey.fromRaw(header.pubkey).mapErrTo(InvalidPubKey)
signature = ? Signature.fromRaw(header.signature).mapErrTo(SignatureError)
var secret = ecdhSecret(h.host.seckey, pubkey)
var secret = ecdhSharedSecret(h.host.seckey, pubkey)
secret.data = secret.data xor header.nonce
var recovered = recover(signature, SkMessage(secret.data))
@ -415,7 +415,7 @@ proc decodeAuthMessageEIP8(h: var Handshake, m: openArray[byte]): AuthResult[voi
pubkey = ? PublicKey.fromRaw(pubkeyBr).mapErrTo(InvalidPubKey)
nonce = toArray(KeyLength, nonceBr)
var secret = ecdhSecret(h.host.seckey, pubkey)
var secret = ecdhSharedSecret(h.host.seckey, pubkey)
secret.data = secret.data xor nonce
let recovered = recover(signature, SkMessage(secret.data))
@ -524,7 +524,7 @@ proc getSecrets*(
secret: ConnectionSecret
# ecdhe-secret = ecdh.agree(ephemeral-privkey, remote-ephemeral-pubk)
var shsec = ecdhSecret(h.ephemeral.seckey, h.remoteEPubkey)
var shsec = ecdhSharedSecret(h.ephemeral.seckey, h.remoteEPubkey)
# shared-secret = keccak(ecdhe-secret || keccak(nonce || initiator-nonce))
ctx0.init()

View File

@ -138,7 +138,7 @@ proc verifyIdSignature*(sig: SignatureNR, challengeData, ephKey: openArray[byte]
proc deriveKeys*(n1, n2: NodeId, priv: PrivateKey, pub: PublicKey,
challengeData: openArray[byte]): HandshakeSecrets =
let eph = ecdhSecretFull(priv, pub)
let eph = ecdhSharedSecretFull(priv, pub)
var info = newSeqOfCap[byte](keyAgreementPrefix.len + 32 * 2)
for i, c in keyAgreementPrefix: info.add(byte(c))

View File

@ -114,7 +114,7 @@ proc eciesEncrypt*(rng: var HmacDrbgContext, input: openArray[byte],
var
ephemeral = KeyPair.random(rng)
secret = ecdhSecret(ephemeral.seckey, pubkey)
secret = ecdhSharedSecret(ephemeral.seckey, pubkey)
material = kdf(secret.data)
clear(secret)
@ -183,7 +183,7 @@ proc eciesDecrypt*(input: openArray[byte],
var
pubkey = ? PublicKey.fromRaw(header.pubkey).mapErrTo(IncorrectKey)
secret = ecdhSecret(seckey, pubkey)
secret = ecdhSharedSecret(seckey, pubkey)
material = kdf(secret.data)
clear(secret)

View File

@ -160,7 +160,7 @@ suite "ECC/ECDSA/ECDHE tests suite":
var s = PrivateKey.fromHex(privateKeys[i])[]
var p = PublicKey.fromHex(stripSpaces(publicKeys[i]))[]
let expect = fromHex(stripSpaces(sharedSecrets[i]))
let secret = ecdhSecret(s, p)
let secret = ecdhSharedSecret(s, p)
check:
expect == secret.data
@ -172,7 +172,7 @@ suite "ECC/ECDSA/ECDHE tests suite":
var s = PrivateKey.fromRaw(keccak256.digest("ecdhAgree").data)[]
var p = s.toPublicKey()
let expect = fromHex(stripSpaces(expectm))
let secret = ecdhSecret(s, p)
let secret = ecdhSharedSecret(s, p)
check:
expect == secret.data
@ -189,7 +189,7 @@ suite "ECC/ECDSA/ECDHE tests suite":
var s = PrivateKey.fromHex(stripSpaces(s0))[]
var p = PublicKey.fromHex(stripSpaces(p0))[]
let expect = fromHex(stripSpaces(e0))
let secret = ecdhSecret(s, p)
let secret = ecdhSharedSecret(s, p)
check:
compare(expect, secret.data) == true
@ -242,8 +242,8 @@ suite "ECC/ECDSA/ECDHE tests suite":
var alicePublic = aliceSecret.toPublicKey()
var bobSecret = PrivateKey.random(rng[])
var bobPublic = bobSecret.toPublicKey()
var secret1 = ecdhSecret(aliceSecret, bobPublic)
var secret2 = ecdhSecret(bobSecret, alicePublic)
var secret1 = ecdhSharedSecret(aliceSecret, bobPublic)
var secret2 = ecdhSharedSecret(bobSecret, alicePublic)
check:
secret1 == secret2

View File

@ -180,7 +180,7 @@ suite "Discovery v5.1 Cryptographic Primitives Test Vectors":
let
pub = PublicKey.fromHex(publicKey)[]
priv = PrivateKey.fromHex(secretKey)[]
eph = ecdhSecretFull(priv, pub)
eph = ecdhSharedSecretFull(priv, pub)
check:
eph.data == hexToSeqByte(sharedSecret)