mirror of https://github.com/status-im/nim-eth.git
keys: get rid of deprecated calls (#213)
This commit is contained in:
parent
42b36d1aef
commit
ac5bbe4d3d
|
@ -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
|
||||||
|
|
305
eth/keys.nim
305
eth/keys.nim
|
@ -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
|
|
||||||
|
|
114
eth/p2p/auth.nim
114
eth/p2p/auth.nim
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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?
|
||||||
|
|
|
@ -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()):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)[]
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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":
|
||||||
|
|
|
@ -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]
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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] = @[]
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue