mirror of https://github.com/status-im/nim-eth.git
remove ecdhRaw usage and replace it with ecdh+custom hash function
This commit is contained in:
parent
6053c252e7
commit
9bf2e1786b
39
eth/keys.nim
39
eth/keys.nim
|
@ -17,7 +17,7 @@
|
|||
import
|
||||
std/strformat,
|
||||
secp256k1, bearssl/hash as bhash, bearssl/rand,
|
||||
stew/[byteutils, objects, results],
|
||||
stew/[byteutils, objects, results, ptrops],
|
||||
./common/eth_hash
|
||||
|
||||
from nimcrypto/utils import burnMem
|
||||
|
@ -25,7 +25,9 @@ from nimcrypto/utils import burnMem
|
|||
export secp256k1, results, rand
|
||||
|
||||
const
|
||||
KeyLength* = SkEcdhRawSecretSize - 1
|
||||
FullKeyLength* = 33
|
||||
|
||||
KeyLength* = FullKeyLength - 1
|
||||
## Shared secret key length without format marker
|
||||
RawPublicKeySize* = SkRawPublicKeySize - 1
|
||||
## Size of uncompressed public key without format marker (0x04)
|
||||
|
@ -43,7 +45,9 @@ type
|
|||
SignatureNR* = distinct SkSignature
|
||||
## ...but ENR uses non-recoverable signatures!
|
||||
|
||||
SharedSecretFull* = SkEcdhRawSecret
|
||||
SharedSecretFull* = object
|
||||
data*: array[FullKeyLength, byte]
|
||||
|
||||
SharedSecret* = object
|
||||
data*: array[KeyLength, byte]
|
||||
|
||||
|
@ -230,11 +234,28 @@ func verify*(sig: SignatureNR, msg: openArray[byte], key: PublicKey): bool =
|
|||
let hash = keccakHash(msg)
|
||||
verify(sig, SkMessage(hash.data), key)
|
||||
|
||||
func ecdhRaw*(seckey: PrivateKey, pubkey: PublicKey): SharedSecret =
|
||||
let tmp = ecdhRaw(SkSecretKey(seckey), SkPublicKey(pubkey))
|
||||
proc ecdhSecretHash(output: ptr byte, x32, y32: ptr byte, data: pointer): cint
|
||||
{.cdecl, raises: [].} =
|
||||
copyMem(output, x32, 32)
|
||||
return 1
|
||||
|
||||
# Remove first byte!
|
||||
copyMem(addr result.data[0], unsafeAddr(tmp.data[1]), sizeof(result))
|
||||
func ecdhSecret*(seckey: PrivateKey, pubkey: PublicKey): SharedSecret =
|
||||
# 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)
|
||||
|
||||
func ecdhRawFull*(seckey: PrivateKey, pubkey: PublicKey): SharedSecretFull =
|
||||
SharedSecretFull(ecdhRaw(SkSecretKey(seckey), SkPublicKey(pubkey)))
|
||||
proc ecdhSecretFullHash(output: ptr byte, x32, y32: ptr byte, data: pointer): cint
|
||||
{.cdecl, raises: [].} =
|
||||
# output[0] = 0x02 | (y32[31] & 1)
|
||||
output[] = 0x02 or (y32.offset(31)[] and 0x01)
|
||||
copyMem(output.offset(1), x32, 32)
|
||||
return 1
|
||||
|
||||
func ecdhSecretFull*(seckey: PrivateKey, pubkey: PublicKey): SharedSecretFull =
|
||||
# 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)
|
||||
|
|
|
@ -150,7 +150,7 @@ proc authMessagePreEIP8(h: var Handshake,
|
|||
outlen = 0
|
||||
let header = cast[ptr AuthMessageV4](addr buffer[0])
|
||||
|
||||
var secret = ecdhRaw(h.host.seckey, pubkey)
|
||||
var secret = ecdhSecret(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 = ecdhRaw(h.host.seckey, pubkey)
|
||||
var secret = ecdhSecret(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 = ecdhRaw(h.host.seckey, pubkey)
|
||||
var secret = ecdhSecret(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 = ecdhRaw(h.host.seckey, pubkey)
|
||||
var secret = ecdhSecret(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 = ecdhRaw(h.ephemeral.seckey, h.remoteEPubkey)
|
||||
var shsec = ecdhSecret(h.ephemeral.seckey, h.remoteEPubkey)
|
||||
|
||||
# shared-secret = keccak(ecdhe-secret || keccak(nonce || initiator-nonce))
|
||||
ctx0.init()
|
||||
|
|
|
@ -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 = ecdhRawFull(priv, pub)
|
||||
let eph = ecdhSecretFull(priv, pub)
|
||||
|
||||
var info = newSeqOfCap[byte](keyAgreementPrefix.len + 32 * 2)
|
||||
for i, c in keyAgreementPrefix: info.add(byte(c))
|
||||
|
|
|
@ -114,8 +114,8 @@ proc eciesEncrypt*(rng: var HmacDrbgContext, input: openArray[byte],
|
|||
|
||||
var
|
||||
ephemeral = KeyPair.random(rng)
|
||||
secret = ecdhRaw(ephemeral.seckey, pubkey)
|
||||
material = kdf(secret.data)
|
||||
secret = ecdhSecret(ephemeral.seckey, pubkey)
|
||||
material = kdf(secret.data)
|
||||
|
||||
clear(secret)
|
||||
|
||||
|
@ -183,10 +183,10 @@ proc eciesDecrypt*(input: openArray[byte],
|
|||
|
||||
var
|
||||
pubkey = ? PublicKey.fromRaw(header.pubkey).mapErrTo(IncorrectKey)
|
||||
secret = ecdhRaw(seckey, pubkey)
|
||||
secret = ecdhSecret(seckey, pubkey)
|
||||
material = kdf(secret.data)
|
||||
|
||||
var material = kdf(secret.data)
|
||||
burnMem(secret)
|
||||
clear(secret)
|
||||
|
||||
copyMem(addr encKey[0], addr material[0], aes128.sizeKey)
|
||||
var macKey =
|
||||
|
|
|
@ -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 = ecdhRaw(s, p)
|
||||
let secret = ecdhSecret(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 = ecdhRaw(s, p)
|
||||
let secret = ecdhSecret(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 = ecdhRaw(s, p)
|
||||
let secret = ecdhSecret(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 = ecdhRaw(aliceSecret, bobPublic)
|
||||
var secret2 = ecdhRaw(bobSecret, alicePublic)
|
||||
var secret1 = ecdhSecret(aliceSecret, bobPublic)
|
||||
var secret2 = ecdhSecret(bobSecret, alicePublic)
|
||||
check:
|
||||
secret1 == secret2
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ suite "Discovery v5.1 Cryptographic Primitives Test Vectors":
|
|||
let
|
||||
pub = PublicKey.fromHex(publicKey)[]
|
||||
priv = PrivateKey.fromHex(secretKey)[]
|
||||
eph = ecdhRawFull(priv, pub)
|
||||
eph = ecdhSecretFull(priv, pub)
|
||||
check:
|
||||
eph.data == hexToSeqByte(sharedSecret)
|
||||
|
||||
|
|
Loading…
Reference in New Issue