keys: get rid of deprecated calls (#213)

This commit is contained in:
Jacek Sieka 2020-04-04 18:44:01 +02:00 committed by GitHub
parent 42b36d1aef
commit ac5bbe4d3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 441 additions and 641 deletions

View File

@ -177,7 +177,7 @@ proc encryptKey(seckey: PrivateKey,
if cryptkind == AES128CTR: if cryptkind == AES128CTR:
var ctx: CTR[aes128] var ctx: CTR[aes128]
ctx.init(toOpenArray(key, 0, 15), iv) ctx.init(toOpenArray(key, 0, 15), iv)
ctx.encrypt(seckey.data, crypttext) ctx.encrypt(seckey.toRaw(), crypttext)
ctx.clear() ctx.clear()
result = Success result = Success
else: else:
@ -308,7 +308,7 @@ proc createKeyFileJson*(seckey: PrivateKey,
outjson = %* outjson = %*
{ {
"address": seckey.getPublicKey().toAddress(false), "address": seckey.toPublicKey().tryGet().toAddress(false),
"crypto": { "crypto": {
"cipher": $cryptkind, "cipher": $cryptkind,
"cipherparams": { "cipherparams": {
@ -394,7 +394,7 @@ proc decodeKeyFileJson*(j: JsonNode,
if res != Success: if res != Success:
return res return res
try: try:
seckey = initPrivateKey(plaintext) seckey = PrivateKey.fromRaw(plaintext).tryGet()
except CatchableError: except CatchableError:
return IncorrectPrivateKey return IncorrectPrivateKey
result = Success result = Success

View File

@ -29,6 +29,8 @@ const
## Size of uncompressed public key without format marker (0x04) ## Size of uncompressed public key without format marker (0x04)
RawSignatureSize* = SkRawRecoverableSignatureSize RawSignatureSize* = SkRawRecoverableSignatureSize
RawSignatureNRSize* = SkRawSignatureSize
type type
PrivateKey* = distinct SkSecretKey PrivateKey* = distinct SkSecretKey
@ -61,6 +63,8 @@ proc toRaw*(seckey: PrivateKey): array[SkRawSecretKeySize, byte] {.borrow.}
proc toPublicKey*(seckey: PrivateKey): SkResult[PublicKey] = proc toPublicKey*(seckey: PrivateKey): SkResult[PublicKey] =
SkSecretKey(seckey).toPublicKey().mapConvert(PublicKey) SkSecretKey(seckey).toPublicKey().mapConvert(PublicKey)
proc verify*(seckey: PrivateKey): bool {.borrow.}
proc fromRaw*(T: type PublicKey, data: openArray[byte]): SkResult[T] = proc fromRaw*(T: type PublicKey, data: openArray[byte]): SkResult[T] =
if data.len() == SkRawCompressedPubKeySize: if data.len() == SkRawCompressedPubKeySize:
return SkPublicKey.fromRaw(data).mapConvert(PublicKey) return SkPublicKey.fromRaw(data).mapConvert(PublicKey)
@ -84,11 +88,16 @@ proc toRaw*(pubkey: PublicKey): array[RawPublicKeySize, byte] =
proc toRawCompressed*(pubkey: PublicKey): array[33, byte] {.borrow.} proc toRawCompressed*(pubkey: PublicKey): array[33, byte] {.borrow.}
proc random*(t: type KeyPair): SkResult[KeyPair] = proc random*(T: type KeyPair): SkResult[T] =
let tmp = ?SkKeypair.random() let tmp = ?SkKeypair.random()
ok(KeyPair(seckey: PrivateKey(tmp.seckey), pubkey: PublicKey(tmp.pubkey))) ok(T(seckey: PrivateKey(tmp.seckey), pubkey: PublicKey(tmp.pubkey)))
proc fromRaw(T: type Signature, data: openArray[byte]): SkResult[T] = proc toKeyPair*(seckey: PrivateKey): SkResult[KeyPair] =
let
pubkey = seckey.toPublicKey()
pubkey and ok(KeyPair(seckey: seckey, pubkey: pubkey[]))
proc fromRaw*(T: type Signature, data: openArray[byte]): SkResult[T] =
SkRecoverableSignature.fromRaw(data).mapConvert(Signature) SkRecoverableSignature.fromRaw(data).mapConvert(Signature)
proc fromHex*(T: type Signature, data: string): SkResult[T] = proc fromHex*(T: type Signature, data: string): SkResult[T] =
@ -96,6 +105,11 @@ proc fromHex*(T: type Signature, data: string): SkResult[T] =
proc toRaw*(sig: Signature): array[RawSignatureSize, byte] {.borrow.} proc toRaw*(sig: Signature): array[RawSignatureSize, byte] {.borrow.}
proc fromRaw*(T: type SignatureNR, data: openArray[byte]): SkResult[T] =
SkSignature.fromRaw(data).mapConvert(SignatureNR)
proc toRaw*(sig: SignatureNR): array[RawSignatureNRSize, byte] {.borrow.}
proc toAddress*(pubkey: PublicKey, with0x = true): string = proc toAddress*(pubkey: PublicKey, with0x = true): string =
## Convert public key to hexadecimal string address. ## Convert public key to hexadecimal string address.
var hash = keccak256.digest(pubkey.toRaw()) var hash = keccak256.digest(pubkey.toRaw())
@ -180,272 +194,39 @@ proc clear*(v: var KeyPair) =
proc clear*(v: var SharedSecret) = burnMem(v.data) proc clear*(v: var SharedSecret) = burnMem(v.data)
proc clear*(v: var SharedSecretFull) = burnMem(v.data) proc clear*(v: var SharedSecretFull) = burnMem(v.data)
proc sign*(seckey: PrivateKey, msg: SkMessage): SkResult[Signature] =
signRecoverable(SkSecretKey(seckey), msg).mapConvert(Signature)
# Backwards compat - the functions in here are deprecated and should be moved proc sign*(seckey: PrivateKey, msg: openArray[byte]): SkResult[Signature] =
# reimplemented using functions that return Result instead! let hash = keccak256.digest(msg)
sign(seckey, hash)
{.pop.} # raises proc signNR*(seckey: PrivateKey, msg: SkMessage): SkResult[SignatureNR] =
sign(SkSecretKey(seckey), msg).mapConvert(SignatureNR)
from nimcrypto/utils import stripSpaces proc signNR*(seckey: PrivateKey, msg: openArray[byte]): SkResult[SignatureNR] =
let hash = keccak256.digest(msg)
signNR(seckey, hash)
type proc recover*(sig: Signature, msg: SkMessage): SkResult[PublicKey] =
EthKeysException* {.deprecated.} = object of CatchableError recover(SkRecoverableSignature(sig), msg).mapConvert(PublicKey)
Secp256k1Exception* {.deprecated.} = object of CatchableError
EthKeysStatus* {.deprecated.} = enum proc recover*(sig: Signature, msg: openArray[byte]): SkResult[PublicKey] =
Success let hash = keccak256.digest(msg)
Error recover(sig, hash)
template data*(pubkey: PublicKey): auto = proc verify*(sig: SignatureNR, msg: SkMessage, key: PublicKey): bool =
SkPublicKey(pubkey).data verify(SkSignature(sig), msg, SkPublicKey(key))
template data*(seckey: PrivateKey): auto = proc verify*(sig: SignatureNR, msg: openArray[byte], key: PublicKey): bool =
SkSecretKey(seckey).data let hash = keccak256.digest(msg)
verify(sig, hash, key)
template data*(sig: Signature): auto = proc ecdhRaw*(seckey: PrivateKey, pubkey: PublicKey): SkResult[SharedSecret] =
SkRecoverableSignature(sig).data ecdhRaw(
proc isZeroKey*(seckey: PrivateKey): bool {.deprecated.} =
## Check if private key `seckey` contains only 0 bytes.
# TODO this is a weird check - better would be to check if the key is valid!
result = true
for i in seckey.data: # constant time, loop all bytes always
if i != byte(0):
result = false
proc isZeroKey*(pubkey: PublicKey): bool {.deprecated.} =
## Check if public key `pubkey` contains only 0 bytes.
# TODO this is a weird check - better would be to check if the key is valid!
result = true
for i in pubkey.data: # constant time, loop all bytes always
if i != byte(0):
result = false
proc newPrivateKey*(): PrivateKey {.deprecated: "random".} =
let key = PrivateKey.random()
if key.isErr:
raise newException(Secp256k1Exception, $key.error)
key[]
proc newKeyPair*(): KeyPair {.deprecated: "random".} =
let kp = KeyPair.random()
if kp.isErr:
raise newException(Secp256k1Exception, $kp.error)
kp[]
proc getPublicKey*(seckey: PrivateKey): PublicKey {.deprecated: "toPublicKey".} =
let key = seckey.toPublicKey()
if key.isErr:
raise newException(Secp256k1Exception, "invalid private key")
key[]
proc ecdhAgree*(
seckey: PrivateKey, pubkey: PublicKey,
s: var SharedSecret): EthKeysStatus {.deprecated.} =
let v = ecdhRaw(
SkSecretKey(seckey), SkPublicKey(pubkey)).map proc(v: auto): SharedSecret = SkSecretKey(seckey), SkPublicKey(pubkey)).map proc(v: auto): SharedSecret =
copyMem(addr result.data[0], unsafeAddr(v.data[1]), sizeof(result)) # Remove first byte!
copyMem(addr result.data[0], unsafeAddr(v.data[1]), sizeof(result))
if v.isOk(): proc ecdhRawFull*(seckey: PrivateKey, pubkey: PublicKey): SkResult[SharedSecretFull] =
s = v[] ecdhRaw(SkSecretKey(seckey), SkPublicKey(pubkey)).mapconvert(SharedSecretFull)
return Success
return Error
proc getRaw*(
pubkey: PublicKey): array[RawPublicKeySize, byte] {.deprecated: "toRaw".} =
pubkey.toRaw()
proc getRawCompressed*(
pubkey: PublicKey): array[SkRawCompressedPubKeySize, byte] {.
deprecated: "toRawCompressed".} =
pubkey.toRawCompressed()
proc recoverPublicKey*(
data: openArray[byte], pubkey: var PublicKey): EthKeysStatus {.
deprecated: "fromRaw".} =
let v = PublicKey.fromRaw(data)
if v.isOk():
pubkey = v[]
return Success
return Error
proc signRawMessage*(data: openarray[byte], seckey: PrivateKey,
signature: var Signature): EthKeysStatus {.deprecated.} =
if len(data) != SkMessageSize:
return Error
let sig = signRecoverable(
SkSecretKey(seckey), SkMessage(data: toArray(32, data.toOpenArray(0, 31))))
if sig.isOk():
signature = Signature(sig[])
return Success
return Error
proc signRawMessage*(data: openarray[byte], seckey: PrivateKey,
signature: var SignatureNR): EthKeysStatus {.deprecated.} =
## Sign message `data` of `KeyLength` size using private key `seckey` and
## store result into `signature`.
let length = len(data)
if length != KeyLength:
return(EthKeysStatus.Error)
let sig = sign(
SkSecretKey(seckey), SkMessage(data: toArray(32, data.toOpenArray(0, 31))))
if sig.isOk():
signature = SignatureNR(sig[])
return Success
return Error
proc signMessage*(seckey: PrivateKey,
data: openarray[byte]): Signature {.deprecated.} =
let hash = keccak256.digest(data)
if signRawMessage(hash.data, seckey, result) != EthKeysStatus.Success:
raise newException(EthKeysException, "signature failed")
proc getRaw*(
s: SignatureNR): array[SkRawSignatureSize, byte] {.deprecated: "toRaw".} =
## Converts signature `s` to serialized form.
SkSignature(s).toRaw()
proc getRaw*(
s: Signature): array[SkRawRecoverableSignatureSize, byte] {.
deprecated: "toRaw".} =
## Converts signature `s` to serialized form.
SkRecoverableSignature(s).toRaw()
proc recoverSignatureKey*(signature: Signature,
msg: openarray[byte],
pubkey: var PublicKey): EthKeysStatus {.deprecated.} =
if len(msg) < SkMessageSize:
return Error
let pk = recover(
SkRecoverableSignature(signature),
SkMessage(data: toArray(32, msg.toOpenArray(0, 31))))
if pk.isErr(): return Error
pubkey = PublicKey(pk[])
return Success
proc recoverSignatureKey*(data: openarray[byte],
msg: openarray[byte],
pubkey: var PublicKey): EthKeysStatus {.deprecated.} =
let signature = SkRecoverableSignature.fromRaw(data)
if signature.isErr(): return Error
if len(msg) < SkMessageSize:
return Error
let pk = recover(
SkRecoverableSignature(signature[]),
SkMessage(data: toArray(32, msg.toOpenArray(0, 31))))
if pk.isErr(): return Error
pubkey = PublicKey(pk[])
return Success
proc initPrivateKey*(
data: openArray[byte]): PrivateKey {.deprecated: "PrivateKey.fromRaw".} =
let res = PrivateKey.fromRaw(data)
if res.isOk():
return res[]
raise (ref EthKeysException)(msg: $res.error)
proc initPrivateKey*(
data: string): PrivateKey {.deprecated: "PrivateKey.fromHex".} =
let res = PrivateKey.fromHex(stripSpaces(data))
if res.isOk():
return res[]
raise (ref EthKeysException)(msg: $res.error)
proc initPublicKey*(
hexstr: string): PublicKey {.deprecated: "PublicKey.fromHex".} =
let pk = PublicKey.fromHex(stripSpaces(hexstr))
if pk.isOk(): return pk[]
raise newException(EthKeysException, $pk.error)
proc initPublicKey*(data: openarray[byte]): PublicKey {.deprecated.} =
let pk = PublicKey.fromRaw(data)
if pk.isOk(): return pk[]
raise newException(EthKeysException, $pk.error)
proc signMessage*(seckey: PrivateKey, data: string): Signature {.deprecated.} =
signMessage(seckey, cast[seq[byte]](data))
proc toKeyPair*(key: PrivateKey): KeyPair {.deprecated.} =
KeyPair(seckey: key, pubkey: key.getPublicKey())
proc initSignature*(data: openArray[byte]): Signature {.deprecated.} =
let sig = SkRecoverableSignature.fromRaw(data)
if sig.isOk(): return Signature(sig[])
raise newException(EthKeysException, $sig.error)
proc initSignature*(hexstr: string): Signature {.deprecated.} =
let sig = SkRecoverableSignature.fromHex(stripSpaces(hexstr))
if sig.isOk(): return Signature(sig[])
raise newException(EthKeysException, $sig.error)
proc recoverSignature*(data: openarray[byte],
signature: var Signature): EthKeysStatus {.deprecated.} =
## Deprecated, use `parseCompact` instead
if data.len < RawSignatureSize:
return(EthKeysStatus.Error)
let sig = SkRecoverableSignature.fromRaw(data)
if sig.isErr():
return Error
signature = Signature(sig[])
return Success
proc recoverKeyFromSignature*(signature: Signature,
hash: MDigest[256]): PublicKey {.deprecated.} =
## Recover public key from signature `signature` using `message`.
let key = recover(SkRecoverableSignature(signature), hash)
if key.isOk():
return PublicKey(key[])
raise newException(EthKeysException, $key.error)
proc recoverKeyFromSignature*(
signature: Signature,
message: openArray[byte]): PublicKey {.deprecated.} =
let hash = keccak256.digest(message)
recoverKeyFromSignature(signature, hash)
proc recoverKeyFromSignature*(
signature: Signature, data: string): PublicKey {.deprecated.} =
recoverKeyFromSignature(signature, cast[seq[byte]](data))
proc parseCompact*(
signature: var SignatureNR,
data: openarray[byte]): EthKeysStatus {.deprecated.} =
let sig = SkSignature.fromRaw(data)
if sig.isErr():
return Error
signature = SignatureNR(sig[])
return Success
proc verifySignatureRaw*(
signature: SignatureNR, message: openarray[byte],
publicKey: PublicKey): EthKeysStatus {.deprecated.} =
## Verify `signature` using original `message` (32 bytes) and `publicKey`.
if verify(
SkSignature(signature),
SkMessage(data: toArray(32, message.toOpenArray(0, 31))),
SkPublicKey(publicKey)):
return Success
return Error
proc ecdhAgree*(
seckey: PrivateKey, pubkey: PublicKey,
s: var SharedSecretFull): EthKeysStatus {.deprecated.} =
let v = ecdhRaw(SkSecretKey(seckey), SkPublicKey(pubkey))
if v.isOk():
s = SharedSecretFull(v[])
return Success
return Error

View File

@ -32,14 +32,14 @@ const
type type
Nonce* = array[KeyLength, byte] Nonce* = array[KeyLength, byte]
AuthMessageV4* = object {.packed.} AuthMessageV4* {.packed.} = object
signature: array[RawSignatureSize, byte] signature: array[RawSignatureSize, byte]
keyhash: array[keccak256.sizeDigest, byte] keyhash: array[keccak256.sizeDigest, byte]
pubkey: PublicKey pubkey: array[RawPublicKeySize, byte]
nonce: array[keccak256.sizeDigest, byte] nonce: array[keccak256.sizeDigest, byte]
flag: byte flag: byte
AckMessageV4* = object {.packed.} AckMessageV4* {.packed.} = object
pubkey: array[RawPublicKeySize, byte] pubkey: array[RawPublicKeySize, byte]
nonce: array[keccak256.sizeDigest, byte] nonce: array[keccak256.sizeDigest, byte]
flag: byte flag: byte
@ -94,7 +94,7 @@ proc newHandshake*(flags: set[HandshakeFlag] = {Initiator},
## Create new `Handshake` object. ## Create new `Handshake` object.
result.version = byte(version and 0xFF) result.version = byte(version and 0xFF)
result.flags = flags result.flags = flags
result.ephemeral = newKeyPair() result.ephemeral = KeyPair.random().tryGet()
if Initiator in flags: if Initiator in flags:
result.expectedLength = AckMessageV4Length result.expectedLength = AckMessageV4Length
if randomBytes(result.initiatorNonce) != len(result.initiatorNonce): if randomBytes(result.initiatorNonce) != len(result.initiatorNonce):
@ -112,25 +112,25 @@ proc authMessagePreEIP8(h: var Handshake,
encrypt: bool = true): AuthStatus = encrypt: bool = true): AuthStatus =
## Create plain pre-EIP8 authentication message. ## Create plain pre-EIP8 authentication message.
var var
secret: SharedSecret
signature: Signature
buffer: array[PlainAuthMessageV4Length, byte] buffer: array[PlainAuthMessageV4Length, byte]
flagb: byte flagb: byte
header: ptr AuthMessageV4 header: ptr AuthMessageV4
outlen = 0 outlen = 0
flagb = byte(flag) flagb = byte(flag)
header = cast[ptr AuthMessageV4](addr buffer[0]) header = cast[ptr AuthMessageV4](addr buffer[0])
if ecdhAgree(h.host.seckey, pubkey, secret) != EthKeysStatus.Success: var secret = ecdhRaw(h.host.seckey, pubkey)
if secret.isErr:
return(EcdhError) return(EcdhError)
var xornonce = h.initiatorNonce var xornonce = h.initiatorNonce
xornonce.sxor(secret.data) xornonce.sxor(secret[].data)
if signRawMessage(xornonce, h.ephemeral.seckey, secret[].clear()
signature) != EthKeysStatus.Success: let sig = sign(h.ephemeral.seckey, SkMessage(data: xornonce))
if sig.isErr:
return(SignatureError) return(SignatureError)
h.remoteHPubkey = pubkey h.remoteHPubkey = pubkey
header.signature = signature.getRaw() header.signature = sig[].toRaw()
header.keyhash = keccak256.digest(h.ephemeral.pubkey.getRaw()).data header.keyhash = keccak256.digest(h.ephemeral.pubkey.toRaw()).data
header.pubkey = cast[PublicKey](h.host.pubkey.getRaw()) header.pubkey = h.host.pubkey.toRaw()
header.nonce = h.initiatorNonce header.nonce = h.initiatorNonce
header.flag = flagb header.flag = flagb
if encrypt: if encrypt:
@ -155,23 +155,23 @@ proc authMessageEIP8(h: var Handshake,
encrypt: bool = true): AuthStatus = encrypt: bool = true): AuthStatus =
## Create EIP8 authentication message. ## Create EIP8 authentication message.
var var
secret: SharedSecret
signature: Signature
buffer: array[PlainAuthMessageMaxEIP8, byte] buffer: array[PlainAuthMessageMaxEIP8, byte]
padsize: byte padsize: byte
doAssert(EIP8 in h.flags) doAssert(EIP8 in h.flags)
outlen = 0 outlen = 0
if ecdhAgree(h.host.seckey, pubkey, secret) != EthKeysStatus.Success: var secret = ecdhRaw(h.host.seckey, pubkey)
if secret.isErr:
return(EcdhError) return(EcdhError)
var xornonce = h.initiatorNonce var xornonce = h.initiatorNonce
xornonce.sxor(secret.data) xornonce.sxor(secret[].data)
if signRawMessage(xornonce, h.ephemeral.seckey, secret[].clear()
signature) != EthKeysStatus.Success: var sig = sign(h.ephemeral.seckey, SkMessage(data: xornonce))
if sig.isErr:
return(SignatureError) return(SignatureError)
h.remoteHPubkey = pubkey h.remoteHPubkey = pubkey
var payload = rlp.encodeList(signature.getRaw(), var payload = rlp.encodeList(sig[].toRaw(),
h.host.pubkey.getRaw(), h.host.pubkey.toRaw(),
h.initiatorNonce, h.initiatorNonce,
[byte(h.version)]) [byte(h.version)])
doAssert(len(payload) == PlainAuthMessageEIP8Length) doAssert(len(payload) == PlainAuthMessageEIP8Length)
@ -216,7 +216,7 @@ proc ackMessagePreEIP8(h: var Handshake,
var buffer: array[PlainAckMessageV4Length, byte] var buffer: array[PlainAckMessageV4Length, byte]
outlen = 0 outlen = 0
var header = cast[ptr AckMessageV4](addr buffer[0]) var header = cast[ptr AckMessageV4](addr buffer[0])
header.pubkey = h.ephemeral.pubkey.getRaw() header.pubkey = h.ephemeral.pubkey.toRaw()
header.nonce = h.responderNonce header.nonce = h.responderNonce
header.flag = byte(flag) header.flag = byte(flag)
if encrypt: if encrypt:
@ -242,7 +242,7 @@ proc ackMessageEIP8(h: var Handshake,
buffer: array[PlainAckMessageMaxEIP8, byte] buffer: array[PlainAckMessageMaxEIP8, byte]
padsize: byte padsize: byte
doAssert(EIP8 in h.flags) doAssert(EIP8 in h.flags)
var payload = rlp.encodeList(h.ephemeral.pubkey.getRaw(), var payload = rlp.encodeList(h.ephemeral.pubkey.toRaw(),
h.responderNonce, h.responderNonce,
[byte(h.version)]) [byte(h.version)])
doAssert(len(payload) == PlainAckMessageEIP8Length) doAssert(len(payload) == PlainAckMessageEIP8Length)
@ -317,32 +317,36 @@ proc ackMessage*(h: var Handshake, output: var openarray[byte],
proc decodeAuthMessageV4(h: var Handshake, m: openarray[byte]): AuthStatus = proc decodeAuthMessageV4(h: var Handshake, m: openarray[byte]): AuthStatus =
## Decodes V4 AuthMessage. ## Decodes V4 AuthMessage.
var var
secret: SharedSecret
buffer: array[PlainAuthMessageV4Length, byte] buffer: array[PlainAuthMessageV4Length, byte]
pubkey: PublicKey
doAssert(Responder in h.flags) doAssert(Responder in h.flags)
if eciesDecrypt(m, buffer, h.host.seckey) != EciesStatus.Success: if eciesDecrypt(m, buffer, h.host.seckey) != EciesStatus.Success:
return(EciesError) return(EciesError)
var header = cast[ptr AuthMessageV4](addr buffer[0]) var header = cast[ptr AuthMessageV4](addr buffer[0])
if recoverPublicKey(header.pubkey.data, pubkey) != EthKeysStatus.Success: let pubkey = PublicKey.fromRaw(header.pubkey)
if pubkey.isErr:
return(InvalidPubKey) return(InvalidPubKey)
if ecdhAgree(h.host.seckey, pubkey, secret) != EthKeysStatus.Success: var secret = ecdhRaw(h.host.seckey, pubkey[])
if secret.isErr:
return(EcdhError) return(EcdhError)
var xornonce = header.nonce var xornonce = header.nonce
xornonce.sxor(secret.data) xornonce.sxor(secret[].data)
if recoverSignatureKey(header.signature, xornonce, secret[].clear()
h.remoteEPubkey) != EthKeysStatus.Success: let sig = Signature.fromRaw(header.signature)
if sig.isErr:
return(SignatureError) return(SignatureError)
let remoteEPubkey = recover(sig[], SkMessage(data: xornonce))
if remoteEPubkey.isErr:
return(SignatureError)
h.remoteEPubkey = remoteEPubkey[]
h.initiatorNonce = header.nonce h.initiatorNonce = header.nonce
h.remoteHPubkey = pubkey h.remoteHPubkey = pubkey[]
result = Success result = Success
proc decodeAuthMessageEip8(h: var Handshake, m: openarray[byte]): AuthStatus = proc decodeAuthMessageEip8(h: var Handshake, m: openarray[byte]): AuthStatus =
## Decodes EIP-8 AuthMessage. ## Decodes EIP-8 AuthMessage.
var var
pubkey: PublicKey
nonce: Nonce nonce: Nonce
secret: SharedSecret
let size = uint16.fromBytesBE(m) let size = uint16.fromBytesBE(m)
h.expectedLength = int(size) + 2 h.expectedLength = int(size) + 2
@ -368,20 +372,25 @@ proc decodeAuthMessageEip8(h: var Handshake, m: openarray[byte]): AuthStatus =
var pubkeyBr = reader.listElem(1).toBytes() var pubkeyBr = reader.listElem(1).toBytes()
var nonceBr = reader.listElem(2).toBytes() var nonceBr = reader.listElem(2).toBytes()
var versionBr = reader.listElem(3).toBytes() var versionBr = reader.listElem(3).toBytes()
if recoverPublicKey(pubkeyBr.toOpenArray(), let pubkey = PublicKey.fromRaw(pubkeyBr.toOpenArray())
pubkey) != EthKeysStatus.Success: if pubkey.isErr:
return(InvalidPubKey) return(InvalidPubKey)
copyMem(addr nonce[0], nonceBr.baseAddr, KeyLength) copyMem(addr nonce[0], nonceBr.baseAddr, KeyLength)
if ecdhAgree(h.host.seckey, pubkey, secret) != EthKeysStatus.Success: var secret = ecdhRaw(h.host.seckey, pubkey[])
if secret.isErr:
return(EcdhError) return(EcdhError)
var xornonce = nonce var xornonce = nonce
xornonce.sxor(secret.data) xornonce.sxor(secret[].data)
if recoverSignatureKey(signatureBr.toOpenArray(), secret[].clear()
xornonce, let sig = Signature.fromRaw(signatureBr.toOpenArray())
h.remoteEPubkey) != EthKeysStatus.Success: if sig.isErr:
return(SignatureError) return(SignatureError)
let remoteEPubkey = recover(sig[], SkMessage(data: xornonce))
if remoteEPubkey.isErr:
return(SignatureError)
h.remoteEPubkey = remoteEPubkey[]
h.initiatorNonce = nonce h.initiatorNonce = nonce
h.remoteHPubkey = pubkey h.remoteHPubkey = pubkey[]
h.version = cast[ptr byte](versionBr.baseAddr)[] h.version = cast[ptr byte](versionBr.baseAddr)[]
result = Success result = Success
except CatchableError: except CatchableError:
@ -411,9 +420,10 @@ proc decodeAckMessageEip8*(h: var Handshake, m: openarray[byte]): AuthStatus =
let pubkeyBr = reader.listElem(0).toBytes() let pubkeyBr = reader.listElem(0).toBytes()
let nonceBr = reader.listElem(1).toBytes() let nonceBr = reader.listElem(1).toBytes()
let versionBr = reader.listElem(2).toBytes() let versionBr = reader.listElem(2).toBytes()
if recoverPublicKey(pubkeyBr.toOpenArray(), let remoteEPubkey = PublicKey.fromRaw(pubkeyBr.toOpenArray())
h.remoteEPubkey) != EthKeysStatus.Success: if remoteEPubkey.isErr:
return(InvalidPubKey) return(InvalidPubKey)
h.remoteEPubkey = remoteEPubkey[]
copyMem(addr h.responderNonce[0], nonceBr.baseAddr, KeyLength) copyMem(addr h.responderNonce[0], nonceBr.baseAddr, KeyLength)
h.version = cast[ptr byte](versionBr.baseAddr)[] h.version = cast[ptr byte](versionBr.baseAddr)[]
result = Success result = Success
@ -428,8 +438,10 @@ proc decodeAckMessageV4(h: var Handshake, m: openarray[byte]): AuthStatus =
if eciesDecrypt(m, buffer, h.host.seckey) != EciesStatus.Success: if eciesDecrypt(m, buffer, h.host.seckey) != EciesStatus.Success:
return(EciesError) return(EciesError)
var header = cast[ptr AckMessageV4](addr buffer[0]) var header = cast[ptr AckMessageV4](addr buffer[0])
if recoverPublicKey(header.pubkey, h.remoteEPubkey) != EthKeysStatus.Success: let remoteEPubkey = PublicKey.fromRaw(header.pubkey)
if remoteEPubkey.isErr:
return(InvalidPubKey) return(InvalidPubKey)
h.remoteEPubkey = remoteEPubkey[]
h.responderNonce = header.nonce h.responderNonce = header.nonce
result = Success result = Success
@ -479,15 +491,14 @@ proc getSecrets*(h: Handshake, authmsg: openarray[byte],
## Derive secrets from handshake `h` using encrypted AuthMessage `authmsg` and ## Derive secrets from handshake `h` using encrypted AuthMessage `authmsg` and
## encrypted AckMessage `ackmsg`. ## encrypted AckMessage `ackmsg`.
var var
shsec: SharedSecret
ctx0: keccak256 ctx0: keccak256
ctx1: keccak256 ctx1: keccak256
mac1: MDigest[256] mac1: MDigest[256]
xornonce: Nonce xornonce: Nonce
# ecdhe-secret = ecdh.agree(ephemeral-privkey, remote-ephemeral-pubk) # ecdhe-secret = ecdh.agree(ephemeral-privkey, remote-ephemeral-pubk)
if ecdhAgree(h.ephemeral.seckey, h.remoteEPubkey, var shsec = ecdhRaw(h.ephemeral.seckey, h.remoteEPubkey)
shsec) != EthKeysStatus.Success: if shsec.isErr:
return(EcdhError) return(EcdhError)
# shared-secret = keccak(ecdhe-secret || keccak(nonce || initiator-nonce)) # shared-secret = keccak(ecdhe-secret || keccak(nonce || initiator-nonce))
@ -497,25 +508,26 @@ proc getSecrets*(h: Handshake, authmsg: openarray[byte],
ctx1.update(h.initiatorNonce) ctx1.update(h.initiatorNonce)
mac1 = ctx1.finish() mac1 = ctx1.finish()
ctx1.clear() ctx1.clear()
ctx0.update(shsec.data) ctx0.update(shsec[].data)
ctx0.update(mac1.data) ctx0.update(mac1.data)
mac1 = ctx0.finish() mac1 = ctx0.finish()
# aes-secret = keccak(ecdhe-secret || shared-secret) # aes-secret = keccak(ecdhe-secret || shared-secret)
ctx0.init() ctx0.init()
ctx0.update(shsec.data) ctx0.update(shsec[].data)
ctx0.update(mac1.data) ctx0.update(mac1.data)
mac1 = ctx0.finish() mac1 = ctx0.finish()
# mac-secret = keccak(ecdhe-secret || aes-secret) # mac-secret = keccak(ecdhe-secret || aes-secret)
ctx0.init() ctx0.init()
ctx0.update(shsec.data) ctx0.update(shsec[].data)
ctx0.update(mac1.data) ctx0.update(mac1.data)
secret.aesKey = mac1.data secret.aesKey = mac1.data
mac1 = ctx0.finish() mac1 = ctx0.finish()
secret.macKey = mac1.data secret.macKey = mac1.data
burnMem(shsec) shsec[].clear()
# egress-mac = keccak256(mac-secret ^ recipient-nonce || auth-sent-init) # egress-mac = keccak256(mac-secret ^ recipient-nonce || auth-sent-init)
xornonce = mac1.data xornonce = mac1.data
xornonce.sxor(h.responderNonce) xornonce.sxor(h.responderNonce)

View File

@ -56,7 +56,7 @@ proc append*(w: var RlpWriter, a: IpAddress) =
w.append(a.address_v4.toMemRange) w.append(a.address_v4.toMemRange)
proc append(w: var RlpWriter, p: Port) {.inline.} = w.append(p.int) proc append(w: var RlpWriter, p: Port) {.inline.} = w.append(p.int)
proc append(w: var RlpWriter, pk: PublicKey) {.inline.} = w.append(pk.getRaw()) proc append(w: var RlpWriter, pk: PublicKey) {.inline.} = w.append(pk.toRaw())
proc append(w: var RlpWriter, h: MDigest[256]) {.inline.} = w.append(h.data) proc append(w: var RlpWriter, h: MDigest[256]) {.inline.} = w.append(h.data)
proc pack(cmdId: CommandId, payload: BytesRange, pk: PrivateKey): Bytes = proc pack(cmdId: CommandId, payload: BytesRange, pk: PrivateKey): Bytes =
@ -67,7 +67,7 @@ proc pack(cmdId: CommandId, payload: BytesRange, pk: PrivateKey): Bytes =
# TODO: There is a lot of unneeded allocations here # TODO: There is a lot of unneeded allocations here
let encodedData = @[cmdId.byte] & payload.toSeq() let encodedData = @[cmdId.byte] & payload.toSeq()
let signature = @(pk.signMessage(encodedData).getRaw()) let signature = @(pk.sign(encodedData).tryGet().toRaw())
let msgHash = keccak256.digest(signature & encodedData) let msgHash = keccak256.digest(signature & encodedData)
result = @(msgHash.data) & signature & encodedData result = @(msgHash.data) & signature & encodedData
@ -77,10 +77,13 @@ proc validateMsgHash(msg: Bytes, msgHash: var MDigest[256]): bool =
result = msgHash == keccak256.digest(msg.toOpenArray(MAC_SIZE, msg.high)) result = msgHash == keccak256.digest(msg.toOpenArray(MAC_SIZE, msg.high))
proc recoverMsgPublicKey(msg: Bytes, pk: var PublicKey): bool = proc recoverMsgPublicKey(msg: Bytes, pk: var PublicKey): bool =
msg.len > HEAD_SIZE and if msg.len > HEAD_SIZE:
recoverSignatureKey(msg.toOpenArray(MAC_SIZE, HEAD_SIZE), let sig = Signature.fromRaw(msg.toOpenArray(MAC_SIZE, HEAD_SIZE))
keccak256.digest(msg.toOpenArray(HEAD_SIZE, msg.high)).data, if sig.isOk():
pk) == EthKeysStatus.Success let pubkey = recover(sig[], msg.toOpenArray(HEAD_SIZE, msg.high))
if pubkey.isOk():
pk = pubkey[]
return true
proc unpack(msg: Bytes): tuple[cmdId: CommandId, payload: Bytes] = proc unpack(msg: Bytes): tuple[cmdId: CommandId, payload: Bytes] =
# Check against possible RangeError # Check against possible RangeError
@ -154,7 +157,7 @@ proc newDiscoveryProtocol*(privKey: PrivateKey, address: Address,
result.address = address result.address = address
result.bootstrapNodes = newSeqOfCap[Node](bootstrapNodes.len) result.bootstrapNodes = newSeqOfCap[Node](bootstrapNodes.len)
for n in bootstrapNodes: result.bootstrapNodes.add(newNode(n)) for n in bootstrapNodes: result.bootstrapNodes.add(newNode(n))
result.thisNode = newNode(privKey.getPublicKey(), address) result.thisNode = newNode(privKey.toPublicKey().tryGet(), address)
result.kademlia = newKademliaProtocol(result.thisNode, result) result.kademlia = newKademliaProtocol(result.thisNode, result)
proc recvPing(d: DiscoveryProtocol, node: Node, proc recvPing(d: DiscoveryProtocol, node: Node,
@ -190,12 +193,12 @@ proc recvNeighbours(d: DiscoveryProtocol, node: Node,
let udpPort = n.listElem(1).toInt(uint16).Port let udpPort = n.listElem(1).toInt(uint16).Port
let tcpPort = n.listElem(2).toInt(uint16).Port let tcpPort = n.listElem(2).toInt(uint16).Port
var pk: PublicKey let pk = PublicKey.fromRaw(n.listElem(3).toBytes.toOpenArray())
if recoverPublicKey(n.listElem(3).toBytes.toOpenArray(), pk) != EthKeysStatus.Success: if pk.isErr:
warn "Could not parse public key" warn "Could not parse public key"
continue continue
neighbours.add(newNode(pk, Address(ip: ip, udpPort: udpPort, tcpPort: tcpPort))) neighbours.add(newNode(pk[], Address(ip: ip, udpPort: udpPort, tcpPort: tcpPort)))
d.kademlia.recvNeighbours(node, neighbours) d.kademlia.recvNeighbours(node, neighbours)
proc recvFindNode(d: DiscoveryProtocol, node: Node, payload: Bytes) {.inline, gcsafe.} = proc recvFindNode(d: DiscoveryProtocol, node: Node, payload: Bytes) {.inline, gcsafe.} =
@ -314,9 +317,10 @@ when isMainModule:
let (cmdId, payload) = unpack(m) let (cmdId, payload) = unpack(m)
doAssert(payload == hexToSeqByte"f2cb842edbd4d182944382765da0ab56fb9e64a85a597e6bb27c656b4f1afb7e06b0fd4e41ccde6dba69a3c4a150845aaa4de2") doAssert(payload == hexToSeqByte"f2cb842edbd4d182944382765da0ab56fb9e64a85a597e6bb27c656b4f1afb7e06b0fd4e41ccde6dba69a3c4a150845aaa4de2")
doAssert(cmdId == cmdPong) doAssert(cmdId == cmdPong)
doAssert(remotePubkey == initPublicKey("78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d")) doAssert(remotePubkey == PublicKey.fromHex(
"78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d"))[]
let privKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617") let privKey = PrivateKey.fromHex("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[]
# echo privKey # echo privKey

View File

@ -46,27 +46,33 @@ type
PacketError, PacketError,
DecryptError DecryptError
proc randomBytes*(v: var openarray[byte]) = proc randomBytes2*(v: var openarray[byte]) =
if nimcrypto.randomBytes(v) != v.len: # TODO if this is called randomBytes it breaks calling the real randomBytes
# in other modules... sigh, nim modules and global namespaces...
# ideally, a new random library will take the place of both these proc's
# in as setting without exceptions for such low-level constructs..
if randomBytes(v) != v.len:
raise newException(RandomSourceDepleted, "Could not randomize bytes") raise newException(RandomSourceDepleted, "Could not randomize bytes")
proc idNonceHash(nonce, ephkey: openarray[byte]): array[32, byte] = proc idNonceHash(nonce, ephkey: openarray[byte]): MDigest[256] =
var ctx: sha256 var ctx: sha256
ctx.init() ctx.init()
ctx.update(idNoncePrefix) ctx.update(idNoncePrefix)
ctx.update(nonce) ctx.update(nonce)
ctx.update(ephkey) ctx.update(ephkey)
ctx.finish().data ctx.finish()
proc signIDNonce*(c: Codec, idNonce, ephKey: openarray[byte]): SignatureNR = proc signIDNonce*(c: Codec, idNonce, ephKey: openarray[byte]): SignatureNR =
if signRawMessage(idNonceHash(idNonce, ephKey), c.privKey, result) != EthKeysStatus.Success: let sig = signNR(c.privKey, idNonceHash(idNonce, ephKey))
raise newException(EthKeysException, "Could not sign idNonce") if sig.isErr:
raise newException(CatchableError, "Could not sign idNonce")
sig[]
proc deriveKeys(n1, n2: NodeID, priv: PrivateKey, pub: PublicKey, proc deriveKeys(n1, n2: NodeID, priv: PrivateKey, pub: PublicKey,
idNonce: openarray[byte], result: var HandshakeSecrets) = idNonce: openarray[byte], result: var HandshakeSecrets) =
var eph: SharedSecretFull let eph = ecdhRawFull(priv, pub)
if ecdhAgree(priv, pub, eph) != EthKeysStatus.Success: if eph.isErr:
raise newException(EthKeysException, "ecdhAgree failed") raise newException(CatchableError, "ecdhRawFull failed")
# TODO: Unneeded allocation here # TODO: Unneeded allocation here
var info = newSeqOfCap[byte](idNoncePrefix.len + 32 * 2) var info = newSeqOfCap[byte](idNoncePrefix.len + 32 * 2)
@ -78,7 +84,7 @@ proc deriveKeys(n1, n2: NodeID, priv: PrivateKey, pub: PublicKey,
static: assert(sizeof(result) == aesKeySize * 3) static: assert(sizeof(result) == aesKeySize * 3)
var res = cast[ptr UncheckedArray[byte]](addr result) var res = cast[ptr UncheckedArray[byte]](addr result)
hkdf(sha256, eph.data, idNonce, info, toOpenArray(res, 0, sizeof(result) - 1)) hkdf(sha256, eph[].data, idNonce, info, toOpenArray(res, 0, sizeof(result) - 1))
proc encryptGCM*(key, nonce, pt, authData: openarray[byte]): seq[byte] = proc encryptGCM*(key, nonce, pt, authData: openarray[byte]): seq[byte] =
var ectx: GCM[aes128] var ectx: GCM[aes128]
@ -97,10 +103,10 @@ proc makeAuthHeader(c: Codec, toId: NodeID, nonce: array[gcmNonceSize, byte],
if challenge.recordSeq < ln.record.seqNum: if challenge.recordSeq < ln.record.seqNum:
resp.record = ln.record resp.record = ln.record
let ephKey = newPrivateKey() let ephKey = PrivateKey.random().tryGet()
let ephPubkey = ephKey.getPublicKey().getRaw let ephPubkey = ephKey.toPublicKey().tryGet().toRaw
resp.signature = c.signIDNonce(challenge.idNonce, ephPubkey).getRaw resp.signature = c.signIDNonce(challenge.idNonce, ephPubkey).toRaw
deriveKeys(ln.id, toId, ephKey, challenge.pubKey, challenge.idNonce, deriveKeys(ln.id, toId, ephKey, challenge.pubKey, challenge.idNonce,
handshakeSecrets) handshakeSecrets)
@ -131,7 +137,7 @@ proc encodeEncrypted*(c: Codec,
challenge: Whoareyou): challenge: Whoareyou):
(seq[byte], array[gcmNonceSize, byte]) = (seq[byte], array[gcmNonceSize, byte]) =
var nonce: array[gcmNonceSize, byte] var nonce: array[gcmNonceSize, byte]
randomBytes(nonce) randomBytes2(nonce)
var headEnc: seq[byte] var headEnc: seq[byte]
var writeKey: AesKey var writeKey: AesKey
@ -223,11 +229,11 @@ proc decodeAuthResp(c: Codec, fromId: NodeId, head: AuthHeader,
warn "Unknown auth scheme" warn "Unknown auth scheme"
return false return false
var ephKey: PublicKey var ephKey = PublicKey.fromRaw(head.ephemeralKey)
if recoverPublicKey(head.ephemeralKey, ephKey) != EthKeysStatus.Success: if ephKey.isErr:
return false return false
deriveKeys(fromId, c.localNode.id, c.privKey, ephKey, challenge.idNonce, deriveKeys(fromId, c.localNode.id, c.privKey, ephKey[], challenge.idNonce,
secrets) secrets)
var zeroNonce: array[gcmNonceSize, byte] var zeroNonce: array[gcmNonceSize, byte]

View File

@ -59,10 +59,10 @@ proc makeEnrAux(seqNum: uint64, pk: PrivateKey, pairs: openarray[(string, Field)
result.pairs = @pairs result.pairs = @pairs
result.seqNum = seqNum result.seqNum = seqNum
let pubkey = pk.getPublicKey() let pubkey = pk.toPublicKey().tryGet()
result.pairs.add(("id", Field(kind: kString, str: "v4"))) result.pairs.add(("id", Field(kind: kString, str: "v4")))
result.pairs.add(("secp256k1", Field(kind: kBytes, bytes: @(pubkey.getRawCompressed())))) result.pairs.add(("secp256k1", Field(kind: kBytes, bytes: @(pubkey.toRawCompressed()))))
# Sort by key # Sort by key
result.pairs.sort() do(a, b: (string, Field)) -> int: result.pairs.sort() do(a, b: (string, Field)) -> int:
@ -82,13 +82,13 @@ proc makeEnrAux(seqNum: uint64, pk: PrivateKey, pairs: openarray[(string, Field)
var w = initRlpList(result.pairs.len * 2 + 1) var w = initRlpList(result.pairs.len * 2 + 1)
w.append(seqNum, result.pairs) w.append(seqNum, result.pairs)
var sig: SignatureNR let sig = signNR(pk, toSign)
if signRawMessage(keccak256.digest(toSign).data, pk, sig) != EthKeysStatus.Success: if sig.isErr:
raise newException(EthKeysException, "Could not sign ENR (internal error)") raise newException(CatchableError, "Could not sign ENR (internal error)")
result.raw = block: result.raw = block:
var w = initRlpList(result.pairs.len * 2 + 2) var w = initRlpList(result.pairs.len * 2 + 2)
w.append(sig.getRaw()) w.append(sig[].toRaw())
w.append(seqNum, result.pairs) w.append(seqNum, result.pairs)
macro initRecord*(seqNum: uint64, pk: PrivateKey, pairs: untyped{nkTableConstr}): untyped = macro initRecord*(seqNum: uint64, pk: PrivateKey, pairs: untyped{nkTableConstr}): untyped =
@ -146,8 +146,10 @@ proc get*(r: Record, key: string, T: type): T =
return f.str return f.str
elif T is PublicKey: elif T is PublicKey:
requireKind(f, kBytes) requireKind(f, kBytes)
if recoverPublicKey(f.bytes, result) != EthKeysStatus.Success: let pk = PublicKey.fromRaw(f.bytes)
if pk.isErr:
raise newException(ValueError, "Invalid public key") raise newException(ValueError, "Invalid public key")
return pk[]
elif T is array: elif T is array:
when type(result[0]) is byte: when type(result[0]) is byte:
requireKind(f, kBytes) requireKind(f, kBytes)
@ -164,7 +166,10 @@ proc get*(r: Record, key: string, T: type): T =
proc get*(r: Record, pubKey: var PublicKey): bool = proc get*(r: Record, pubKey: var PublicKey): bool =
var pubkeyField: Field var pubkeyField: Field
if r.getField("secp256k1", pubkeyField) and pubkeyField.kind == kBytes: if r.getField("secp256k1", pubkeyField) and pubkeyField.kind == kBytes:
result = recoverPublicKey(pubkeyField.bytes, pubKey) == EthKeysStatus.Success let pk = PublicKey.fromRaw(pubkeyField.bytes)
if pk.isOk:
pubKey = pk[]
return true
proc tryGet*(r: Record, key: string, T: type): Option[T] = proc tryGet*(r: Record, key: string, T: type): Option[T] =
try: try:
@ -194,11 +199,10 @@ proc toTypedRecord*(r: Record): Option[TypedRecord] =
proc verifySignatureV4(r: Record, sigData: openarray[byte], content: seq[byte]): bool = proc verifySignatureV4(r: Record, sigData: openarray[byte], content: seq[byte]): bool =
var publicKey: PublicKey var publicKey: PublicKey
if r.get(publicKey): if r.get(publicKey):
var sig: SignatureNR let sig = SignatureNR.fromRaw(sigData)
if sig.parseCompact(sigData) == EthKeysStatus.Success: if sig.isOk:
var h = keccak256.digest(content) var h = keccak256.digest(content)
if verifySignatureRaw(sig, h.data, publicKey) == EthKeysStatus.Success: return verify(sig[], h, publicKey)
return true
proc verifySignature(r: Record): bool = proc verifySignature(r: Record): bool =
var rlp = rlpFromBytes(r.raw.toRange) var rlp = rlpFromBytes(r.raw.toRange)

View File

@ -9,7 +9,7 @@ type
record*: Record record*: Record
proc toNodeId*(pk: PublicKey): NodeId = proc toNodeId*(pk: PublicKey): NodeId =
readUintBE[256](keccak256.digest(pk.getRaw()).data) readUintBE[256](keccak256.digest(pk.toRaw()).data)
proc newNode*(enode: ENode): Node = proc newNode*(enode: ENode): Node =
Node(node: enode, Node(node: enode,
@ -43,15 +43,15 @@ proc newNode*(r: Record): Node =
# Will need some refactor though. # Will need some refactor though.
discard discard
var pk: PublicKey let pk = PublicKey.fromRaw(r.get("secp256k1", seq[byte]))
if recoverPublicKey(r.get("secp256k1", seq[byte]), pk) != EthKeysStatus.Success: if pk.isErr:
warn "Could not recover public key" warn "Could not recover public key", err = pk.error
return return
result = newNode(initENode(pk, a)) result = newNode(initENode(pk[], a))
result.record = r result.record = r
proc hash*(n: Node): hashes.Hash = hash(n.node.pubkey.data) proc hash*(n: Node): hashes.Hash = hash(n.node.pubkey.toRaw)
proc `==`*(a, b: Node): bool = (a.isNil and b.isNil) or (not a.isNil and not b.isNil and a.node.pubkey == b.node.pubkey) proc `==`*(a, b: Node): bool = (a.isNil and b.isNil) or (not a.isNil and not b.isNil and a.node.pubkey == b.node.pubkey)
proc address*(n: Node): Address {.inline.} = n.node.address proc address*(n: Node): Address {.inline.} = n.node.address

View File

@ -108,7 +108,7 @@ proc decodeWhoAreYou(d: Protocol, msg: Bytes): Whoareyou =
proc sendWhoareyou(d: Protocol, address: Address, toNode: NodeId, authTag: AuthTag) = proc sendWhoareyou(d: Protocol, address: Address, toNode: NodeId, authTag: AuthTag) =
trace "sending who are you", to = $toNode, toAddress = $address trace "sending who are you", to = $toNode, toAddress = $address
let challenge = Whoareyou(authTag: authTag, recordSeq: 0) let challenge = Whoareyou(authTag: authTag, recordSeq: 0)
encoding.randomBytes(challenge.idNonce) encoding.randomBytes2(challenge.idNonce)
# If there is already a handshake going on for this nodeid then we drop this # If there is already a handshake going on for this nodeid then we drop this
# new one. Handshake will get cleaned up after `handshakeTimeout`. # new one. Handshake will get cleaned up after `handshakeTimeout`.
# If instead overwriting the handshake would be allowed, the handshake timeout # If instead overwriting the handshake would be allowed, the handshake timeout
@ -181,8 +181,6 @@ proc receive*(d: Protocol, a: Address, msg: Bytes) {.gcsafe,
RlpError, RlpError,
IOError, IOError,
TransportAddressError, TransportAddressError,
EthKeysException,
Secp256k1Exception,
].} = ].} =
if msg.len < tagSize: # or magicSize, can be either if msg.len < tagSize: # or magicSize, can be either
return # Invalid msg return # Invalid msg
@ -482,7 +480,7 @@ proc newProtocol*(privKey: PrivateKey, db: Database,
let let
a = Address(ip: externalIp.get(IPv4_any()), a = Address(ip: externalIp.get(IPv4_any()),
tcpPort: tcpPort, udpPort: udpPort) tcpPort: tcpPort, udpPort: udpPort)
enode = initENode(privKey.getPublicKey(), a) enode = initENode(privKey.toPublicKey().tryGet(), a)
enrRec = enr.Record.init(1, privKey, externalIp, tcpPort, udpPort) enrRec = enr.Record.init(1, privKey, externalIp, tcpPort, udpPort)
node = newNode(enode, enrRec) node = newNode(enode, enrRec)

View File

@ -99,7 +99,6 @@ proc eciesEncrypt*(input: openarray[byte], output: var openarray[byte],
cipher: CTR[aes128] cipher: CTR[aes128]
ctx: HMAC[sha256] ctx: HMAC[sha256]
iv: array[aes128.sizeBlock, byte] iv: array[aes128.sizeBlock, byte]
secret: SharedSecret
material: array[KeyLength, byte] material: array[KeyLength, byte]
if len(output) < eciesEncryptedLength(len(input)): if len(output) < eciesEncryptedLength(len(input)):
@ -107,12 +106,15 @@ proc eciesEncrypt*(input: openarray[byte], output: var openarray[byte],
if randomBytes(iv) != aes128.sizeBlock: if randomBytes(iv) != aes128.sizeBlock:
return(RandomError) return(RandomError)
var ephemeral = newKeyPair() var ephemeral = KeyPair.random()
if ephemeral.isErr:
return(RandomError)
if ecdhAgree(ephemeral.seckey, pubkey, secret) != EthKeysStatus.Success: var secret = ecdhRaw(ephemeral[].seckey, pubkey)
if secret.isErr:
return(EcdhError) return(EcdhError)
material = kdf(secret.data) material = kdf(secret[].data)
burnMem(secret) burnMem(secret)
copyMem(addr encKey[0], addr material[0], aes128.sizeKey) copyMem(addr encKey[0], addr material[0], aes128.sizeKey)
@ -121,7 +123,7 @@ proc eciesEncrypt*(input: openarray[byte], output: var openarray[byte],
var header = cast[ptr EciesHeader](addr output[0]) var header = cast[ptr EciesHeader](addr output[0])
header.version = 0x04 header.version = 0x04
header.pubkey = ephemeral.pubkey.getRaw() header.pubkey = ephemeral[].pubkey.toRaw()
header.iv = iv header.iv = iv
var so = eciesDataPos() var so = eciesDataPos()
@ -158,11 +160,9 @@ proc eciesDecrypt*(input: openarray[byte],
## Length of output data can be calculated using ``eciesDecryptedLength()`` ## Length of output data can be calculated using ``eciesDecryptedLength()``
## template. ## template.
var var
pubkey: PublicKey
encKey: array[aes128.sizeKey, byte] encKey: array[aes128.sizeKey, byte]
cipher: CTR[aes128] cipher: CTR[aes128]
ctx: HMAC[sha256] ctx: HMAC[sha256]
secret: SharedSecret
if len(input) <= 0: if len(input) <= 0:
return(IncompleteError) return(IncompleteError)
@ -174,12 +174,14 @@ proc eciesDecrypt*(input: openarray[byte],
return(IncompleteError) return(IncompleteError)
if len(input) - eciesOverheadLength() > len(output): if len(input) - eciesOverheadLength() > len(output):
return(BufferOverrun) return(BufferOverrun)
if recoverPublicKey(header.pubkey, pubkey) != EthKeysStatus.Success: let pubkey = PublicKey.fromRaw(header.pubkey)
if pubkey.isErr:
return(IncorrectKey) return(IncorrectKey)
if ecdhAgree(seckey, pubkey, secret) != EthKeysStatus.Success: var secret = ecdhRaw(seckey, pubkey[])
if secret.isErr:
return(EcdhError) return(EcdhError)
var material = kdf(secret.data) var material = kdf(secret[].data)
burnMem(secret) burnMem(secret)
copyMem(addr encKey[0], addr material[0], aes128.sizeKey) copyMem(addr encKey[0], addr material[0], aes128.sizeKey)
var macKey = sha256.digest(material, ostart = KeyLength div 2) var macKey = sha256.digest(material, ostart = KeyLength div 2)

View File

@ -60,7 +60,6 @@ proc initENode*(e: string, node: var ENode): ENodeStatus =
uport: int = 0 uport: int = 0
tport: int = 0 tport: int = 0
uri: Uri = initUri() uri: Uri = initUri()
data: string
if len(e) == 0: if len(e) == 0:
return IncorrectUri return IncorrectUri
@ -104,13 +103,10 @@ proc initENode*(e: string, node: var ENode): ENodeStatus =
else: else:
uport = tport uport = tport
try: let pk = PublicKey.fromHex(uri.username)
data = parseHexStr(uri.username) if pk.isErr:
if recoverPublicKey(cast[seq[byte]](data),
node.pubkey) != EthKeysStatus.Success:
return IncorrectNodeId
except CatchableError:
return IncorrectNodeId return IncorrectNodeId
node.pubkey = pk[]
try: try:
node.address.ip = parseIpAddress(uri.hostname) node.address.ip = parseIpAddress(uri.hostname)
@ -135,11 +131,8 @@ proc initENode*(pubkey: PublicKey, address: Address): ENode {.inline.} =
proc isCorrect*(n: ENode): bool = proc isCorrect*(n: ENode): bool =
## Returns ``true`` if ENode ``n`` is properly filled. ## Returns ``true`` if ENode ``n`` is properly filled.
result = false var pk: PublicKey
for i in n.pubkey.data: n.pubkey != pk
if i != 0x00'u8:
result = true
break
proc `$`*(n: ENode): string = proc `$`*(n: ENode): string =
## Returns string representation of ENode. ## Returns string representation of ENode.

View File

@ -51,7 +51,7 @@ const
ID_SIZE = 256 ID_SIZE = 256
proc toNodeId*(pk: PublicKey): NodeId = proc toNodeId*(pk: PublicKey): NodeId =
readUintBE[256](keccak256.digest(pk.getRaw()).data) readUintBE[256](keccak256.digest(pk.toRaw()).data)
proc newNode*(pk: PublicKey, address: Address): Node = proc newNode*(pk: PublicKey, address: Address): Node =
result.new() result.new()
@ -76,7 +76,7 @@ proc `$`*(n: Node): string =
else: else:
"Node[" & $n.node.address.ip & ":" & $n.node.address.udpPort & "]" "Node[" & $n.node.address.ip & ":" & $n.node.address.udpPort & "]"
proc hash*(n: Node): hashes.Hash = hash(n.node.pubkey.data) proc hash*(n: Node): hashes.Hash = hash(n.node.pubkey.toRaw)
proc `==`*(a, b: Node): bool = (a.isNil and b.isNil) or (not a.isNil and not b.isNil and a.node.pubkey == b.node.pubkey) proc `==`*(a, b: Node): bool = (a.isNil and b.isNil) or (not a.isNil and not b.isNil and a.node.pubkey == b.node.pubkey)
proc newKBucket(istart, iend: NodeId): KBucket = proc newKBucket(istart, iend: NodeId): KBucket =
@ -259,7 +259,7 @@ template onTimeout(b: untyped) =
b b
proc pingId(n: Node, token: seq[byte]): seq[byte] {.inline.} = proc pingId(n: Node, token: seq[byte]): seq[byte] {.inline.} =
result = token & @(n.node.pubkey.data) result = token & @(n.node.pubkey.toRaw)
proc waitPong(k: KademliaProtocol, n: Node, pingid: seq[byte]): Future[bool] = proc waitPong(k: KademliaProtocol, n: Node, pingid: seq[byte]): Future[bool] =
doAssert(pingid notin k.pongFutures, "Already waiting for pong from " & $n) doAssert(pingid notin k.pongFutures, "Already waiting for pong from " & $n)
@ -441,7 +441,7 @@ proc bootstrap*(k: KademliaProtocol, bootstrapNodes: seq[Node], retries = 0) {.a
proc recvPong*(k: KademliaProtocol, n: Node, token: seq[byte]) = proc recvPong*(k: KademliaProtocol, n: Node, token: seq[byte]) =
trace "<<< pong from ", n trace "<<< pong from ", n
let pingid = token & @(n.node.pubkey.data) let pingid = token & @(n.node.pubkey.toRaw)
var future: Future[bool] var future: Future[bool]
if k.pongFutures.take(pingid, future): if k.pongFutures.take(pingid, future):
future.complete(true) future.complete(true)

View File

@ -162,7 +162,7 @@ template compression(m: MockConf): bool =
proc newMockPeer*(userConfigurator: proc (m: MockConf)): EthereumNode = proc newMockPeer*(userConfigurator: proc (m: MockConf)): EthereumNode =
var mockConf = new MockConf var mockConf = new MockConf
mockConf.keys = newKeyPair() mockConf.keys = KeyPair.random()[]
mockConf.address = localhostAddress(nextUnusedMockPort) mockConf.address = localhostAddress(nextUnusedMockPort)
inc nextUnusedMockPort inc nextUnusedMockPort
mockConf.networkId = 1'u mockConf.networkId = 1'u

View File

@ -857,8 +857,8 @@ proc disconnect*(peer: Peer, reason: DisconnectionReason, notifyOtherPeer = fals
removePeer(peer.network, peer) removePeer(peer.network, peer)
proc validatePubKeyInHello(msg: DevP2P.hello, pubKey: PublicKey): bool = proc validatePubKeyInHello(msg: DevP2P.hello, pubKey: PublicKey): bool =
var pk: PublicKey let pk = PublicKey.fromRaw(msg.nodeId)
recoverPublicKey(msg.nodeId, pk) == EthKeysStatus.Success and pk == pubKey pk.isOk and pk[] == pubKey
proc checkUselessPeer(peer: Peer) {.inline.} = proc checkUselessPeer(peer: Peer) {.inline.} =
if peer.dispatcher.numProtocols == 0: if peer.dispatcher.numProtocols == 0:
@ -1012,7 +1012,7 @@ proc rlpxConnect*(node: EthereumNode, remote: Node): Future[Peer] {.async.} =
node.clientId, node.clientId,
node.capabilities, node.capabilities,
uint(node.address.tcpPort), uint(node.address.tcpPort),
node.keys.pubkey.getRaw()) node.keys.pubkey.toRaw())
var response = await result.handshakeImpl( var response = await result.handshakeImpl(
sendHelloFut, sendHelloFut,
@ -1102,7 +1102,7 @@ proc rlpxAccept*(node: EthereumNode,
node.clientId, node.clientId,
node.capabilities, node.capabilities,
listenPort.uint, listenPort.uint,
node.keys.pubkey.getRaw()) node.keys.pubkey.toRaw())
var response = await result.handshakeImpl( var response = await result.handshakeImpl(
sendHelloFut, sendHelloFut,

View File

@ -266,11 +266,9 @@ p2pProtocol les(version = lesVersion,
if signature.isNone: if signature.isNone:
error "missing announce signature" error "missing announce signature"
return return
let sigHash = keccak256.digest rlp.encodeList(headHash, let sigMsg = rlp.encodeList(headHash, headNumber, headTotalDifficulty)
headNumber, let sig = Signature.fromRaw(signature.get).tryGet()
headTotalDifficulty) let signerKey = recover(sig, sigMsg).tryGet()
let signerKey = recoverKeyFromSignature(signature.get.initSignature,
sigHash)
if signerKey.toNodeId != peer.remote.id: if signerKey.toNodeId != peer.remote.id:
error "invalid announce signature" error "invalid announce signature"
# TODO: should we disconnect this peer? # TODO: should we disconnect this peer?

View File

@ -297,14 +297,12 @@ proc encode*(self: Payload): Option[Bytes] =
plain.add padding plain.add padding
if self.src.isSome(): # Private key present - signature requested if self.src.isSome(): # Private key present - signature requested
let hash = keccak256.digest(plain) let sig = sign(self.src.get(), plain)
var sig: Signature if sig.isErr:
let err = signRawMessage(hash.data, self.src.get(), sig) notice "Signing message failed", err = sig.error
if err != EthKeysStatus.Success:
notice "Signing message failed", err
return return
plain.add sig.getRaw() plain.add sig[].toRaw()
if self.dst.isSome(): # Asymmetric key present - encryption requested if self.dst.isSome(): # Asymmetric key present - encryption requested
var res = newSeq[byte](eciesEncryptedLength(plain.len)) var res = newSeq[byte](eciesEncryptedLength(plain.len))
@ -392,14 +390,13 @@ proc decode*(data: openarray[byte], dst = none[PrivateKey](),
debug "Missing expected signature", len = plain.len debug "Missing expected signature", len = plain.len
return return
let sig = plain[^keys.RawSignatureSize .. ^1] let sig = Signature.fromRaw(plain[^keys.RawSignatureSize .. ^1])
let hash = keccak256.digest(plain[0 ..< ^keys.RawSignatureSize]) let key = sig and recover(
var key: PublicKey sig[], plain.toOpenArray(0, plain.len - keys.RawSignatureSize - 1))
let err = recoverSignatureKey(sig, hash.data, key) if key.isErr:
if err != EthKeysStatus.Success: debug "Failed to recover signature key", err = key.error
debug "Failed to recover signature key", err
return return
res.src = some(key) res.src = some(key[])
if hasSignature: if hasSignature:
if plain.len > pos + keys.RawSignatureSize: if plain.len > pos + keys.RawSignatureSize:
@ -633,16 +630,16 @@ proc notify*(filters: var Filters, msg: Message) {.gcsafe.} =
if decoded.isNone(): if decoded.isNone():
continue continue
if filter.privateKey.isSome(): if filter.privateKey.isSome():
keyHash = keccak256.digest(filter.privateKey.get().data) keyHash = keccak256.digest(filter.privateKey.get().toRaw())
# TODO: Get rid of the hash and just use pubkey to compare? # TODO: Get rid of the hash and just use pubkey to compare?
dst = some(getPublicKey(filter.privateKey.get())) dst = some(toPublicKey(filter.privateKey.get()).tryGet())
elif filter.symKey.isSome(): elif filter.symKey.isSome():
keyHash = keccak256.digest(filter.symKey.get()) keyHash = keccak256.digest(filter.symKey.get())
# else: # else:
# NOTE: In this case the message was not encrypted # NOTE: In this case the message was not encrypted
else: else:
if filter.privateKey.isSome(): if filter.privateKey.isSome():
if keyHash != keccak256.digest(filter.privateKey.get().data): if keyHash != keccak256.digest(filter.privateKey.get().toRaw()):
continue continue
elif filter.symKey.isSome(): elif filter.symKey.isSome():
if keyHash != keccak256.digest(filter.symKey.get()): if keyHash != keccak256.digest(filter.symKey.get()):

View File

@ -8,7 +8,7 @@ var targetNode: DiscoveryProtocol
init: init:
# Set up a discovery node, this is the node we target when fuzzing # Set up a discovery node, this is the node we target when fuzzing
var var
targetNodeKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617") targetNodeKey = PrivateKey.fromRaw("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[]
targetNodeAddr = localAddress(DefaultListeningPort) targetNodeAddr = localAddress(DefaultListeningPort)
targetNode = newDiscoveryProtocol(targetNodeKey, targetNodeAddr, @[]) targetNode = newDiscoveryProtocol(targetNodeKey, targetNodeAddr, @[])
# Create the transport as else replies on the messages send will fail. # Create the transport as else replies on the messages send will fail.
@ -22,7 +22,7 @@ test:
# Sending raw payload is possible but won't find us much. We need a hash and # Sending raw payload is possible but won't find us much. We need a hash and
# a signature, and without it there is a big chance it will always result in # a signature, and without it there is a big chance it will always result in
# "Wrong msg mac from" error. # "Wrong msg mac from" error.
let nodeKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618") let nodeKey = PrivateKey.fromRaw("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[]
msg = packData(payload, nodeKey) msg = packData(payload, nodeKey)
address = localAddress(DefaultListeningPort + 1) address = localAddress(DefaultListeningPort + 1)

View File

@ -20,7 +20,7 @@ proc generate() =
let let
fromAddr = localAddress(30303) fromAddr = localAddress(30303)
toAddr = localAddress(30304) toAddr = localAddress(30304)
peerKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617") peerKey = PrivateKey.fromHex("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[]
# valid data for a Ping packet # valid data for a Ping packet
block: block:
@ -42,7 +42,7 @@ proc generate() =
# valid data for a FindNode packet # valid data for a FindNode packet
block: block:
var data: array[64, byte] var data: array[64, byte]
data[32 .. ^1] = peerKey.getPublicKey.toNodeId().toByteArrayBE() data[32 .. ^1] = peerKey.toPublicKey().tryGet().toNodeId().toByteArrayBE()
let payload = rlp.encode((data, expiration())).toRange let payload = rlp.encode((data, expiration())).toRange
let encodedData = @[3.byte] & payload.toSeq() let encodedData = @[3.byte] & payload.toSeq()
debug "FindNode", data=byteutils.toHex(encodedData) debug "FindNode", data=byteutils.toHex(encodedData)
@ -54,14 +54,16 @@ proc generate() =
let let
n1Addr = localAddress(30305) n1Addr = localAddress(30305)
n2Addr = localAddress(30306) n2Addr = localAddress(30306)
n1Key = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618") n1Key = PrivateKey.fromHex(
n2Key = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619") "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[]
n2Key = PrivateKey.fromHex(
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619")[]
type Neighbour = tuple[ip: IpAddress, udpPort, tcpPort: Port, pk: PublicKey] type Neighbour = tuple[ip: IpAddress, udpPort, tcpPort: Port, pk: PublicKey]
var nodes = newSeqOfCap[Neighbour](2) var nodes = newSeqOfCap[Neighbour](2)
nodes.add((n1Addr.ip, n1Addr.udpPort, n1Addr.tcpPort, n1Key.getPublicKey())) nodes.add((n1Addr.ip, n1Addr.udpPort, n1Addr.tcpPort, n1Key.toPublicKey().tryGet()))
nodes.add((n2Addr.ip, n2Addr.udpPort, n2Addr.tcpPort, n2Key.getPublicKey())) nodes.add((n2Addr.ip, n2Addr.udpPort, n2Addr.tcpPort, n2Key.toPublicKey().tryGet()))
let payload = rlp.encode((nodes, expiration())).toRange let payload = rlp.encode((nodes, expiration())).toRange
let encodedData = @[4.byte] & payload.toSeq() let encodedData = @[4.byte] & payload.toSeq()

View File

@ -88,28 +88,28 @@ var jobject: JsonNode
suite "KeyFile test suite": suite "KeyFile test suite":
test "KeyStoreTests/basic_tests.json test1": test "KeyStoreTests/basic_tests.json test1":
var seckey: PrivateKey var seckey: PrivateKey
var expectkey = initPrivateKey(TestVectors[0].getOrDefault("priv").getStr()) var expectkey = PrivateKey.fromHex(TestVectors[0].getOrDefault("priv").getStr())[]
check: check:
decodeKeyFileJson(TestVectors[0].getOrDefault("keyfile"), decodeKeyFileJson(TestVectors[0].getOrDefault("keyfile"),
TestVectors[0].getOrDefault("password").getStr(), TestVectors[0].getOrDefault("password").getStr(),
seckey) == KeyFileStatus.Success seckey) == KeyFileStatus.Success
seckey.data == expectkey.data seckey.toRaw == expectkey.toRaw
test "KeyStoreTests/basic_tests.json python_generated_test_with_odd_iv": test "KeyStoreTests/basic_tests.json python_generated_test_with_odd_iv":
var seckey: PrivateKey var seckey: PrivateKey
var expectkey = initPrivateKey(TestVectors[1].getOrDefault("priv").getStr()) var expectkey = PrivateKey.fromHex(TestVectors[1].getOrDefault("priv").getStr())[]
check: check:
decodeKeyFileJson(TestVectors[1].getOrDefault("keyfile"), decodeKeyFileJson(TestVectors[1].getOrDefault("keyfile"),
TestVectors[1].getOrDefault("password").getStr(), TestVectors[1].getOrDefault("password").getStr(),
seckey) == KeyFileStatus.Success seckey) == KeyFileStatus.Success
seckey.data == expectkey.data seckey.toRaw == expectkey.toRaw
test "KeyStoreTests/basic_tests.json evilnonce": test "KeyStoreTests/basic_tests.json evilnonce":
var seckey: PrivateKey var seckey: PrivateKey
var expectkey = initPrivateKey(TestVectors[2].getOrDefault("priv").getStr()) var expectkey = PrivateKey.fromHex(TestVectors[2].getOrDefault("priv").getStr())[]
check: check:
decodeKeyFileJson(TestVectors[2].getOrDefault("keyfile"), decodeKeyFileJson(TestVectors[2].getOrDefault("keyfile"),
TestVectors[2].getOrDefault("password").getStr(), TestVectors[2].getOrDefault("password").getStr(),
seckey) == KeyFileStatus.Success seckey) == KeyFileStatus.Success
seckey.data == expectkey.data seckey.toRaw == expectkey.toRaw
test "KeyStoreTests/basic_tests.json evilnonce with wrong password": test "KeyStoreTests/basic_tests.json evilnonce with wrong password":
var seckey: PrivateKey var seckey: PrivateKey
check: check:
@ -117,7 +117,7 @@ suite "KeyFile test suite":
"wrongpassword", "wrongpassword",
seckey) == KeyFileStatus.IncorrectMac seckey) == KeyFileStatus.IncorrectMac
test "Create/Save/Load test": test "Create/Save/Load test":
var seckey0 = newPrivateKey() var seckey0 = PrivateKey.random()[]
var seckey1: PrivateKey var seckey1: PrivateKey
check: check:
createKeyFileJson(seckey0, "randompassword", createKeyFileJson(seckey0, "randompassword",
@ -125,7 +125,7 @@ suite "KeyFile test suite":
saveKeyFile("test.keyfile", jobject) == KeyFileStatus.Success saveKeyFile("test.keyfile", jobject) == KeyFileStatus.Success
loadKeyFile("test.keyfile", "randompassword", loadKeyFile("test.keyfile", "randompassword",
seckey1) == KeyFileStatus.Success seckey1) == KeyFileStatus.Success
seckey0.data == seckey1.data seckey0.toRaw == seckey1.toRaw
removeFile("test.keyfile") removeFile("test.keyfile")
test "Load non-existent pathname test": test "Load non-existent pathname test":
var seckey: PrivateKey var seckey: PrivateKey

View File

@ -17,7 +17,7 @@ suite "Test key and signature data structure":
test "Signing from private key object (ported from official eth-keys)": test "Signing from private key object (ported from official eth-keys)":
for person in [alice, bob, eve]: for person in [alice, bob, eve]:
let let
pk = initPrivateKey(person.privkey) pk = PrivateKey.fromHex(person.privkey)[]
signature = pk.sign_msg(MSG) signature = pk.sign_msg(MSG)
check: verify_msg(pk.public_key, MSG, signature) check: verify_msg(pk.public_key, MSG, signature)
@ -25,7 +25,7 @@ suite "Test key and signature data structure":
test "Hash signing from private key object (ported from official eth-keys)": test "Hash signing from private key object (ported from official eth-keys)":
for person in [alice, bob, eve]: for person in [alice, bob, eve]:
let let
pk = initPrivateKey(person.privkey) pk = PrivateKey.fromHex(person.privkey)[]
signature = pk.sign_msg(MSGHASH) signature = pk.sign_msg(MSGHASH)
check: verify_msg(pk.public_key, MSGHASH, signature) check: verify_msg(pk.public_key, MSGHASH, signature)
@ -33,7 +33,7 @@ suite "Test key and signature data structure":
test "Recover public key from message": test "Recover public key from message":
for person in [alice, bob, eve]: for person in [alice, bob, eve]:
let let
pk = initPrivateKey(person.privkey) pk = PrivateKey.fromHex(person.privkey)[]
signature = pk.sign_msg(MSG) signature = pk.sign_msg(MSG)
recovered_pubkey = recover_pubkey_from_msg(MSG, signature) recovered_pubkey = recover_pubkey_from_msg(MSG, signature)
@ -43,7 +43,7 @@ suite "Test key and signature data structure":
test "Recover public key from message hash": test "Recover public key from message hash":
for person in [alice, bob, eve]: for person in [alice, bob, eve]:
let let
pk = initPrivateKey(person.privkey) pk = PrivateKey.formHex(person.privkey)[]
signature = pk.sign_msg(MSGHASH) signature = pk.sign_msg(MSGHASH)
recovered_pubkey = recover_pubkey_from_msg(MSGHASH, signature) recovered_pubkey = recover_pubkey_from_msg(MSGHASH, signature)
@ -53,7 +53,7 @@ suite "Test key and signature data structure":
test "Signature serialization and deserialization": test "Signature serialization and deserialization":
for person in [alice, bob, eve]: for person in [alice, bob, eve]:
let let
pk = initPrivateKey(person.privkey) pk = PrivateKey.fromHex(person.privkey)[]
signature = pk.sign_msg(MSG) signature = pk.sign_msg(MSG)
deserializedSignature = parseSignature(hexToSeqByteBE(person.serialized_sig)) deserializedSignature = parseSignature(hexToSeqByteBE(person.serialized_sig))

View File

@ -12,6 +12,8 @@ import eth/keys
import nimcrypto/hash, nimcrypto/keccak, nimcrypto/utils import nimcrypto/hash, nimcrypto/keccak, nimcrypto/utils
from strutils import toLowerAscii from strutils import toLowerAscii
import stew/byteutils
proc compare(x: openarray[byte], y: openarray[byte]): bool = proc compare(x: openarray[byte], y: openarray[byte]): bool =
result = len(x) == len(y) result = len(x) == len(y)
if result: if result:
@ -19,9 +21,11 @@ proc compare(x: openarray[byte], y: openarray[byte]): bool =
if x[i] != y[i]: if x[i] != y[i]:
result = false result = false
break break
let message = "message".toBytes()
const const
pkbytes = "58d23b55bc9cdce1f18c2500f40ff4ab7245df9a89505e9b1fa4851f623d241d" pkbytes = "58d23b55bc9cdce1f18c2500f40ff4ab7245df9a89505e9b1fa4851f623d241d"
message = "message"
address = "dc544d1aa88ff8bbd2f2aec754b1f1e99e1812fd" address = "dc544d1aa88ff8bbd2f2aec754b1f1e99e1812fd"
alice = [ alice = [
@ -49,50 +53,50 @@ const
suite "ECC/ECDSA/ECDHE tests suite": suite "ECC/ECDSA/ECDHE tests suite":
test "Known private to known public keys (test data from Ethereum eth-keys)": test "Known private to known public keys (test data from Ethereum eth-keys)":
for person in [alice, bob, eve]: for person in [alice, bob, eve]:
let privkey = initPrivateKey(person[0]) let privkey = PrivateKey.fromHex(person[0])[]
var pubkeyHex = $privkey.getPublicKey() var pubkeyHex = $privkey.toPublicKey()[]
check: check:
pubkeyHex == stripSpaces(person[1]) pubkeyHex == stripSpaces(person[1])
test "Recover public key from message": test "Recover public key from message":
for person in [alice, bob, eve]: for person in [alice, bob, eve]:
let privkey = initPrivateKey(person[0]) let privkey = PrivateKey.fromHex(person[0])[]
let signature = privkey.signMessage(message) let signature = privkey.sign(message)[]
let recoveredKey = signature.recoverKeyFromSignature(message) let recoveredKey = signature.recover(message)[]
check: check:
$privkey.getPublicKey() == $recoveredKey $privkey.toPublicKey()[] == $recoveredKey
test "Signature serialization and deserialization": test "Signature serialization and deserialization":
for person in [alice, bob, eve]: for person in [alice, bob, eve]:
let privkey = initPrivateKey(person[0]) let privkey = PrivateKey.fromHex(person[0])[]
let signature = privkey.signMessage(message) let signature = privkey.sign(message)[]
let expectSignature = initSignature(person[2]) let expectSignature = Signature.fromHex(stripSpaces(person[2]))[]
check: check:
$signature == $expectSignature $signature == $expectSignature
test "test_recover_from_signature_obj": test "test_recover_from_signature_obj":
var s = initPrivateKey(pkbytes) var s = PrivateKey.fromHex(pkbytes)[]
var mhash = keccak256.digest(message) var mhash = keccak256.digest(message)
var signature = s.signMessage(message) var signature = s.sign(message)[]
var p = recoverKeyFromSignature(signature, mhash) var p = recover(signature, mhash)
check: check:
s.getPublicKey() == p s.toPublicKey() == p
test "test_to_address_from_public_key": test "test_to_address_from_public_key":
var s = initPrivateKey(pkbytes) var s = PrivateKey.fromHex(pkbytes)[]
var chk = s.getPublicKey().toAddress() var chk = s.toPublicKey()[].toAddress()
var expect = "0x" & address var expect = "0x" & address
check chk == expect check chk == expect
test "test_to_canonical_address_from_public_key": test "test_to_canonical_address_from_public_key":
var s = initPrivateKey(pkbytes) var s = PrivateKey.fromHex(pkbytes)[]
var chk = s.getPublicKey().toCanonicalAddress() var chk = s.toPublicKey()[].toCanonicalAddress()
var expect = fromHex(stripSpaces(address)) var expect = fromHex(stripSpaces(address))
check compare(chk, expect) == true check compare(chk, expect) == true
test "test_to_checksum_address_from_public_key": test "test_to_checksum_address_from_public_key":
var s = initPrivateKey(pkbytes) var s = PrivateKey.fromHex(pkbytes)[]
var chk = s.getPublicKey().toChecksumAddress() var chk = s.toPublicKey()[].toChecksumAddress()
var expect = "0x" & address var expect = "0x" & address
check: check:
chk.toLowerAscii() == expect chk.toLowerAscii() == expect
@ -124,7 +128,7 @@ suite "ECC/ECDSA/ECDHE tests suite":
test "EIP-55 100 addresses": test "EIP-55 100 addresses":
for i in 1..100: for i in 1..100:
var kp = newKeyPair() var kp = KeyPair.random()[]
var chaddress = kp.pubkey.toChecksumAddress() var chaddress = kp.pubkey.toChecksumAddress()
var noaddress = kp.pubkey.toAddress() var noaddress = kp.pubkey.toAddress()
if noaddress != chaddress: if noaddress != chaddress:
@ -149,13 +153,12 @@ suite "ECC/ECDSA/ECDHE tests suite":
"ee1418607c2fcfb57fda40380e885a707f49000a5dda056d828b7d9bd1f29a08", "ee1418607c2fcfb57fda40380e885a707f49000a5dda056d828b7d9bd1f29a08",
"167ccc13ac5e8a26b131c3446030c60fbfac6aa8e31149d0869f93626a4cdf62" "167ccc13ac5e8a26b131c3446030c60fbfac6aa8e31149d0869f93626a4cdf62"
] ]
var secret: SharedSecret
for i in 0..1: for i in 0..1:
var s = privateKeys[i].initPrivateKey() var s = PrivateKey.fromHex(privateKeys[i])[]
var p = publicKeys[i].initPublicKey() var p = PublicKey.fromHex(stripSpaces(publicKeys[i]))[]
let expect = fromHex(stripSpaces(sharedSecrets[i])) let expect = fromHex(stripSpaces(sharedSecrets[i]))
let secret = ecdhRaw(s, p)[]
check: check:
ecdhAgree(s, p, secret) == EthKeysStatus.Success
expect == secret.data expect == secret.data
test "ECDHE/cpp-ethereum crypto.cpp#L394": test "ECDHE/cpp-ethereum crypto.cpp#L394":
@ -163,12 +166,11 @@ suite "ECC/ECDSA/ECDHE tests suite":
# Copied from https://github.com/ethereum/cpp-ethereum/blob/develop/test/unittests/libdevcrypto/crypto.cpp#L394 # Copied from https://github.com/ethereum/cpp-ethereum/blob/develop/test/unittests/libdevcrypto/crypto.cpp#L394
var expectm = """ var expectm = """
8ac7e464348b85d9fdfc0a81f2fdc0bbbb8ee5fb3840de6ed60ad9372e718977""" 8ac7e464348b85d9fdfc0a81f2fdc0bbbb8ee5fb3840de6ed60ad9372e718977"""
var secret: SharedSecret var s = PrivateKey.fromRaw(keccak256.digest("ecdhAgree").data)[]
var s = initPrivateKey(keccak256.digest("ecdhAgree").data) var p = s.toPublicKey()[]
var p = s.getPublicKey()
let expect = fromHex(stripSpaces(expectm)) let expect = fromHex(stripSpaces(expectm))
let secret = ecdhRaw(s, p)[]
check: check:
ecdhAgree(s, p, secret) == EthKeysStatus.Success
expect == secret.data expect == secret.data
test "ECDHE/cpp-ethereum rlpx.cpp#L425": test "ECDHE/cpp-ethereum rlpx.cpp#L425":
@ -181,12 +183,11 @@ suite "ECC/ECDSA/ECDHE tests suite":
7f0821367332598b6aa4e180a41e92f4ebbae3518da847f0b1c0bbfe20bcf4e1""" 7f0821367332598b6aa4e180a41e92f4ebbae3518da847f0b1c0bbfe20bcf4e1"""
var e0 = """ var e0 = """
ee1418607c2fcfb57fda40380e885a707f49000a5dda056d828b7d9bd1f29a08""" ee1418607c2fcfb57fda40380e885a707f49000a5dda056d828b7d9bd1f29a08"""
var secret: SharedSecret var s = PrivateKey.fromHex(stripSpaces(s0))[]
var s = initPrivateKey(s0) var p = PublicKey.fromHex(stripSpaces(p0))[]
var p = initPublicKey(p0)
let expect = fromHex(stripSpaces(e0)) let expect = fromHex(stripSpaces(e0))
let secret = ecdhRaw(s, p)[]
check: check:
ecdhAgree(s, p, secret) == Success
compare(expect, secret.data) == true compare(expect, secret.data) == true
test "ECDSA/cpp-ethereum crypto.cpp#L132": test "ECDSA/cpp-ethereum crypto.cpp#L132":
@ -200,72 +201,62 @@ suite "ECC/ECDSA/ECDHE tests suite":
84453b0b24f49086feba0bd978bb4446bae8dff1e79fcc1e9cf482ec2d07c3""" 84453b0b24f49086feba0bd978bb4446bae8dff1e79fcc1e9cf482ec2d07c3"""
var check1 = fromHex(stripSpaces(signature)) var check1 = fromHex(stripSpaces(signature))
var check2 = fromHex(stripSpaces(pubkey)) var check2 = fromHex(stripSpaces(pubkey))
var sig: Signature
var key: PublicKey var s = PrivateKey.fromRaw(keccak256.digest("sec").data)[]
var s = initPrivateKey(keccak256.digest("sec").data) var m = keccak256.digest("msg")
var m = keccak256.digest("msg").data var sig = sign(s, m)[]
check signRawMessage(m, s, sig) == Success var sersig = sig.toRaw()
var sersig = sig.getRaw() var key = recover(sig, m)[]
check recoverSignatureKey(sersig, m, key) == Success var serkey = key.toRaw()
var serkey = key.getRaw()
check: check:
compare(sersig, check1) == true compare(sersig, check1) == true
compare(serkey, check2) == true compare(serkey, check2) == true
test "ECDSA/100 signatures": test "ECDSA/100 signatures":
# signature test # signature test
var rkey: PublicKey
var sig: Signature
for i in 1..100: for i in 1..100:
var m = newPrivateKey().data var m = PrivateKey.random()[].toRaw
var s = newPrivateKey() var s = PrivateKey.random()[]
var key = s.getPublicKey() var key = s.toPublicKey()[]
check signRawMessage(m, s, sig) == Success let sig = sign(s, m)[]
var sersig = sig.getRaw() let rkey = recover(sig, m)[]
check: check:
recoverSignatureKey(sersig, m, rkey) == Success
key == rkey key == rkey
test "KEYS/100 create/recovery keys": test "KEYS/100 create/recovery keys":
# key create/recovery test # key create/recovery test
var rkey: PublicKey
for i in 1..100: for i in 1..100:
var s = newPrivateKey() var s = PrivateKey.random()[]
var key = s.getPublicKey() var key = s.toPublicKey()[]
let rkey = PublicKey.fromRaw(key.toRaw())[]
check: check:
recoverPublicKey(key.getRaw(), rkey) == Success
key == rkey key == rkey
test "ECDHE/100 shared secrets": test "ECDHE/100 shared secrets":
# ECDHE shared secret test # ECDHE shared secret test
var secret1, secret2: SharedSecret
for i in 1..100: for i in 1..100:
var aliceSecret = newPrivateKey() var aliceSecret = PrivateKey.random()[]
var alicePublic = aliceSecret.getPublicKey() var alicePublic = aliceSecret.toPublicKey()[]
var bobSecret = newPrivateKey() var bobSecret = PrivateKey.random()[]
var bobPublic = bobSecret.getPublicKey() var bobPublic = bobSecret.toPublicKey()[]
var secret1 = ecdhRaw(aliceSecret, bobPublic)[]
var secret2 = ecdhRaw(bobSecret, alicePublic)[]
check: check:
ecdhAgree(aliceSecret, bobPublic, secret1) == Success
ecdhAgree(bobSecret, alicePublic, secret2) == Success
secret1 == secret2 secret1 == secret2
test "isZeroKey() checks": test "verfiy() checks":
var seckey1: PrivateKey var seckey1: PrivateKey
var pubkey1: PublicKey var seckey2 = PrivateKey.random()[]
var seckey2 = newPrivateKey()
var pubkey2 = seckey2.getPublicKey()
check: check:
seckey1.isZeroKey() == true seckey1.verify() == false
pubkey1.isZeroKey() == true seckey2.verify() == true
seckey2.isZeroKey() == false
pubkey2.isZeroKey() == false
test "Compressed public keys": test "Compressed public keys":
let pubkeyCompressed = "03CA634CAE0D49ACB401D8A4C6B6FE8C55B70D115BF400769CC1400F3258CD3138" let pubkeyCompressed = "03CA634CAE0D49ACB401D8A4C6B6FE8C55B70D115BF400769CC1400F3258CD3138".toLowerAscii
let s = initPublicKey(pubkeyCompressed) let s = PublicKey.fromHex(pubkeyCompressed)[]
check: check:
s.getRaw.toHex == """CA634CAE0D49ACB401D8A4C6B6FE8C55B70D115BF400769CC1400F3258 s.toRaw.toHex == """CA634CAE0D49ACB401D8A4C6B6FE8C55B70D115BF400769CC1400F3258
CD31387574077F301B421BC84DF7266C44E9E6D569FC56BE00812904767BF5CCD1FC7F""".stripSpaces CD31387574077F301B421BC84DF7266C44E9E6D569FC56BE00812904767BF5CCD1FC7F""".stripSpaces.toLowerAscii
s.getRawCompressed.toHex == pubkeyCompressed s.toRawCompressed.toHex == pubkeyCompressed

View File

@ -16,12 +16,12 @@ suite "Testing private -> public key conversion":
test "Known private to known public keys (test data from Ethereum eth-keys)": test "Known private to known public keys (test data from Ethereum eth-keys)":
for person in [alice, bob, eve]: for person in [alice, bob, eve]:
let let
privKey = initPrivateKey(person.privkey) privKey = PrivateKey.fromHex(person.privkey)[]
pubKey = privKey.getPublicKey pubKey = privKey.toPublicKey()[]
check: check:
# Compare as strings # Compare as strings
$pubKey == person.pubkey $pubKey == person.pubkey
# Compare as keys # Compare as keys
pubKey == initPublicKey(person.pubkey) pubKey == PublicKey.fromHex(person.pubkey)[]

View File

@ -22,7 +22,7 @@ template asyncTest(name, body: untyped) =
asyncTest "network with 3 peers using the Whisper protocol": asyncTest "network with 3 peers using the Whisper protocol":
const useCompression = defined(useSnappy) const useCompression = defined(useSnappy)
let localKeys = newKeyPair() let localKeys = KeyPair.random()[]
let localAddress = localAddress(30303) let localAddress = localAddress(30303)
var localNode = newEthereumNode(localKeys, localAddress, 1, nil, var localNode = newEthereumNode(localKeys, localAddress, 1, nil,
addAllCapabilities = false, addAllCapabilities = false,

View File

@ -17,13 +17,13 @@ proc startDiscoveryNode*(privKey: PrivateKey, address: Address,
proc setupBootNode*(): Future[ENode] {.async.} = proc setupBootNode*(): Future[ENode] {.async.} =
let let
bootNodeKey = newPrivateKey() bootNodeKey = KeyPair.random()[]
bootNodeAddr = localAddress(30301) bootNodeAddr = localAddress(30301)
bootNode = await startDiscoveryNode(bootNodeKey, bootNodeAddr, @[]) bootNode = await startDiscoveryNode(bootNodeKey.seckey, bootNodeAddr, @[])
result = initENode(bootNodeKey.getPublicKey, bootNodeAddr) result = initENode(bootNodeKey.pubkey, bootNodeAddr)
proc setupTestNode*(capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode = proc setupTestNode*(capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode =
let keys1 = newKeyPair() let keys1 = KeyPair.random()[]
result = newEthereumNode(keys1, localAddress(nextPort), 1, nil, result = newEthereumNode(keys1, localAddress(nextPort), 1, nil,
addAllCapabilities = false) addAllCapabilities = false)
nextPort.inc nextPort.inc
@ -45,7 +45,7 @@ template procSuite*(name, body: untyped) =
proc packData*(payload: openArray[byte], pk: PrivateKey): seq[byte] = proc packData*(payload: openArray[byte], pk: PrivateKey): seq[byte] =
let let
payloadSeq = @payload payloadSeq = @payload
signature = @(pk.signMessage(payload).getRaw()) signature = @(pk.sign(payload).tryGet().toRaw())
msgHash = keccak256.digest(signature & payloadSeq) msgHash = keccak256.digest(signature & payloadSeq)
result = @(msgHash.data) & signature & payloadSeq result = @(msgHash.data) & signature & payloadSeq

View File

@ -79,15 +79,17 @@ if config.main:
else: else:
netId = 15 netId = 15
let keypair = newKeyPair() let keypair = KeyPair.random()[]
var node = newEthereumNode(keypair, address, netId, nil, addAllCapabilities = false) var node = newEthereumNode(keypair, address, netId, nil, addAllCapabilities = false)
node.addCapability Whisper node.addCapability Whisper
# lets prepare some prearranged keypairs # lets prepare some prearranged keypairs
let encPrivateKey = initPrivateKey("5dc5381cae54ba3174dc0d46040fe11614d0cc94d41185922585198b4fcef9d3") let encPrivateKey = PrivateKey.fromHex(
let encPublicKey = encPrivateKey.getPublicKey() "5dc5381cae54ba3174dc0d46040fe11614d0cc94d41185922585198b4fcef9d3")[]
let signPrivateKey = initPrivateKey("365bda0757d22212b04fada4b9222f8c3da59b49398fa04cf612481cd893b0a3") let encPublicKey = encPrivateKey.toPublicKey()[]
let signPublicKey = signPrivateKey.getPublicKey() let signPrivateKey = PrivateKey.fromHex(
"365bda0757d22212b04fada4b9222f8c3da59b49398fa04cf612481cd893b0a3")[]
let signPublicKey = signPrivateKey.toPublicKey()[]
var symKey: SymKey var symKey: SymKey
# To test with geth: all 0's key is invalid in geth console # To test with geth: all 0's key is invalid in geth console
symKey[31] = 1 symKey[31] = 1

View File

@ -217,19 +217,19 @@ suite "Ethereum P2P handshake test suite":
proc newTestHandshake(flags: set[HandshakeFlag]): Handshake = proc newTestHandshake(flags: set[HandshakeFlag]): Handshake =
result = newHandshake(flags) result = newHandshake(flags)
if Initiator in flags: if Initiator in flags:
result.host.seckey = initPrivateKey(testValue("initiator_private_key")) result.host.seckey = PrivateKey.fromHex(testValue("initiator_private_key"))[]
result.host.pubkey = result.host.seckey.getPublicKey() result.host.pubkey = result.host.seckey.toPublicKey()[]
let epki = testValue("initiator_ephemeral_private_key") let epki = testValue("initiator_ephemeral_private_key")
result.ephemeral.seckey = initPrivateKey(epki) result.ephemeral.seckey = PrivateKey.fromHex(epki)[]
result.ephemeral.pubkey = result.ephemeral.seckey.getPublicKey() result.ephemeral.pubkey = result.ephemeral.seckey.toPublicKey()[]
let nonce = fromHex(stripSpaces(testValue("initiator_nonce"))) let nonce = fromHex(stripSpaces(testValue("initiator_nonce")))
result.initiatorNonce[0..^1] = nonce[0..^1] result.initiatorNonce[0..^1] = nonce[0..^1]
elif Responder in flags: elif Responder in flags:
result.host.seckey = initPrivateKey(testValue("receiver_private_key")) result.host.seckey = PrivateKey.fromHex(testValue("receiver_private_key"))[]
result.host.pubkey = result.host.seckey.getPublicKey() result.host.pubkey = result.host.seckey.toPublicKey()[]
let epkr = testValue("receiver_ephemeral_private_key") let epkr = testValue("receiver_ephemeral_private_key")
result.ephemeral.seckey = initPrivateKey(epkr) result.ephemeral.seckey = PrivateKey.fromHex(epkr)[]
result.ephemeral.pubkey = result.ephemeral.seckey.getPublicKey() result.ephemeral.pubkey = result.ephemeral.seckey.toPublicKey()[]
let nonce = fromHex(stripSpaces(testValue("receiver_nonce"))) let nonce = fromHex(stripSpaces(testValue("receiver_nonce")))
result.responderNonce[0..^1] = nonce[0..^1] result.responderNonce[0..^1] = nonce[0..^1]
@ -252,15 +252,15 @@ suite "Ethereum P2P handshake test suite":
var responder = newTestHandshake({Responder}) var responder = newTestHandshake({Responder})
var m0 = newSeq[byte](initiator.authSize()) var m0 = newSeq[byte](initiator.authSize())
var k0 = 0 var k0 = 0
let remoteEPubkey0 = initiator.ephemeral.pubkey.data let remoteEPubkey0 = initiator.ephemeral.pubkey
let remoteHPubkey0 = initiator.host.pubkey.data let remoteHPubkey0 = initiator.host.pubkey
check: check:
initiator.authMessage(responder.host.pubkey, initiator.authMessage(responder.host.pubkey,
m0, k0) == AuthStatus.Success m0, k0) == AuthStatus.Success
responder.decodeAuthMessage(m0) == AuthStatus.Success responder.decodeAuthMessage(m0) == AuthStatus.Success
responder.initiatorNonce[0..^1] == initiator.initiatorNonce[0..^1] responder.initiatorNonce[0..^1] == initiator.initiatorNonce[0..^1]
responder.remoteEPubkey.data[0..^1] == remoteEPubkey0[0..^1] responder.remoteEPubkey == remoteEPubkey0
responder.remoteHPubkey.data[0..^1] == remoteHPubkey0[0..^1] responder.remoteHPubkey == remoteHPubkey0
test "ACK message expectation": test "ACK message expectation":
var initiator = newTestHandshake({Initiator}) var initiator = newTestHandshake({Initiator})
@ -291,11 +291,11 @@ suite "Ethereum P2P handshake test suite":
responder.decodeAuthMessage(m0) == AuthStatus.Success responder.decodeAuthMessage(m0) == AuthStatus.Success
responder.ackMessage(m1, k1) == AuthStatus.Success responder.ackMessage(m1, k1) == AuthStatus.Success
initiator.decodeAckMessage(m1) == AuthStatus.Success initiator.decodeAckMessage(m1) == AuthStatus.Success
let remoteEPubkey0 = responder.ephemeral.pubkey.data let remoteEPubkey0 = responder.ephemeral.pubkey
let remoteHPubkey0 = responder.host.pubkey.data let remoteHPubkey0 = responder.host.pubkey
check: check:
initiator.remoteEPubkey.data[0..^1] == remoteEPubkey0[0..^1] initiator.remoteEPubkey == remoteEPubkey0
initiator.remoteHPubkey.data[0..^1] == remoteHPubkey0[0..^1] initiator.remoteHPubkey == remoteHPubkey0
initiator.responderNonce == responder.responderNonce initiator.responderNonce == responder.responderNonce
test "Check derived secrets": test "Check derived secrets":
@ -332,19 +332,19 @@ suite "Ethereum P2P handshake test suite":
proc newTestHandshake(flags: set[HandshakeFlag]): Handshake = proc newTestHandshake(flags: set[HandshakeFlag]): Handshake =
result = newHandshake(flags) result = newHandshake(flags)
if Initiator in flags: if Initiator in flags:
result.host.seckey = initPrivateKey(testE8Value("initiator_private_key")) result.host.seckey = PrivateKey.fromHex(testE8Value("initiator_private_key"))[]
result.host.pubkey = result.host.seckey.getPublicKey() result.host.pubkey = result.host.seckey.toPublicKey()[]
let esec = testE8Value("initiator_ephemeral_private_key") let esec = testE8Value("initiator_ephemeral_private_key")
result.ephemeral.seckey = initPrivateKey(esec) result.ephemeral.seckey = PrivateKey.fromHex(esec)[]
result.ephemeral.pubkey = result.ephemeral.seckey.getPublicKey() result.ephemeral.pubkey = result.ephemeral.seckey.toPublicKey()[]
let nonce = fromHex(stripSpaces(testE8Value("initiator_nonce"))) let nonce = fromHex(stripSpaces(testE8Value("initiator_nonce")))
result.initiatorNonce[0..^1] = nonce[0..^1] result.initiatorNonce[0..^1] = nonce[0..^1]
elif Responder in flags: elif Responder in flags:
result.host.seckey = initPrivateKey(testE8Value("receiver_private_key")) result.host.seckey = PrivateKey.fromHex(testE8Value("receiver_private_key"))[]
result.host.pubkey = result.host.seckey.getPublicKey() result.host.pubkey = result.host.seckey.toPublicKey()[]
let esec = testE8Value("receiver_ephemeral_private_key") let esec = testE8Value("receiver_ephemeral_private_key")
result.ephemeral.seckey = initPrivateKey(esec) result.ephemeral.seckey = PrivateKey.fromHex(esec)[]
result.ephemeral.pubkey = result.ephemeral.seckey.getPublicKey() result.ephemeral.pubkey = result.ephemeral.seckey.toPublicKey()[]
let nonce = fromHex(stripSpaces(testE8Value("receiver_nonce"))) let nonce = fromHex(stripSpaces(testE8Value("receiver_nonce")))
result.responderNonce[0..^1] = nonce[0..^1] result.responderNonce[0..^1] = nonce[0..^1]
@ -355,16 +355,16 @@ suite "Ethereum P2P handshake test suite":
check: check:
responder.decodeAuthMessage(m0) == AuthStatus.Success responder.decodeAuthMessage(m0) == AuthStatus.Success
responder.initiatorNonce[0..^1] == initiator.initiatorNonce[0..^1] responder.initiatorNonce[0..^1] == initiator.initiatorNonce[0..^1]
let remoteEPubkey0 = initiator.ephemeral.pubkey.data let remoteEPubkey0 = initiator.ephemeral.pubkey
let remoteHPubkey0 = initiator.host.pubkey.data let remoteHPubkey0 = initiator.host.pubkey
check: check:
responder.remoteEPubkey.data[0..^1] == remoteEPubkey0[0..^1] responder.remoteEPubkey == remoteEPubkey0
responder.remoteHPubkey.data[0..^1] == remoteHPubkey0[0..^1] responder.remoteHPubkey == remoteHPubkey0
var m1 = fromHex(stripSpaces(testE8Value("authack_ciphertext_v4"))) var m1 = fromHex(stripSpaces(testE8Value("authack_ciphertext_v4")))
check initiator.decodeAckMessage(m1) == AuthStatus.Success check initiator.decodeAckMessage(m1) == AuthStatus.Success
let remoteEPubkey1 = responder.ephemeral.pubkey.data let remoteEPubkey1 = responder.ephemeral.pubkey
check: check:
initiator.remoteEPubkey.data[0..^1] == remoteEPubkey1[0..^1] initiator.remoteEPubkey == remoteEPubkey1
initiator.responderNonce[0..^1] == responder.responderNonce[0..^1] initiator.responderNonce[0..^1] == responder.responderNonce[0..^1]
test "AUTH/ACK EIP-8 test vectors": test "AUTH/ACK EIP-8 test vectors":
@ -374,15 +374,15 @@ suite "Ethereum P2P handshake test suite":
check: check:
responder.decodeAuthMessage(m0) == AuthStatus.Success responder.decodeAuthMessage(m0) == AuthStatus.Success
responder.initiatorNonce[0..^1] == initiator.initiatorNonce[0..^1] responder.initiatorNonce[0..^1] == initiator.initiatorNonce[0..^1]
let remoteEPubkey0 = initiator.ephemeral.pubkey.data let remoteEPubkey0 = initiator.ephemeral.pubkey
check responder.remoteEPubkey.data[0..^1] == remoteEPubkey0[0..^1] check responder.remoteEPubkey == remoteEPubkey0
let remoteHPubkey0 = initiator.host.pubkey.data let remoteHPubkey0 = initiator.host.pubkey
check responder.remoteHPubkey.data[0..^1] == remoteHPubkey0[0..^1] check responder.remoteHPubkey == remoteHPubkey0
var m1 = fromHex(stripSpaces(testE8Value("authack_ciphertext_eip8"))) var m1 = fromHex(stripSpaces(testE8Value("authack_ciphertext_eip8")))
check initiator.decodeAckMessage(m1) == AuthStatus.Success check initiator.decodeAckMessage(m1) == AuthStatus.Success
let remoteEPubkey1 = responder.ephemeral.pubkey.data let remoteEPubkey1 = responder.ephemeral.pubkey
check: check:
initiator.remoteEPubkey.data[0..^1] == remoteEPubkey1[0..^1] initiator.remoteEPubkey == remoteEPubkey1
initiator.responderNonce[0..^1] == responder.responderNonce[0..^1] initiator.responderNonce[0..^1] == responder.responderNonce[0..^1]
var taes = fromHex(stripSpaces(testE8Value("auth2ack2_aes_secret"))) var taes = fromHex(stripSpaces(testE8Value("auth2ack2_aes_secret")))
var tmac = fromHex(stripSpaces(testE8Value("auth2ack2_mac_secret"))) var tmac = fromHex(stripSpaces(testE8Value("auth2ack2_mac_secret")))
@ -410,18 +410,18 @@ suite "Ethereum P2P handshake test suite":
check: check:
responder.decodeAuthMessage(m0) == AuthStatus.Success responder.decodeAuthMessage(m0) == AuthStatus.Success
responder.initiatorNonce[0..^1] == initiator.initiatorNonce[0..^1] responder.initiatorNonce[0..^1] == initiator.initiatorNonce[0..^1]
let remoteEPubkey0 = initiator.ephemeral.pubkey.data let remoteEPubkey0 = initiator.ephemeral.pubkey
let remoteHPubkey0 = initiator.host.pubkey.data let remoteHPubkey0 = initiator.host.pubkey
check: check:
responder.remoteEPubkey.data[0..^1] == remoteEPubkey0[0..^1] responder.remoteEPubkey == remoteEPubkey0
responder.remoteHPubkey.data[0..^1] == remoteHPubkey0[0..^1] responder.remoteHPubkey == remoteHPubkey0
var m1 = fromHex(stripSpaces(testE8Value("authack_ciphertext_eip8_3f"))) var m1 = fromHex(stripSpaces(testE8Value("authack_ciphertext_eip8_3f")))
check initiator.decodeAckMessage(m1) == AuthStatus.Success check initiator.decodeAckMessage(m1) == AuthStatus.Success
let remoteEPubkey1 = responder.ephemeral.pubkey.data let remoteEPubkey1 = responder.ephemeral.pubkey
check: check:
int(initiator.version) == 57 int(initiator.version) == 57
int(responder.version) == 56 int(responder.version) == 56
initiator.remoteEPubkey.data[0..^1] == remoteEPubkey1[0..^1] initiator.remoteEPubkey == remoteEPubkey1
initiator.responderNonce[0..^1] == responder.responderNonce[0..^1] initiator.responderNonce[0..^1] == responder.responderNonce[0..^1]
test "100 AUTH/ACK EIP-8 handshakes": test "100 AUTH/ACK EIP-8 handshakes":

View File

@ -90,19 +90,19 @@ suite "Ethereum RLPx encryption/decryption test suite":
proc newTestHandshake(flags: set[HandshakeFlag]): Handshake = proc newTestHandshake(flags: set[HandshakeFlag]): Handshake =
result = newHandshake(flags) result = newHandshake(flags)
if Initiator in flags: if Initiator in flags:
result.host.seckey = initPrivateKey(testValue("initiator_private_key")) result.host.seckey = PrivateKey.fromHex(testValue("initiator_private_key"))[]
result.host.pubkey = result.host.seckey.getPublicKey() result.host.pubkey = result.host.seckey.toPublicKey()[]
let epki = testValue("initiator_ephemeral_private_key") let epki = testValue("initiator_ephemeral_private_key")
result.ephemeral.seckey = initPrivateKey(epki) result.ephemeral.seckey = PrivateKey.fromHex(epki)[]
result.ephemeral.pubkey = result.ephemeral.seckey.getPublicKey() result.ephemeral.pubkey = result.ephemeral.seckey.toPublicKey()[]
let nonce = fromHex(stripSpaces(testValue("initiator_nonce"))) let nonce = fromHex(stripSpaces(testValue("initiator_nonce")))
result.initiatorNonce[0..^1] = nonce[0..^1] result.initiatorNonce[0..^1] = nonce[0..^1]
elif Responder in flags: elif Responder in flags:
result.host.seckey = initPrivateKey(testValue("receiver_private_key")) result.host.seckey = PrivateKey.fromHex(testValue("receiver_private_key"))[]
result.host.pubkey = result.host.seckey.getPublicKey() result.host.pubkey = result.host.seckey.toPublicKey()[]
let epkr = testValue("receiver_ephemeral_private_key") let epkr = testValue("receiver_ephemeral_private_key")
result.ephemeral.seckey = initPrivateKey(epkr) result.ephemeral.seckey = PrivateKey.fromHex(epkr)[]
result.ephemeral.pubkey = result.ephemeral.seckey.getPublicKey() result.ephemeral.pubkey = result.ephemeral.seckey.toPublicKey()[]
let nonce = fromHex(stripSpaces(testValue("receiver_nonce"))) let nonce = fromHex(stripSpaces(testValue("receiver_nonce")))
result.responderNonce[0..^1] = nonce[0..^1] result.responderNonce[0..^1] = nonce[0..^1]

View File

@ -19,16 +19,20 @@ proc nodeIdInNodes(id: NodeId, nodes: openarray[Node]): bool =
proc test() {.async.} = proc test() {.async.} =
suite "Discovery Tests": suite "Discovery Tests":
let let
bootNodeKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617") bootNodeKey = PrivateKey.fromHex(
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[]
bootNodeAddr = localAddress(20301) bootNodeAddr = localAddress(20301)
bootENode = initENode(bootNodeKey.getPublicKey, bootNodeAddr) bootENode = initENode(bootNodeKey.toPublicKey()[], bootNodeAddr)
bootNode = await startDiscoveryNode(bootNodeKey, bootNodeAddr, @[]) bootNode = await startDiscoveryNode(bootNodeKey, bootNodeAddr, @[])
test "Discover nodes": test "Discover nodes":
let nodeKeys = [ let nodeKeys = [
initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618"), PrivateKey.fromHex(
initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619"), "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[],
initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a620") PrivateKey.fromHex(
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619")[],
PrivateKey.fromHex(
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a620")[]
] ]
var nodeAddrs = newSeqOfCap[Address](nodeKeys.len) var nodeAddrs = newSeqOfCap[Address](nodeKeys.len)
for i in 0 ..< nodeKeys.len: nodeAddrs.add(localAddress(20302 + i)) for i in 0 ..< nodeKeys.len: nodeAddrs.add(localAddress(20302 + i))
@ -62,7 +66,8 @@ proc test() {.async.} =
] ]
let let
address = localAddress(20302) address = localAddress(20302)
nodeKey = initPrivateKey("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") nodeKey = PrivateKey.fromHex(
"b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")[]
for data in validProtocolData: for data in validProtocolData:
# none of these may raise # none of these may raise
@ -80,7 +85,8 @@ proc test() {.async.} =
] ]
let let
address = localAddress(20302) address = localAddress(20302)
nodeKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618") nodeKey = PrivateKey.fromHex(
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[]
for data in invalidProtocolData: for data in invalidProtocolData:
expect DiscProtocolError: expect DiscProtocolError:

View File

@ -26,13 +26,13 @@ proc randomPacket(tag: PacketTag): seq[byte] =
authTag: AuthTag authTag: AuthTag
msg: array[44, byte] msg: array[44, byte]
randomBytes(authTag) randomBytes2(authTag)
randomBytes(msg) randomBytes2(msg)
result.add(tag) result.add(tag)
result.add(rlp.encode(authTag)) result.add(rlp.encode(authTag))
result.add(msg) result.add(msg)
proc generateNode(privKey = newPrivateKey(), port: int): Node = proc generateNode(privKey = PrivateKey.random()[], port: int): Node =
let port = Port(port) let port = Port(port)
let enr = enr.Record.init(1, privKey, some(parseIpAddress("127.0.0.1")), let enr = enr.Record.init(1, privKey, some(parseIpAddress("127.0.0.1")),
port, port) port, port)
@ -41,13 +41,17 @@ proc generateNode(privKey = newPrivateKey(), port: int): Node =
suite "Discovery v5 Tests": suite "Discovery v5 Tests":
asyncTest "Random nodes": asyncTest "Random nodes":
let let
bootNodeKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617") bootNodeKey = PrivateKey.fromHex(
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[]
bootNode = initDiscoveryNode(bootNodeKey, localAddress(20301)) bootNode = initDiscoveryNode(bootNodeKey, localAddress(20301))
let nodeKeys = [ let nodeKeys = [
initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618"), PrivateKey.fromHex(
initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619"), "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[],
initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a620") PrivateKey.fromHex(
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619")[],
PrivateKey.fromHex(
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a620")[]
] ]
var nodeAddrs = newSeqOfCap[Address](nodeKeys.len) var nodeAddrs = newSeqOfCap[Address](nodeKeys.len)
for i in 0 ..< nodeKeys.len: nodeAddrs.add(localAddress(20302 + i)) for i in 0 ..< nodeKeys.len: nodeAddrs.add(localAddress(20302 + i))
@ -74,13 +78,13 @@ suite "Discovery v5 Tests":
const const
nodeCount = 17 nodeCount = 17
let bootNode = initDiscoveryNode(newPrivateKey(), localAddress(20301)) let bootNode = initDiscoveryNode(PrivateKey.random()[], localAddress(20301))
bootNode.start() bootNode.start()
var nodes = newSeqOfCap[discv5_protocol.Protocol](nodeCount) var nodes = newSeqOfCap[discv5_protocol.Protocol](nodeCount)
nodes.add(bootNode) nodes.add(bootNode)
for i in 1 ..< nodeCount: for i in 1 ..< nodeCount:
nodes.add(initDiscoveryNode(newPrivateKey(), localAddress(20301 + i), nodes.add(initDiscoveryNode(PrivateKey.random()[], localAddress(20301 + i),
@[bootNode.localNode.record])) @[bootNode.localNode.record]))
nodes[i].start() nodes[i].start()
@ -96,7 +100,7 @@ suite "Discovery v5 Tests":
asyncTest "FindNode with test table": asyncTest "FindNode with test table":
let mainNode = initDiscoveryNode(newPrivateKey(), localAddress(20301)) let mainNode = initDiscoveryNode(PrivateKey.random()[], localAddress(20301))
# Generate 1000 random nodes and add to our main node's routing table # Generate 1000 random nodes and add to our main node's routing table
for i in 0..<1000: for i in 0..<1000:
@ -110,7 +114,7 @@ suite "Discovery v5 Tests":
debug "Closest neighbour", closestDistance, id=closest.id.toHex() debug "Closest neighbour", closestDistance, id=closest.id.toHex()
let let
testNode = initDiscoveryNode(newPrivateKey(), localAddress(20302), testNode = initDiscoveryNode(PrivateKey.random()[], localAddress(20302),
@[mainNode.localNode.record]) @[mainNode.localNode.record])
discovered = await discv5_protocol.findNode(testNode, mainNode.localNode, discovered = await discv5_protocol.findNode(testNode, mainNode.localNode,
closestDistance) closestDistance)
@ -123,7 +127,7 @@ suite "Discovery v5 Tests":
asyncTest "GetNode": asyncTest "GetNode":
# TODO: This could be tested in just a routing table only context # TODO: This could be tested in just a routing table only context
let let
node = initDiscoveryNode(newPrivateKey(), localAddress(20302)) node = initDiscoveryNode(PrivateKey.random()[], localAddress(20302))
targetNode = generateNode(port = 20303) targetNode = generateNode(port = 20303)
node.addNode(targetNode) node.addNode(targetNode)
@ -137,10 +141,10 @@ suite "Discovery v5 Tests":
asyncTest "Node deletion": asyncTest "Node deletion":
let let
bootnode = initDiscoveryNode(newPrivateKey(), localAddress(20301)) bootnode = initDiscoveryNode(PrivateKey.random()[], localAddress(20301))
node1 = initDiscoveryNode(newPrivateKey(), localAddress(20302), node1 = initDiscoveryNode(PrivateKey.random()[], localAddress(20302),
@[bootnode.localNode.record]) @[bootnode.localNode.record])
node2 = initDiscoveryNode(newPrivateKey(), localAddress(20303), node2 = initDiscoveryNode(PrivateKey.random()[], localAddress(20303),
@[bootnode.localNode.record]) @[bootnode.localNode.record])
pong1 = await discv5_protocol.ping(node1, bootnode.localNode) pong1 = await discv5_protocol.ping(node1, bootnode.localNode)
pong2 = await discv5_protocol.ping(node1, node2.localNode) pong2 = await discv5_protocol.ping(node1, node2.localNode)
@ -160,12 +164,12 @@ suite "Discovery v5 Tests":
asyncTest "Handshake cleanup": asyncTest "Handshake cleanup":
let node = initDiscoveryNode(newPrivateKey(), localAddress(20302)) let node = initDiscoveryNode(PrivateKey.random()[], localAddress(20302))
var tag: PacketTag var tag: PacketTag
let a = localAddress(20303) let a = localAddress(20303)
for i in 0 ..< 5: for i in 0 ..< 5:
randomBytes(tag) randomBytes2(tag)
node.receive(a, randomPacket(tag)) node.receive(a, randomPacket(tag))
# Checking different nodeIds but same address # Checking different nodeIds but same address
@ -179,7 +183,7 @@ suite "Discovery v5 Tests":
await node.closeWait() await node.closeWait()
asyncTest "Handshake different address": asyncTest "Handshake different address":
let node = initDiscoveryNode(newPrivateKey(), localAddress(20302)) let node = initDiscoveryNode(PrivateKey.random()[], localAddress(20302))
var tag: PacketTag var tag: PacketTag
for i in 0 ..< 5: for i in 0 ..< 5:
@ -191,7 +195,7 @@ suite "Discovery v5 Tests":
await node.closeWait() await node.closeWait()
asyncTest "Handshake duplicates": asyncTest "Handshake duplicates":
let node = initDiscoveryNode(newPrivateKey(), localAddress(20302)) let node = initDiscoveryNode(PrivateKey.random()[], localAddress(20302))
var tag: PacketTag var tag: PacketTag
let a = localAddress(20303) let a = localAddress(20303)
@ -235,8 +239,8 @@ suite "Discovery v5 Tests":
("8c5b422155d33ea8e9d46f71d1ad3e7b24cb40051413ffa1a81cff613d243ba9", 256'u32) ("8c5b422155d33ea8e9d46f71d1ad3e7b24cb40051413ffa1a81cff613d243ba9", 256'u32)
] ]
let targetId = toNodeId(initPublicKey(targetKey)) let targetId = toNodeId(PublicKey.fromHex(targetKey)[])
for (key, d) in testValues: for (key, d) in testValues:
let id = toNodeId(initPrivateKey(key).getPublicKey()) let id = toNodeId(PrivateKey.fromHex(key)[].toPublicKey()[])
check logDist(targetId, id) == d check logDist(targetId, id) == d

View File

@ -132,13 +132,12 @@ suite "Discovery v5 Cryptographic Primitives":
sharedSecret = "0x033b11a2a1f214567e1537ce5e509ffd9b21373247f2a3ff6841f4976f53165e7e" sharedSecret = "0x033b11a2a1f214567e1537ce5e509ffd9b21373247f2a3ff6841f4976f53165e7e"
let let
pub = initPublicKey(publicKey) pub = PublicKey.fromHex(publicKey)[]
priv = initPrivateKey(secretKey) priv = PrivateKey.fromHex(secretKey)[]
var eph: SharedSecretFull
let eph = ecdhRawFull(priv, pub)
check: check:
ecdhAgree(priv, pub, eph) == EthKeysStatus.Success eph[].data == hexToSeqByte(sharedSecret)
eph.data == hexToSeqByte(sharedSecret)
test "Key Derivation": test "Key Derivation":
# const # const
@ -167,10 +166,10 @@ suite "Discovery v5 Cryptographic Primitives":
idNonceSig = "0xc5036e702a79902ad8aa147dabfe3958b523fd6fa36cc78e2889b912d682d8d35fdea142e141f690736d86f50b39746ba2d2fc510b46f82ee08f08fd55d133a4" idNonceSig = "0xc5036e702a79902ad8aa147dabfe3958b523fd6fa36cc78e2889b912d682d8d35fdea142e141f690736d86f50b39746ba2d2fc510b46f82ee08f08fd55d133a4"
let let
c = Codec(privKey: initPrivateKey(localSecretKey)) c = Codec(privKey: PrivateKey.fromHex(localSecretKey)[])
signature = signIDNonce(c, hexToByteArray[idNonceSize](idNonce), signature = signIDNonce(c, hexToByteArray[idNonceSize](idNonce),
hexToByteArray[64](ephemeralKey)) hexToByteArray[64](ephemeralKey))
check signature.getRaw() == hexToByteArray[64](idNonceSig) check signature.toRaw() == hexToByteArray[64](idNonceSig)
test "Encryption/Decryption": test "Encryption/Decryption":
const const

View File

@ -69,8 +69,8 @@ suite "ECIES test suite":
var encr = newSeq[byte](eciesEncryptedLength(len(m))) var encr = newSeq[byte](eciesEncryptedLength(len(m)))
var decr = newSeq[byte](len(m)) var decr = newSeq[byte](len(m))
var shmac = [0x13'u8, 0x13'u8] var shmac = [0x13'u8, 0x13'u8]
var s = newPrivateKey() var s = PrivateKey.random()[]
var p = s.getPublicKey() var p = s.toPublicKey()[]
check: check:
# Without additional mac data # Without additional mac data
eciesEncrypt(plain, encr, p) == EciesStatus.Success eciesEncrypt(plain, encr, p) == EciesStatus.Success
@ -123,7 +123,7 @@ suite "ECIES test suite":
] ]
var data: array[1024, byte] var data: array[1024, byte]
for i in 0..1: for i in 0..1:
var s = initPrivateKey(secretKeys[i]) var s = PrivateKey.fromHex(secretKeys[i])[]
var cipher = fromHex(stripSpaces(cipherText[i])) var cipher = fromHex(stripSpaces(cipherText[i]))
var expect = fromHex(stripSpaces(expectText[i])) var expect = fromHex(stripSpaces(expectText[i]))
check: check:
@ -164,7 +164,7 @@ suite "ECIES test suite":
] ]
var data: array[1024, byte] var data: array[1024, byte]
for i in 0..3: for i in 0..3:
var s = initPrivateKey(secretKeys[i]) var s = PrivateKey.fromHex(secretKeys[i])[]
var cipher = fromHex(stripSpaces(cipherData[i])) var cipher = fromHex(stripSpaces(cipherData[i]))
check: check:
eciesDecrypt(cipher, data, s) == EciesStatus.Success eciesDecrypt(cipher, data, s) == EciesStatus.Success

View File

@ -97,5 +97,5 @@ suite "ENode":
check isCorrect(node) == false check isCorrect(node) == false
node.address.udpPort = Port(25) node.address.udpPort = Port(25)
check isCorrect(node) == false check isCorrect(node) == false
node.pubkey.data[0] = 1'u8 node.pubkey = PrivateKey.random()[].toPublicKey()[]
check isCorrect(node) == true check isCorrect(node) == true

View File

@ -5,7 +5,8 @@ import
suite "ENR": suite "ENR":
test "Serialization": test "Serialization":
var pk = initPrivateKey("5d2908f3f09ea1ff2e327c3f623159639b00af406e9009de5fd4b910fc34049d") var pk = PrivateKey.fromHex(
"5d2908f3f09ea1ff2e327c3f623159639b00af406e9009de5fd4b910fc34049d")[]
var r = initRecord(123, pk, {"udp": 1234'u, "ip": [byte 5, 6, 7, 8]}) var r = initRecord(123, pk, {"udp": 1234'u, "ip": [byte 5, 6, 7, 8]})
doAssert($r == """(id: "v4", ip: 0x05060708, secp256k1: 0x02E51EFA66628CE09F689BC2B82F165A75A9DDECBB6A804BE15AC3FDF41F3B34E7, udp: 1234)""") doAssert($r == """(id: "v4", ip: 0x05060708, secp256k1: 0x02E51EFA66628CE09F689BC2B82F165A75A9DDECBB6A804BE15AC3FDF41F3B34E7, udp: 1234)""")
let uri = r.toURI() let uri = r.toURI()
@ -32,14 +33,14 @@ suite "ENR":
test "Create from ENode address": test "Create from ENode address":
let let
keys = newKeyPair() keys = KeyPair.random()[]
ip = parseIpAddress("10.20.30.40") ip = parseIpAddress("10.20.30.40")
enr = Record.init(100, keys.seckey, some(ip), Port(9000), Port(9000)) enr = Record.init(100, keys.seckey, some(ip), Port(9000), Port(9000))
typedEnr = get enr.toTypedRecord() typedEnr = get enr.toTypedRecord()
check: check:
typedEnr.secp256k1.isSome() typedEnr.secp256k1.isSome()
typedEnr.secp256k1.get == keys.pubkey.getRawCompressed() typedEnr.secp256k1.get == keys.pubkey.toRawCompressed()
typedEnr.ip.isSome() typedEnr.ip.isSome()
typedEnr.ip.get() == [byte 10, 20, 30, 40] typedEnr.ip.get() == [byte 10, 20, 30, 40]
@ -52,13 +53,13 @@ suite "ENR":
test "ENR without address": test "ENR without address":
let let
keys = newKeyPair() keys = KeyPair.random()[]
enr = Record.init(100, keys.seckey, none(IpAddress), Port(9000), Port(9000)) enr = Record.init(100, keys.seckey, none(IpAddress), Port(9000), Port(9000))
typedEnr = get enr.toTypedRecord() typedEnr = get enr.toTypedRecord()
check: check:
typedEnr.secp256k1.isSome() typedEnr.secp256k1.isSome()
typedEnr.secp256k1.get() == keys.pubkey.getRawCompressed() typedEnr.secp256k1.get() == keys.pubkey.toRawCompressed()
typedEnr.ip.isNone() typedEnr.ip.isNone()
typedEnr.tcp.isSome() typedEnr.tcp.isSome()

View File

@ -36,7 +36,7 @@ suite "Whisper payload":
decoded.get().padding.get().len == 251 # 256 -1 -1 -3 decoded.get().padding.get().len == 251 # 256 -1 -1 -3
test "should roundtrip with signature": test "should roundtrip with signature":
let privKey = keys.newPrivateKey() let privKey = PrivateKey.random()[]
let payload = Payload(src: some(privKey), payload: @[byte 0, 1, 2]) let payload = Payload(src: some(privKey), payload: @[byte 0, 1, 2])
let encoded = whisper.encode(payload) let encoded = whisper.encode(payload)
@ -45,13 +45,13 @@ suite "Whisper payload":
check: check:
decoded.isSome() decoded.isSome()
payload.payload == decoded.get().payload payload.payload == decoded.get().payload
privKey.getPublicKey() == decoded.get().src.get() privKey.toPublicKey()[] == decoded.get().src.get()
decoded.get().padding.get().len == 186 # 256 -1 -1 -3 -65 decoded.get().padding.get().len == 186 # 256 -1 -1 -3 -65
test "should roundtrip with asymmetric encryption": test "should roundtrip with asymmetric encryption":
let privKey = keys.newPrivateKey() let privKey = PrivateKey.random()[]
let payload = Payload(dst: some(privKey.getPublicKey()), let payload = Payload(dst: some(privKey.toPublicKey()[]),
payload: @[byte 0, 1, 2]) payload: @[byte 0, 1, 2])
let encoded = whisper.encode(payload) let encoded = whisper.encode(payload)
@ -84,7 +84,7 @@ suite "Whisper payload padding":
decoded.get().padding.get().len == 256 # as dataLen == 256 decoded.get().padding.get().len == 256 # as dataLen == 256
test "should do max padding with signature": test "should do max padding with signature":
let privKey = keys.newPrivateKey() let privKey = PrivateKey.random()[]
let payload = Payload(src: some(privKey), payload: repeat(byte 1, 189)) let payload = Payload(src: some(privKey), payload: repeat(byte 1, 189))
let encoded = whisper.encode(payload) let encoded = whisper.encode(payload)
@ -93,7 +93,7 @@ suite "Whisper payload padding":
check: check:
decoded.isSome() decoded.isSome()
payload.payload == decoded.get().payload payload.payload == decoded.get().payload
privKey.getPublicKey() == decoded.get().src.get() privKey.toPublicKey()[] == decoded.get().src.get()
decoded.get().padding.isSome() decoded.get().padding.isSome()
decoded.get().padding.get().len == 256 # as dataLen == 256 decoded.get().padding.get().len == 256 # as dataLen == 256
@ -109,7 +109,7 @@ suite "Whisper payload padding":
decoded.get().padding.get().len == 1 # as dataLen == 255 decoded.get().padding.get().len == 1 # as dataLen == 255
test "should do min padding with signature": test "should do min padding with signature":
let privKey = keys.newPrivateKey() let privKey = PrivateKey.random()[]
let payload = Payload(src: some(privKey), payload: repeat(byte 1, 188)) let payload = Payload(src: some(privKey), payload: repeat(byte 1, 188))
let encoded = whisper.encode(payload) let encoded = whisper.encode(payload)
@ -118,7 +118,7 @@ suite "Whisper payload padding":
check: check:
decoded.isSome() decoded.isSome()
payload.payload == decoded.get().payload payload.payload == decoded.get().payload
privKey.getPublicKey() == decoded.get().src.get() privKey.toPublicKey()[] == decoded.get().src.get()
decoded.get().padding.isSome() decoded.get().padding.isSome()
decoded.get().padding.get().len == 1 # as dataLen == 255 decoded.get().padding.get().len == 1 # as dataLen == 255
@ -147,7 +147,7 @@ suite "Whisper payload padding":
decoded.get().padding.isNone() decoded.get().padding.isNone()
test "should roundtrip custom padding with signature": test "should roundtrip custom padding with signature":
let privKey = keys.newPrivateKey() let privKey = PrivateKey.random()[]
let payload = Payload(src: some(privKey), payload: repeat(byte 1, 10), let payload = Payload(src: some(privKey), payload: repeat(byte 1, 10),
padding: some(repeat(byte 2, 100))) padding: some(repeat(byte 2, 100)))
let encoded = whisper.encode(payload) let encoded = whisper.encode(payload)
@ -156,13 +156,13 @@ suite "Whisper payload padding":
check: check:
decoded.isSome() decoded.isSome()
payload.payload == decoded.get().payload payload.payload == decoded.get().payload
privKey.getPublicKey() == decoded.get().src.get() privKey.toPublicKey()[] == decoded.get().src.get()
decoded.get().padding.isSome() decoded.get().padding.isSome()
payload.padding.get() == decoded.get().padding.get() payload.padding.get() == decoded.get().padding.get()
test "should roundtrip custom 0 padding with signature": test "should roundtrip custom 0 padding with signature":
let padding: seq[byte] = @[] let padding: seq[byte] = @[]
let privKey = keys.newPrivateKey() let privKey = PrivateKey.random()[]
let payload = Payload(src: some(privKey), payload: repeat(byte 1, 10), let payload = Payload(src: some(privKey), payload: repeat(byte 1, 10),
padding: some(padding)) padding: some(padding))
let encoded = whisper.encode(payload) let encoded = whisper.encode(payload)
@ -171,7 +171,7 @@ suite "Whisper payload padding":
check: check:
decoded.isSome() decoded.isSome()
payload.payload == decoded.get().payload payload.payload == decoded.get().payload
privKey.getPublicKey() == decoded.get().src.get() privKey.toPublicKey()[] == decoded.get().src.get()
decoded.get().padding.isNone() decoded.get().padding.isNone()
# example from https://github.com/paritytech/parity-ethereum/blob/93e1040d07e385d1219d00af71c46c720b0a1acf/whisper/src/message.rs#L439 # example from https://github.com/paritytech/parity-ethereum/blob/93e1040d07e385d1219d00af71c46c720b0a1acf/whisper/src/message.rs#L439
@ -300,9 +300,9 @@ suite "Whisper filter":
messages[0].dst.isNone() messages[0].dst.isNone()
test "should notify filter on message with asymmetric encryption": test "should notify filter on message with asymmetric encryption":
let privKey = keys.newPrivateKey() let privKey = PrivateKey.random()[]
let topic = [byte 0, 0, 0, 0] let topic = [byte 0, 0, 0, 0]
let msg = prepFilterTestMsg(pubKey = some(privKey.getPublicKey()), let msg = prepFilterTestMsg(pubKey = some(privKey.toPublicKey()[]),
topic = topic) topic = topic)
var filters = initTable[string, Filter]() var filters = initTable[string, Filter]()
@ -318,12 +318,12 @@ suite "Whisper filter":
messages[0].dst.isSome() messages[0].dst.isSome()
test "should notify filter on message with signature": test "should notify filter on message with signature":
let privKey = keys.newPrivateKey() let privKey = PrivateKey.random()[]
let topic = [byte 0, 0, 0, 0] let topic = [byte 0, 0, 0, 0]
let msg = prepFilterTestMsg(src = some(privKey), topic = topic) let msg = prepFilterTestMsg(src = some(privKey), topic = topic)
var filters = initTable[string, Filter]() var filters = initTable[string, Filter]()
let filter = initFilter(src = some(privKey.getPublicKey()), let filter = initFilter(src = some(privKey.toPublicKey()[]),
topics = @[topic]) topics = @[topic])
let filterId = filters.subscribeFilter(filter) let filterId = filters.subscribeFilter(filter)

View File

@ -30,8 +30,8 @@ procSuite "Whisper connections":
node1.peerPool.connectedNodes.len() == 1 node1.peerPool.connectedNodes.len() == 1
asyncTest "Filters with encryption and signing": asyncTest "Filters with encryption and signing":
let encryptKeyPair = newKeyPair() let encryptKeyPair = KeyPair.random()[]
let signKeyPair = newKeyPair() let signKeyPair = KeyPair.random()[]
var symKey: SymKey var symKey: SymKey
let topic = [byte 0x12, 0, 0, 0] let topic = [byte 0x12, 0, 0, 0]
var filters: seq[string] = @[] var filters: seq[string] = @[]

View File

@ -97,7 +97,7 @@ template sendResponse(peer: Peer, proto, msg: untyped, data: varargs[untyped]):
asyncTest "network with 3 peers using custom protocols": asyncTest "network with 3 peers using custom protocols":
const useCompression = defined(useSnappy) const useCompression = defined(useSnappy)
let localKeys = newKeyPair() let localKeys = KeyPair.random()[]
let localAddress = localAddress(30303) let localAddress = localAddress(30303)
var localNode = newEthereumNode(localKeys, localAddress, 1, nil, useCompression = useCompression) var localNode = newEthereumNode(localKeys, localAddress, 1, nil, useCompression = useCompression)
localNode.startListening() localNode.startListening()