diff --git a/eth/keyfile/keyfile.nim b/eth/keyfile/keyfile.nim index 263743b..02ad720 100644 --- a/eth/keyfile/keyfile.nim +++ b/eth/keyfile/keyfile.nim @@ -177,7 +177,7 @@ proc encryptKey(seckey: PrivateKey, if cryptkind == AES128CTR: var ctx: CTR[aes128] ctx.init(toOpenArray(key, 0, 15), iv) - ctx.encrypt(seckey.data, crypttext) + ctx.encrypt(seckey.toRaw(), crypttext) ctx.clear() result = Success else: @@ -308,7 +308,7 @@ proc createKeyFileJson*(seckey: PrivateKey, outjson = %* { - "address": seckey.getPublicKey().toAddress(false), + "address": seckey.toPublicKey().tryGet().toAddress(false), "crypto": { "cipher": $cryptkind, "cipherparams": { @@ -394,7 +394,7 @@ proc decodeKeyFileJson*(j: JsonNode, if res != Success: return res try: - seckey = initPrivateKey(plaintext) + seckey = PrivateKey.fromRaw(plaintext).tryGet() except CatchableError: return IncorrectPrivateKey result = Success diff --git a/eth/keys.nim b/eth/keys.nim index 2eb9a49..a57334f 100644 --- a/eth/keys.nim +++ b/eth/keys.nim @@ -29,6 +29,8 @@ const ## Size of uncompressed public key without format marker (0x04) RawSignatureSize* = SkRawRecoverableSignatureSize + RawSignatureNRSize* = SkRawSignatureSize + type PrivateKey* = distinct SkSecretKey @@ -61,6 +63,8 @@ proc toRaw*(seckey: PrivateKey): array[SkRawSecretKeySize, byte] {.borrow.} proc toPublicKey*(seckey: PrivateKey): SkResult[PublicKey] = SkSecretKey(seckey).toPublicKey().mapConvert(PublicKey) +proc verify*(seckey: PrivateKey): bool {.borrow.} + proc fromRaw*(T: type PublicKey, data: openArray[byte]): SkResult[T] = if data.len() == SkRawCompressedPubKeySize: 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 random*(t: type KeyPair): SkResult[KeyPair] = +proc random*(T: type KeyPair): SkResult[T] = 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) 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 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 = ## Convert public key to hexadecimal string address. 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 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 -# reimplemented using functions that return Result instead! +proc sign*(seckey: PrivateKey, msg: openArray[byte]): SkResult[Signature] = + 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 - EthKeysException* {.deprecated.} = object of CatchableError - Secp256k1Exception* {.deprecated.} = object of CatchableError +proc recover*(sig: Signature, msg: SkMessage): SkResult[PublicKey] = + recover(SkRecoverableSignature(sig), msg).mapConvert(PublicKey) - EthKeysStatus* {.deprecated.} = enum - Success - Error +proc recover*(sig: Signature, msg: openArray[byte]): SkResult[PublicKey] = + let hash = keccak256.digest(msg) + recover(sig, hash) -template data*(pubkey: PublicKey): auto = - SkPublicKey(pubkey).data +proc verify*(sig: SignatureNR, msg: SkMessage, key: PublicKey): bool = + verify(SkSignature(sig), msg, SkPublicKey(key)) -template data*(seckey: PrivateKey): auto = - SkSecretKey(seckey).data +proc verify*(sig: SignatureNR, msg: openArray[byte], key: PublicKey): bool = + let hash = keccak256.digest(msg) + verify(sig, hash, key) -template data*(sig: Signature): auto = - SkRecoverableSignature(sig).data - -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( +proc ecdhRaw*(seckey: PrivateKey, pubkey: PublicKey): SkResult[SharedSecret] = + ecdhRaw( 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(): - s = v[] - 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 +proc ecdhRawFull*(seckey: PrivateKey, pubkey: PublicKey): SkResult[SharedSecretFull] = + ecdhRaw(SkSecretKey(seckey), SkPublicKey(pubkey)).mapconvert(SharedSecretFull) diff --git a/eth/p2p/auth.nim b/eth/p2p/auth.nim index df73e0f..518018e 100644 --- a/eth/p2p/auth.nim +++ b/eth/p2p/auth.nim @@ -32,14 +32,14 @@ const type Nonce* = array[KeyLength, byte] - AuthMessageV4* = object {.packed.} + AuthMessageV4* {.packed.} = object signature: array[RawSignatureSize, byte] keyhash: array[keccak256.sizeDigest, byte] - pubkey: PublicKey + pubkey: array[RawPublicKeySize, byte] nonce: array[keccak256.sizeDigest, byte] flag: byte - AckMessageV4* = object {.packed.} + AckMessageV4* {.packed.} = object pubkey: array[RawPublicKeySize, byte] nonce: array[keccak256.sizeDigest, byte] flag: byte @@ -94,7 +94,7 @@ proc newHandshake*(flags: set[HandshakeFlag] = {Initiator}, ## Create new `Handshake` object. result.version = byte(version and 0xFF) result.flags = flags - result.ephemeral = newKeyPair() + result.ephemeral = KeyPair.random().tryGet() if Initiator in flags: result.expectedLength = AckMessageV4Length if randomBytes(result.initiatorNonce) != len(result.initiatorNonce): @@ -112,25 +112,25 @@ proc authMessagePreEIP8(h: var Handshake, encrypt: bool = true): AuthStatus = ## Create plain pre-EIP8 authentication message. var - secret: SharedSecret - signature: Signature buffer: array[PlainAuthMessageV4Length, byte] flagb: byte header: ptr AuthMessageV4 outlen = 0 flagb = byte(flag) 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) var xornonce = h.initiatorNonce - xornonce.sxor(secret.data) - if signRawMessage(xornonce, h.ephemeral.seckey, - signature) != EthKeysStatus.Success: + xornonce.sxor(secret[].data) + secret[].clear() + let sig = sign(h.ephemeral.seckey, SkMessage(data: xornonce)) + if sig.isErr: return(SignatureError) h.remoteHPubkey = pubkey - header.signature = signature.getRaw() - header.keyhash = keccak256.digest(h.ephemeral.pubkey.getRaw()).data - header.pubkey = cast[PublicKey](h.host.pubkey.getRaw()) + header.signature = sig[].toRaw() + header.keyhash = keccak256.digest(h.ephemeral.pubkey.toRaw()).data + header.pubkey = h.host.pubkey.toRaw() header.nonce = h.initiatorNonce header.flag = flagb if encrypt: @@ -155,23 +155,23 @@ proc authMessageEIP8(h: var Handshake, encrypt: bool = true): AuthStatus = ## Create EIP8 authentication message. var - secret: SharedSecret - signature: Signature buffer: array[PlainAuthMessageMaxEIP8, byte] padsize: byte doAssert(EIP8 in h.flags) outlen = 0 - if ecdhAgree(h.host.seckey, pubkey, secret) != EthKeysStatus.Success: + var secret = ecdhRaw(h.host.seckey, pubkey) + if secret.isErr: return(EcdhError) var xornonce = h.initiatorNonce - xornonce.sxor(secret.data) - if signRawMessage(xornonce, h.ephemeral.seckey, - signature) != EthKeysStatus.Success: + xornonce.sxor(secret[].data) + secret[].clear() + var sig = sign(h.ephemeral.seckey, SkMessage(data: xornonce)) + if sig.isErr: return(SignatureError) h.remoteHPubkey = pubkey - var payload = rlp.encodeList(signature.getRaw(), - h.host.pubkey.getRaw(), + var payload = rlp.encodeList(sig[].toRaw(), + h.host.pubkey.toRaw(), h.initiatorNonce, [byte(h.version)]) doAssert(len(payload) == PlainAuthMessageEIP8Length) @@ -216,7 +216,7 @@ proc ackMessagePreEIP8(h: var Handshake, var buffer: array[PlainAckMessageV4Length, byte] outlen = 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.flag = byte(flag) if encrypt: @@ -242,7 +242,7 @@ proc ackMessageEIP8(h: var Handshake, buffer: array[PlainAckMessageMaxEIP8, byte] padsize: byte doAssert(EIP8 in h.flags) - var payload = rlp.encodeList(h.ephemeral.pubkey.getRaw(), + var payload = rlp.encodeList(h.ephemeral.pubkey.toRaw(), h.responderNonce, [byte(h.version)]) 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 = ## Decodes V4 AuthMessage. var - secret: SharedSecret buffer: array[PlainAuthMessageV4Length, byte] - pubkey: PublicKey + doAssert(Responder in h.flags) if eciesDecrypt(m, buffer, h.host.seckey) != EciesStatus.Success: return(EciesError) 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) - if ecdhAgree(h.host.seckey, pubkey, secret) != EthKeysStatus.Success: + var secret = ecdhRaw(h.host.seckey, pubkey[]) + if secret.isErr: return(EcdhError) var xornonce = header.nonce - xornonce.sxor(secret.data) - if recoverSignatureKey(header.signature, xornonce, - h.remoteEPubkey) != EthKeysStatus.Success: + xornonce.sxor(secret[].data) + secret[].clear() + let sig = Signature.fromRaw(header.signature) + if sig.isErr: return(SignatureError) + let remoteEPubkey = recover(sig[], SkMessage(data: xornonce)) + if remoteEPubkey.isErr: + return(SignatureError) + h.remoteEPubkey = remoteEPubkey[] h.initiatorNonce = header.nonce - h.remoteHPubkey = pubkey + h.remoteHPubkey = pubkey[] result = Success proc decodeAuthMessageEip8(h: var Handshake, m: openarray[byte]): AuthStatus = ## Decodes EIP-8 AuthMessage. var - pubkey: PublicKey nonce: Nonce - secret: SharedSecret let size = uint16.fromBytesBE(m) 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 nonceBr = reader.listElem(2).toBytes() var versionBr = reader.listElem(3).toBytes() - if recoverPublicKey(pubkeyBr.toOpenArray(), - pubkey) != EthKeysStatus.Success: + let pubkey = PublicKey.fromRaw(pubkeyBr.toOpenArray()) + if pubkey.isErr: return(InvalidPubKey) 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) var xornonce = nonce - xornonce.sxor(secret.data) - if recoverSignatureKey(signatureBr.toOpenArray(), - xornonce, - h.remoteEPubkey) != EthKeysStatus.Success: + xornonce.sxor(secret[].data) + secret[].clear() + let sig = Signature.fromRaw(signatureBr.toOpenArray()) + if sig.isErr: return(SignatureError) + let remoteEPubkey = recover(sig[], SkMessage(data: xornonce)) + if remoteEPubkey.isErr: + return(SignatureError) + h.remoteEPubkey = remoteEPubkey[] h.initiatorNonce = nonce - h.remoteHPubkey = pubkey + h.remoteHPubkey = pubkey[] h.version = cast[ptr byte](versionBr.baseAddr)[] result = Success except CatchableError: @@ -411,9 +420,10 @@ proc decodeAckMessageEip8*(h: var Handshake, m: openarray[byte]): AuthStatus = let pubkeyBr = reader.listElem(0).toBytes() let nonceBr = reader.listElem(1).toBytes() let versionBr = reader.listElem(2).toBytes() - if recoverPublicKey(pubkeyBr.toOpenArray(), - h.remoteEPubkey) != EthKeysStatus.Success: + let remoteEPubkey = PublicKey.fromRaw(pubkeyBr.toOpenArray()) + if remoteEPubkey.isErr: return(InvalidPubKey) + h.remoteEPubkey = remoteEPubkey[] copyMem(addr h.responderNonce[0], nonceBr.baseAddr, KeyLength) h.version = cast[ptr byte](versionBr.baseAddr)[] result = Success @@ -428,8 +438,10 @@ proc decodeAckMessageV4(h: var Handshake, m: openarray[byte]): AuthStatus = if eciesDecrypt(m, buffer, h.host.seckey) != EciesStatus.Success: return(EciesError) 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) + h.remoteEPubkey = remoteEPubkey[] h.responderNonce = header.nonce result = Success @@ -479,15 +491,14 @@ proc getSecrets*(h: Handshake, authmsg: openarray[byte], ## Derive secrets from handshake `h` using encrypted AuthMessage `authmsg` and ## encrypted AckMessage `ackmsg`. var - shsec: SharedSecret ctx0: keccak256 ctx1: keccak256 mac1: MDigest[256] xornonce: Nonce # ecdhe-secret = ecdh.agree(ephemeral-privkey, remote-ephemeral-pubk) - if ecdhAgree(h.ephemeral.seckey, h.remoteEPubkey, - shsec) != EthKeysStatus.Success: + var shsec = ecdhRaw(h.ephemeral.seckey, h.remoteEPubkey) + if shsec.isErr: return(EcdhError) # shared-secret = keccak(ecdhe-secret || keccak(nonce || initiator-nonce)) @@ -497,25 +508,26 @@ proc getSecrets*(h: Handshake, authmsg: openarray[byte], ctx1.update(h.initiatorNonce) mac1 = ctx1.finish() ctx1.clear() - ctx0.update(shsec.data) + ctx0.update(shsec[].data) ctx0.update(mac1.data) mac1 = ctx0.finish() # aes-secret = keccak(ecdhe-secret || shared-secret) ctx0.init() - ctx0.update(shsec.data) + ctx0.update(shsec[].data) ctx0.update(mac1.data) mac1 = ctx0.finish() # mac-secret = keccak(ecdhe-secret || aes-secret) ctx0.init() - ctx0.update(shsec.data) + ctx0.update(shsec[].data) ctx0.update(mac1.data) secret.aesKey = mac1.data mac1 = ctx0.finish() secret.macKey = mac1.data - burnMem(shsec) + shsec[].clear() + # egress-mac = keccak256(mac-secret ^ recipient-nonce || auth-sent-init) xornonce = mac1.data xornonce.sxor(h.responderNonce) diff --git a/eth/p2p/discovery.nim b/eth/p2p/discovery.nim index f0d2877..08de202 100644 --- a/eth/p2p/discovery.nim +++ b/eth/p2p/discovery.nim @@ -56,7 +56,7 @@ proc append*(w: var RlpWriter, a: IpAddress) = w.append(a.address_v4.toMemRange) 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 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 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) 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)) proc recoverMsgPublicKey(msg: Bytes, pk: var PublicKey): bool = - msg.len > HEAD_SIZE and - recoverSignatureKey(msg.toOpenArray(MAC_SIZE, HEAD_SIZE), - keccak256.digest(msg.toOpenArray(HEAD_SIZE, msg.high)).data, - pk) == EthKeysStatus.Success + if msg.len > HEAD_SIZE: + let sig = Signature.fromRaw(msg.toOpenArray(MAC_SIZE, HEAD_SIZE)) + if sig.isOk(): + 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] = # Check against possible RangeError @@ -154,7 +157,7 @@ proc newDiscoveryProtocol*(privKey: PrivateKey, address: Address, result.address = address result.bootstrapNodes = newSeqOfCap[Node](bootstrapNodes.len) 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) 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 tcpPort = n.listElem(2).toInt(uint16).Port - var pk: PublicKey - if recoverPublicKey(n.listElem(3).toBytes.toOpenArray(), pk) != EthKeysStatus.Success: + let pk = PublicKey.fromRaw(n.listElem(3).toBytes.toOpenArray()) + if pk.isErr: warn "Could not parse public key" 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) proc recvFindNode(d: DiscoveryProtocol, node: Node, payload: Bytes) {.inline, gcsafe.} = @@ -314,9 +317,10 @@ when isMainModule: let (cmdId, payload) = unpack(m) doAssert(payload == hexToSeqByte"f2cb842edbd4d182944382765da0ab56fb9e64a85a597e6bb27c656b4f1afb7e06b0fd4e41ccde6dba69a3c4a150845aaa4de2") doAssert(cmdId == cmdPong) - doAssert(remotePubkey == initPublicKey("78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d")) + doAssert(remotePubkey == PublicKey.fromHex( + "78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d"))[] - let privKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617") + let privKey = PrivateKey.fromHex("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[] # echo privKey diff --git a/eth/p2p/discoveryv5/encoding.nim b/eth/p2p/discoveryv5/encoding.nim index 04444a1..d8d5be6 100644 --- a/eth/p2p/discoveryv5/encoding.nim +++ b/eth/p2p/discoveryv5/encoding.nim @@ -46,27 +46,33 @@ type PacketError, DecryptError -proc randomBytes*(v: var openarray[byte]) = - if nimcrypto.randomBytes(v) != v.len: +proc randomBytes2*(v: var openarray[byte]) = + # 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") -proc idNonceHash(nonce, ephkey: openarray[byte]): array[32, byte] = +proc idNonceHash(nonce, ephkey: openarray[byte]): MDigest[256] = var ctx: sha256 ctx.init() ctx.update(idNoncePrefix) ctx.update(nonce) ctx.update(ephkey) - ctx.finish().data + ctx.finish() proc signIDNonce*(c: Codec, idNonce, ephKey: openarray[byte]): SignatureNR = - if signRawMessage(idNonceHash(idNonce, ephKey), c.privKey, result) != EthKeysStatus.Success: - raise newException(EthKeysException, "Could not sign idNonce") + let sig = signNR(c.privKey, idNonceHash(idNonce, ephKey)) + if sig.isErr: + raise newException(CatchableError, "Could not sign idNonce") + sig[] proc deriveKeys(n1, n2: NodeID, priv: PrivateKey, pub: PublicKey, idNonce: openarray[byte], result: var HandshakeSecrets) = - var eph: SharedSecretFull - if ecdhAgree(priv, pub, eph) != EthKeysStatus.Success: - raise newException(EthKeysException, "ecdhAgree failed") + let eph = ecdhRawFull(priv, pub) + if eph.isErr: + raise newException(CatchableError, "ecdhRawFull failed") # TODO: Unneeded allocation here 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) 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] = var ectx: GCM[aes128] @@ -97,10 +103,10 @@ proc makeAuthHeader(c: Codec, toId: NodeID, nonce: array[gcmNonceSize, byte], if challenge.recordSeq < ln.record.seqNum: resp.record = ln.record - let ephKey = newPrivateKey() - let ephPubkey = ephKey.getPublicKey().getRaw + let ephKey = PrivateKey.random().tryGet() + 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, handshakeSecrets) @@ -131,7 +137,7 @@ proc encodeEncrypted*(c: Codec, challenge: Whoareyou): (seq[byte], array[gcmNonceSize, byte]) = var nonce: array[gcmNonceSize, byte] - randomBytes(nonce) + randomBytes2(nonce) var headEnc: seq[byte] var writeKey: AesKey @@ -223,11 +229,11 @@ proc decodeAuthResp(c: Codec, fromId: NodeId, head: AuthHeader, warn "Unknown auth scheme" return false - var ephKey: PublicKey - if recoverPublicKey(head.ephemeralKey, ephKey) != EthKeysStatus.Success: + var ephKey = PublicKey.fromRaw(head.ephemeralKey) + if ephKey.isErr: return false - deriveKeys(fromId, c.localNode.id, c.privKey, ephKey, challenge.idNonce, + deriveKeys(fromId, c.localNode.id, c.privKey, ephKey[], challenge.idNonce, secrets) var zeroNonce: array[gcmNonceSize, byte] diff --git a/eth/p2p/discoveryv5/enr.nim b/eth/p2p/discoveryv5/enr.nim index 2c0f3a6..7242e44 100644 --- a/eth/p2p/discoveryv5/enr.nim +++ b/eth/p2p/discoveryv5/enr.nim @@ -59,10 +59,10 @@ proc makeEnrAux(seqNum: uint64, pk: PrivateKey, pairs: openarray[(string, Field) result.pairs = @pairs result.seqNum = seqNum - let pubkey = pk.getPublicKey() + let pubkey = pk.toPublicKey().tryGet() 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 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) w.append(seqNum, result.pairs) - var sig: SignatureNR - if signRawMessage(keccak256.digest(toSign).data, pk, sig) != EthKeysStatus.Success: - raise newException(EthKeysException, "Could not sign ENR (internal error)") + let sig = signNR(pk, toSign) + if sig.isErr: + raise newException(CatchableError, "Could not sign ENR (internal error)") result.raw = block: var w = initRlpList(result.pairs.len * 2 + 2) - w.append(sig.getRaw()) + w.append(sig[].toRaw()) w.append(seqNum, result.pairs) 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 elif T is PublicKey: 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") + return pk[] elif T is array: when type(result[0]) is byte: requireKind(f, kBytes) @@ -164,7 +166,10 @@ proc get*(r: Record, key: string, T: type): T = proc get*(r: Record, pubKey: var PublicKey): bool = var pubkeyField: Field 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] = try: @@ -194,11 +199,10 @@ proc toTypedRecord*(r: Record): Option[TypedRecord] = proc verifySignatureV4(r: Record, sigData: openarray[byte], content: seq[byte]): bool = var publicKey: PublicKey if r.get(publicKey): - var sig: SignatureNR - if sig.parseCompact(sigData) == EthKeysStatus.Success: + let sig = SignatureNR.fromRaw(sigData) + if sig.isOk: var h = keccak256.digest(content) - if verifySignatureRaw(sig, h.data, publicKey) == EthKeysStatus.Success: - return true + return verify(sig[], h, publicKey) proc verifySignature(r: Record): bool = var rlp = rlpFromBytes(r.raw.toRange) diff --git a/eth/p2p/discoveryv5/node.nim b/eth/p2p/discoveryv5/node.nim index 63a9506..6495049 100644 --- a/eth/p2p/discoveryv5/node.nim +++ b/eth/p2p/discoveryv5/node.nim @@ -9,7 +9,7 @@ type record*: Record proc toNodeId*(pk: PublicKey): NodeId = - readUintBE[256](keccak256.digest(pk.getRaw()).data) + readUintBE[256](keccak256.digest(pk.toRaw()).data) proc newNode*(enode: ENode): Node = Node(node: enode, @@ -43,15 +43,15 @@ proc newNode*(r: Record): Node = # Will need some refactor though. discard - var pk: PublicKey - if recoverPublicKey(r.get("secp256k1", seq[byte]), pk) != EthKeysStatus.Success: - warn "Could not recover public key" + let pk = PublicKey.fromRaw(r.get("secp256k1", seq[byte])) + if pk.isErr: + warn "Could not recover public key", err = pk.error return - result = newNode(initENode(pk, a)) + result = newNode(initENode(pk[], a)) 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 address*(n: Node): Address {.inline.} = n.node.address diff --git a/eth/p2p/discoveryv5/protocol.nim b/eth/p2p/discoveryv5/protocol.nim index baee0b4..fa56753 100644 --- a/eth/p2p/discoveryv5/protocol.nim +++ b/eth/p2p/discoveryv5/protocol.nim @@ -108,7 +108,7 @@ proc decodeWhoAreYou(d: Protocol, msg: Bytes): Whoareyou = proc sendWhoareyou(d: Protocol, address: Address, toNode: NodeId, authTag: AuthTag) = trace "sending who are you", to = $toNode, toAddress = $address 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 # new one. Handshake will get cleaned up after `handshakeTimeout`. # 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, IOError, TransportAddressError, - EthKeysException, - Secp256k1Exception, ].} = if msg.len < tagSize: # or magicSize, can be either return # Invalid msg @@ -482,7 +480,7 @@ proc newProtocol*(privKey: PrivateKey, db: Database, let a = Address(ip: externalIp.get(IPv4_any()), tcpPort: tcpPort, udpPort: udpPort) - enode = initENode(privKey.getPublicKey(), a) + enode = initENode(privKey.toPublicKey().tryGet(), a) enrRec = enr.Record.init(1, privKey, externalIp, tcpPort, udpPort) node = newNode(enode, enrRec) diff --git a/eth/p2p/ecies.nim b/eth/p2p/ecies.nim index 0f276d1..3186e2b 100644 --- a/eth/p2p/ecies.nim +++ b/eth/p2p/ecies.nim @@ -99,7 +99,6 @@ proc eciesEncrypt*(input: openarray[byte], output: var openarray[byte], cipher: CTR[aes128] ctx: HMAC[sha256] iv: array[aes128.sizeBlock, byte] - secret: SharedSecret material: array[KeyLength, byte] if len(output) < eciesEncryptedLength(len(input)): @@ -107,12 +106,15 @@ proc eciesEncrypt*(input: openarray[byte], output: var openarray[byte], if randomBytes(iv) != aes128.sizeBlock: 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) - material = kdf(secret.data) + material = kdf(secret[].data) burnMem(secret) 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]) header.version = 0x04 - header.pubkey = ephemeral.pubkey.getRaw() + header.pubkey = ephemeral[].pubkey.toRaw() header.iv = iv var so = eciesDataPos() @@ -158,11 +160,9 @@ proc eciesDecrypt*(input: openarray[byte], ## Length of output data can be calculated using ``eciesDecryptedLength()`` ## template. var - pubkey: PublicKey encKey: array[aes128.sizeKey, byte] cipher: CTR[aes128] ctx: HMAC[sha256] - secret: SharedSecret if len(input) <= 0: return(IncompleteError) @@ -174,12 +174,14 @@ proc eciesDecrypt*(input: openarray[byte], return(IncompleteError) if len(input) - eciesOverheadLength() > len(output): return(BufferOverrun) - if recoverPublicKey(header.pubkey, pubkey) != EthKeysStatus.Success: + let pubkey = PublicKey.fromRaw(header.pubkey) + if pubkey.isErr: return(IncorrectKey) - if ecdhAgree(seckey, pubkey, secret) != EthKeysStatus.Success: + var secret = ecdhRaw(seckey, pubkey[]) + if secret.isErr: return(EcdhError) - var material = kdf(secret.data) + var material = kdf(secret[].data) burnMem(secret) copyMem(addr encKey[0], addr material[0], aes128.sizeKey) var macKey = sha256.digest(material, ostart = KeyLength div 2) diff --git a/eth/p2p/enode.nim b/eth/p2p/enode.nim index beec9a9..10a0646 100644 --- a/eth/p2p/enode.nim +++ b/eth/p2p/enode.nim @@ -60,7 +60,6 @@ proc initENode*(e: string, node: var ENode): ENodeStatus = uport: int = 0 tport: int = 0 uri: Uri = initUri() - data: string if len(e) == 0: return IncorrectUri @@ -104,13 +103,10 @@ proc initENode*(e: string, node: var ENode): ENodeStatus = else: uport = tport - try: - data = parseHexStr(uri.username) - if recoverPublicKey(cast[seq[byte]](data), - node.pubkey) != EthKeysStatus.Success: - return IncorrectNodeId - except CatchableError: + let pk = PublicKey.fromHex(uri.username) + if pk.isErr: return IncorrectNodeId + node.pubkey = pk[] try: node.address.ip = parseIpAddress(uri.hostname) @@ -135,11 +131,8 @@ proc initENode*(pubkey: PublicKey, address: Address): ENode {.inline.} = proc isCorrect*(n: ENode): bool = ## Returns ``true`` if ENode ``n`` is properly filled. - result = false - for i in n.pubkey.data: - if i != 0x00'u8: - result = true - break + var pk: PublicKey + n.pubkey != pk proc `$`*(n: ENode): string = ## Returns string representation of ENode. diff --git a/eth/p2p/kademlia.nim b/eth/p2p/kademlia.nim index 04bfbac..2e29b2d 100644 --- a/eth/p2p/kademlia.nim +++ b/eth/p2p/kademlia.nim @@ -51,7 +51,7 @@ const ID_SIZE = 256 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 = result.new() @@ -76,7 +76,7 @@ proc `$`*(n: Node): string = else: "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 newKBucket(istart, iend: NodeId): KBucket = @@ -259,7 +259,7 @@ template onTimeout(b: untyped) = b 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] = 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]) = trace "<<< pong from ", n - let pingid = token & @(n.node.pubkey.data) + let pingid = token & @(n.node.pubkey.toRaw) var future: Future[bool] if k.pongFutures.take(pingid, future): future.complete(true) diff --git a/eth/p2p/mock_peers.nim b/eth/p2p/mock_peers.nim index 267ca34..86b5901 100644 --- a/eth/p2p/mock_peers.nim +++ b/eth/p2p/mock_peers.nim @@ -162,7 +162,7 @@ template compression(m: MockConf): bool = proc newMockPeer*(userConfigurator: proc (m: MockConf)): EthereumNode = var mockConf = new MockConf - mockConf.keys = newKeyPair() + mockConf.keys = KeyPair.random()[] mockConf.address = localhostAddress(nextUnusedMockPort) inc nextUnusedMockPort mockConf.networkId = 1'u diff --git a/eth/p2p/rlpx.nim b/eth/p2p/rlpx.nim index ec8d405..f56924c 100644 --- a/eth/p2p/rlpx.nim +++ b/eth/p2p/rlpx.nim @@ -857,8 +857,8 @@ proc disconnect*(peer: Peer, reason: DisconnectionReason, notifyOtherPeer = fals removePeer(peer.network, peer) proc validatePubKeyInHello(msg: DevP2P.hello, pubKey: PublicKey): bool = - var pk: PublicKey - recoverPublicKey(msg.nodeId, pk) == EthKeysStatus.Success and pk == pubKey + let pk = PublicKey.fromRaw(msg.nodeId) + pk.isOk and pk[] == pubKey proc checkUselessPeer(peer: Peer) {.inline.} = if peer.dispatcher.numProtocols == 0: @@ -1012,7 +1012,7 @@ proc rlpxConnect*(node: EthereumNode, remote: Node): Future[Peer] {.async.} = node.clientId, node.capabilities, uint(node.address.tcpPort), - node.keys.pubkey.getRaw()) + node.keys.pubkey.toRaw()) var response = await result.handshakeImpl( sendHelloFut, @@ -1102,7 +1102,7 @@ proc rlpxAccept*(node: EthereumNode, node.clientId, node.capabilities, listenPort.uint, - node.keys.pubkey.getRaw()) + node.keys.pubkey.toRaw()) var response = await result.handshakeImpl( sendHelloFut, diff --git a/eth/p2p/rlpx_protocols/les_protocol.nim b/eth/p2p/rlpx_protocols/les_protocol.nim index c9474ec..7ae4687 100644 --- a/eth/p2p/rlpx_protocols/les_protocol.nim +++ b/eth/p2p/rlpx_protocols/les_protocol.nim @@ -266,11 +266,9 @@ p2pProtocol les(version = lesVersion, if signature.isNone: error "missing announce signature" return - let sigHash = keccak256.digest rlp.encodeList(headHash, - headNumber, - headTotalDifficulty) - let signerKey = recoverKeyFromSignature(signature.get.initSignature, - sigHash) + let sigMsg = rlp.encodeList(headHash, headNumber, headTotalDifficulty) + let sig = Signature.fromRaw(signature.get).tryGet() + let signerKey = recover(sig, sigMsg).tryGet() if signerKey.toNodeId != peer.remote.id: error "invalid announce signature" # TODO: should we disconnect this peer? diff --git a/eth/p2p/rlpx_protocols/whisper/whisper_types.nim b/eth/p2p/rlpx_protocols/whisper/whisper_types.nim index 3b953de..b07353d 100644 --- a/eth/p2p/rlpx_protocols/whisper/whisper_types.nim +++ b/eth/p2p/rlpx_protocols/whisper/whisper_types.nim @@ -297,14 +297,12 @@ proc encode*(self: Payload): Option[Bytes] = plain.add padding if self.src.isSome(): # Private key present - signature requested - let hash = keccak256.digest(plain) - var sig: Signature - let err = signRawMessage(hash.data, self.src.get(), sig) - if err != EthKeysStatus.Success: - notice "Signing message failed", err + let sig = sign(self.src.get(), plain) + if sig.isErr: + notice "Signing message failed", err = sig.error return - plain.add sig.getRaw() + plain.add sig[].toRaw() if self.dst.isSome(): # Asymmetric key present - encryption requested 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 return - let sig = plain[^keys.RawSignatureSize .. ^1] - let hash = keccak256.digest(plain[0 ..< ^keys.RawSignatureSize]) - var key: PublicKey - let err = recoverSignatureKey(sig, hash.data, key) - if err != EthKeysStatus.Success: - debug "Failed to recover signature key", err + let sig = Signature.fromRaw(plain[^keys.RawSignatureSize .. ^1]) + let key = sig and recover( + sig[], plain.toOpenArray(0, plain.len - keys.RawSignatureSize - 1)) + if key.isErr: + debug "Failed to recover signature key", err = key.error return - res.src = some(key) + res.src = some(key[]) if hasSignature: if plain.len > pos + keys.RawSignatureSize: @@ -633,16 +630,16 @@ proc notify*(filters: var Filters, msg: Message) {.gcsafe.} = if decoded.isNone(): continue 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? - dst = some(getPublicKey(filter.privateKey.get())) + dst = some(toPublicKey(filter.privateKey.get()).tryGet()) elif filter.symKey.isSome(): keyHash = keccak256.digest(filter.symKey.get()) # else: # NOTE: In this case the message was not encrypted else: if filter.privateKey.isSome(): - if keyHash != keccak256.digest(filter.privateKey.get().data): + if keyHash != keccak256.digest(filter.privateKey.get().toRaw()): continue elif filter.symKey.isSome(): if keyHash != keccak256.digest(filter.symKey.get()): diff --git a/tests/fuzzing/discovery/fuzz.nim b/tests/fuzzing/discovery/fuzz.nim index c7237cb..f219dff 100644 --- a/tests/fuzzing/discovery/fuzz.nim +++ b/tests/fuzzing/discovery/fuzz.nim @@ -8,7 +8,7 @@ var targetNode: DiscoveryProtocol init: # Set up a discovery node, this is the node we target when fuzzing var - targetNodeKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617") + targetNodeKey = PrivateKey.fromRaw("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[] targetNodeAddr = localAddress(DefaultListeningPort) targetNode = newDiscoveryProtocol(targetNodeKey, targetNodeAddr, @[]) # 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 # a signature, and without it there is a big chance it will always result in # "Wrong msg mac from" error. - let nodeKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618") + let nodeKey = PrivateKey.fromRaw("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[] msg = packData(payload, nodeKey) address = localAddress(DefaultListeningPort + 1) diff --git a/tests/fuzzing/discovery/generate.nim b/tests/fuzzing/discovery/generate.nim index 0dcb57c..ea109e0 100644 --- a/tests/fuzzing/discovery/generate.nim +++ b/tests/fuzzing/discovery/generate.nim @@ -20,7 +20,7 @@ proc generate() = let fromAddr = localAddress(30303) toAddr = localAddress(30304) - peerKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617") + peerKey = PrivateKey.fromHex("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[] # valid data for a Ping packet block: @@ -42,7 +42,7 @@ proc generate() = # valid data for a FindNode packet block: 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 encodedData = @[3.byte] & payload.toSeq() debug "FindNode", data=byteutils.toHex(encodedData) @@ -54,14 +54,16 @@ proc generate() = let n1Addr = localAddress(30305) n2Addr = localAddress(30306) - n1Key = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618") - n2Key = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619") + n1Key = PrivateKey.fromHex( + "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[] + n2Key = PrivateKey.fromHex( + "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619")[] type Neighbour = tuple[ip: IpAddress, udpPort, tcpPort: Port, pk: PublicKey] var nodes = newSeqOfCap[Neighbour](2) - nodes.add((n1Addr.ip, n1Addr.udpPort, n1Addr.tcpPort, n1Key.getPublicKey())) - nodes.add((n2Addr.ip, n2Addr.udpPort, n2Addr.tcpPort, n2Key.getPublicKey())) + nodes.add((n1Addr.ip, n1Addr.udpPort, n1Addr.tcpPort, n1Key.toPublicKey().tryGet())) + nodes.add((n2Addr.ip, n2Addr.udpPort, n2Addr.tcpPort, n2Key.toPublicKey().tryGet())) let payload = rlp.encode((nodes, expiration())).toRange let encodedData = @[4.byte] & payload.toSeq() diff --git a/tests/keyfile/test_keyfile.nim b/tests/keyfile/test_keyfile.nim index a67ac82..a894c9b 100644 --- a/tests/keyfile/test_keyfile.nim +++ b/tests/keyfile/test_keyfile.nim @@ -88,28 +88,28 @@ var jobject: JsonNode suite "KeyFile test suite": test "KeyStoreTests/basic_tests.json test1": var seckey: PrivateKey - var expectkey = initPrivateKey(TestVectors[0].getOrDefault("priv").getStr()) + var expectkey = PrivateKey.fromHex(TestVectors[0].getOrDefault("priv").getStr())[] check: decodeKeyFileJson(TestVectors[0].getOrDefault("keyfile"), TestVectors[0].getOrDefault("password").getStr(), seckey) == KeyFileStatus.Success - seckey.data == expectkey.data + seckey.toRaw == expectkey.toRaw test "KeyStoreTests/basic_tests.json python_generated_test_with_odd_iv": var seckey: PrivateKey - var expectkey = initPrivateKey(TestVectors[1].getOrDefault("priv").getStr()) + var expectkey = PrivateKey.fromHex(TestVectors[1].getOrDefault("priv").getStr())[] check: decodeKeyFileJson(TestVectors[1].getOrDefault("keyfile"), TestVectors[1].getOrDefault("password").getStr(), seckey) == KeyFileStatus.Success - seckey.data == expectkey.data + seckey.toRaw == expectkey.toRaw test "KeyStoreTests/basic_tests.json evilnonce": var seckey: PrivateKey - var expectkey = initPrivateKey(TestVectors[2].getOrDefault("priv").getStr()) + var expectkey = PrivateKey.fromHex(TestVectors[2].getOrDefault("priv").getStr())[] check: decodeKeyFileJson(TestVectors[2].getOrDefault("keyfile"), TestVectors[2].getOrDefault("password").getStr(), seckey) == KeyFileStatus.Success - seckey.data == expectkey.data + seckey.toRaw == expectkey.toRaw test "KeyStoreTests/basic_tests.json evilnonce with wrong password": var seckey: PrivateKey check: @@ -117,7 +117,7 @@ suite "KeyFile test suite": "wrongpassword", seckey) == KeyFileStatus.IncorrectMac test "Create/Save/Load test": - var seckey0 = newPrivateKey() + var seckey0 = PrivateKey.random()[] var seckey1: PrivateKey check: createKeyFileJson(seckey0, "randompassword", @@ -125,7 +125,7 @@ suite "KeyFile test suite": saveKeyFile("test.keyfile", jobject) == KeyFileStatus.Success loadKeyFile("test.keyfile", "randompassword", seckey1) == KeyFileStatus.Success - seckey0.data == seckey1.data + seckey0.toRaw == seckey1.toRaw removeFile("test.keyfile") test "Load non-existent pathname test": var seckey: PrivateKey diff --git a/tests/keys/disabled_test_key_and_signature_datastructures.nim b/tests/keys/disabled_test_key_and_signature_datastructures.nim index 257e1c9..91191b5 100644 --- a/tests/keys/disabled_test_key_and_signature_datastructures.nim +++ b/tests/keys/disabled_test_key_and_signature_datastructures.nim @@ -17,7 +17,7 @@ suite "Test key and signature data structure": test "Signing from private key object (ported from official eth-keys)": for person in [alice, bob, eve]: let - pk = initPrivateKey(person.privkey) + pk = PrivateKey.fromHex(person.privkey)[] signature = pk.sign_msg(MSG) 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)": for person in [alice, bob, eve]: let - pk = initPrivateKey(person.privkey) + pk = PrivateKey.fromHex(person.privkey)[] signature = pk.sign_msg(MSGHASH) 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": for person in [alice, bob, eve]: let - pk = initPrivateKey(person.privkey) + pk = PrivateKey.fromHex(person.privkey)[] signature = pk.sign_msg(MSG) 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": for person in [alice, bob, eve]: let - pk = initPrivateKey(person.privkey) + pk = PrivateKey.formHex(person.privkey)[] signature = pk.sign_msg(MSGHASH) recovered_pubkey = recover_pubkey_from_msg(MSGHASH, signature) @@ -53,7 +53,7 @@ suite "Test key and signature data structure": test "Signature serialization and deserialization": for person in [alice, bob, eve]: let - pk = initPrivateKey(person.privkey) + pk = PrivateKey.fromHex(person.privkey)[] signature = pk.sign_msg(MSG) deserializedSignature = parseSignature(hexToSeqByteBE(person.serialized_sig)) diff --git a/tests/keys/test_keys.nim b/tests/keys/test_keys.nim index 380ed5e..0dc6718 100644 --- a/tests/keys/test_keys.nim +++ b/tests/keys/test_keys.nim @@ -12,6 +12,8 @@ import eth/keys import nimcrypto/hash, nimcrypto/keccak, nimcrypto/utils from strutils import toLowerAscii +import stew/byteutils + proc compare(x: openarray[byte], y: openarray[byte]): bool = result = len(x) == len(y) if result: @@ -19,9 +21,11 @@ proc compare(x: openarray[byte], y: openarray[byte]): bool = if x[i] != y[i]: result = false break + +let message = "message".toBytes() + const pkbytes = "58d23b55bc9cdce1f18c2500f40ff4ab7245df9a89505e9b1fa4851f623d241d" - message = "message" address = "dc544d1aa88ff8bbd2f2aec754b1f1e99e1812fd" alice = [ @@ -49,50 +53,50 @@ const suite "ECC/ECDSA/ECDHE tests suite": test "Known private to known public keys (test data from Ethereum eth-keys)": for person in [alice, bob, eve]: - let privkey = initPrivateKey(person[0]) - var pubkeyHex = $privkey.getPublicKey() + let privkey = PrivateKey.fromHex(person[0])[] + var pubkeyHex = $privkey.toPublicKey()[] check: pubkeyHex == stripSpaces(person[1]) test "Recover public key from message": for person in [alice, bob, eve]: - let privkey = initPrivateKey(person[0]) - let signature = privkey.signMessage(message) - let recoveredKey = signature.recoverKeyFromSignature(message) + let privkey = PrivateKey.fromHex(person[0])[] + let signature = privkey.sign(message)[] + let recoveredKey = signature.recover(message)[] check: - $privkey.getPublicKey() == $recoveredKey + $privkey.toPublicKey()[] == $recoveredKey test "Signature serialization and deserialization": for person in [alice, bob, eve]: - let privkey = initPrivateKey(person[0]) - let signature = privkey.signMessage(message) - let expectSignature = initSignature(person[2]) + let privkey = PrivateKey.fromHex(person[0])[] + let signature = privkey.sign(message)[] + let expectSignature = Signature.fromHex(stripSpaces(person[2]))[] check: $signature == $expectSignature test "test_recover_from_signature_obj": - var s = initPrivateKey(pkbytes) + var s = PrivateKey.fromHex(pkbytes)[] var mhash = keccak256.digest(message) - var signature = s.signMessage(message) - var p = recoverKeyFromSignature(signature, mhash) + var signature = s.sign(message)[] + var p = recover(signature, mhash) check: - s.getPublicKey() == p + s.toPublicKey() == p test "test_to_address_from_public_key": - var s = initPrivateKey(pkbytes) - var chk = s.getPublicKey().toAddress() + var s = PrivateKey.fromHex(pkbytes)[] + var chk = s.toPublicKey()[].toAddress() var expect = "0x" & address check chk == expect test "test_to_canonical_address_from_public_key": - var s = initPrivateKey(pkbytes) - var chk = s.getPublicKey().toCanonicalAddress() + var s = PrivateKey.fromHex(pkbytes)[] + var chk = s.toPublicKey()[].toCanonicalAddress() var expect = fromHex(stripSpaces(address)) check compare(chk, expect) == true test "test_to_checksum_address_from_public_key": - var s = initPrivateKey(pkbytes) - var chk = s.getPublicKey().toChecksumAddress() + var s = PrivateKey.fromHex(pkbytes)[] + var chk = s.toPublicKey()[].toChecksumAddress() var expect = "0x" & address check: chk.toLowerAscii() == expect @@ -124,7 +128,7 @@ suite "ECC/ECDSA/ECDHE tests suite": test "EIP-55 100 addresses": for i in 1..100: - var kp = newKeyPair() + var kp = KeyPair.random()[] var chaddress = kp.pubkey.toChecksumAddress() var noaddress = kp.pubkey.toAddress() if noaddress != chaddress: @@ -149,13 +153,12 @@ suite "ECC/ECDSA/ECDHE tests suite": "ee1418607c2fcfb57fda40380e885a707f49000a5dda056d828b7d9bd1f29a08", "167ccc13ac5e8a26b131c3446030c60fbfac6aa8e31149d0869f93626a4cdf62" ] - var secret: SharedSecret for i in 0..1: - var s = privateKeys[i].initPrivateKey() - var p = publicKeys[i].initPublicKey() + var s = PrivateKey.fromHex(privateKeys[i])[] + var p = PublicKey.fromHex(stripSpaces(publicKeys[i]))[] let expect = fromHex(stripSpaces(sharedSecrets[i])) + let secret = ecdhRaw(s, p)[] check: - ecdhAgree(s, p, secret) == EthKeysStatus.Success expect == secret.data 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 var expectm = """ 8ac7e464348b85d9fdfc0a81f2fdc0bbbb8ee5fb3840de6ed60ad9372e718977""" - var secret: SharedSecret - var s = initPrivateKey(keccak256.digest("ecdhAgree").data) - var p = s.getPublicKey() + var s = PrivateKey.fromRaw(keccak256.digest("ecdhAgree").data)[] + var p = s.toPublicKey()[] let expect = fromHex(stripSpaces(expectm)) + let secret = ecdhRaw(s, p)[] check: - ecdhAgree(s, p, secret) == EthKeysStatus.Success expect == secret.data test "ECDHE/cpp-ethereum rlpx.cpp#L425": @@ -181,12 +183,11 @@ suite "ECC/ECDSA/ECDHE tests suite": 7f0821367332598b6aa4e180a41e92f4ebbae3518da847f0b1c0bbfe20bcf4e1""" var e0 = """ ee1418607c2fcfb57fda40380e885a707f49000a5dda056d828b7d9bd1f29a08""" - var secret: SharedSecret - var s = initPrivateKey(s0) - var p = initPublicKey(p0) + var s = PrivateKey.fromHex(stripSpaces(s0))[] + var p = PublicKey.fromHex(stripSpaces(p0))[] let expect = fromHex(stripSpaces(e0)) + let secret = ecdhRaw(s, p)[] check: - ecdhAgree(s, p, secret) == Success compare(expect, secret.data) == true test "ECDSA/cpp-ethereum crypto.cpp#L132": @@ -200,72 +201,62 @@ suite "ECC/ECDSA/ECDHE tests suite": 84453b0b24f49086feba0bd978bb4446bae8dff1e79fcc1e9cf482ec2d07c3""" var check1 = fromHex(stripSpaces(signature)) var check2 = fromHex(stripSpaces(pubkey)) - var sig: Signature - var key: PublicKey - var s = initPrivateKey(keccak256.digest("sec").data) - var m = keccak256.digest("msg").data - check signRawMessage(m, s, sig) == Success - var sersig = sig.getRaw() - check recoverSignatureKey(sersig, m, key) == Success - var serkey = key.getRaw() + + var s = PrivateKey.fromRaw(keccak256.digest("sec").data)[] + var m = keccak256.digest("msg") + var sig = sign(s, m)[] + var sersig = sig.toRaw() + var key = recover(sig, m)[] + var serkey = key.toRaw() check: compare(sersig, check1) == true compare(serkey, check2) == true test "ECDSA/100 signatures": # signature test - var rkey: PublicKey - var sig: Signature for i in 1..100: - var m = newPrivateKey().data - var s = newPrivateKey() - var key = s.getPublicKey() - check signRawMessage(m, s, sig) == Success - var sersig = sig.getRaw() + var m = PrivateKey.random()[].toRaw + var s = PrivateKey.random()[] + var key = s.toPublicKey()[] + let sig = sign(s, m)[] + let rkey = recover(sig, m)[] check: - recoverSignatureKey(sersig, m, rkey) == Success key == rkey test "KEYS/100 create/recovery keys": # key create/recovery test - var rkey: PublicKey for i in 1..100: - var s = newPrivateKey() - var key = s.getPublicKey() + var s = PrivateKey.random()[] + var key = s.toPublicKey()[] + let rkey = PublicKey.fromRaw(key.toRaw())[] check: - recoverPublicKey(key.getRaw(), rkey) == Success key == rkey test "ECDHE/100 shared secrets": # ECDHE shared secret test - var secret1, secret2: SharedSecret for i in 1..100: - var aliceSecret = newPrivateKey() - var alicePublic = aliceSecret.getPublicKey() - var bobSecret = newPrivateKey() - var bobPublic = bobSecret.getPublicKey() + var aliceSecret = PrivateKey.random()[] + var alicePublic = aliceSecret.toPublicKey()[] + var bobSecret = PrivateKey.random()[] + var bobPublic = bobSecret.toPublicKey()[] + var secret1 = ecdhRaw(aliceSecret, bobPublic)[] + var secret2 = ecdhRaw(bobSecret, alicePublic)[] check: - ecdhAgree(aliceSecret, bobPublic, secret1) == Success - ecdhAgree(bobSecret, alicePublic, secret2) == Success secret1 == secret2 - test "isZeroKey() checks": + test "verfiy() checks": var seckey1: PrivateKey - var pubkey1: PublicKey - var seckey2 = newPrivateKey() - var pubkey2 = seckey2.getPublicKey() + var seckey2 = PrivateKey.random()[] check: - seckey1.isZeroKey() == true - pubkey1.isZeroKey() == true - seckey2.isZeroKey() == false - pubkey2.isZeroKey() == false + seckey1.verify() == false + seckey2.verify() == true test "Compressed public keys": - let pubkeyCompressed = "03CA634CAE0D49ACB401D8A4C6B6FE8C55B70D115BF400769CC1400F3258CD3138" - let s = initPublicKey(pubkeyCompressed) + let pubkeyCompressed = "03CA634CAE0D49ACB401D8A4C6B6FE8C55B70D115BF400769CC1400F3258CD3138".toLowerAscii + let s = PublicKey.fromHex(pubkeyCompressed)[] check: - s.getRaw.toHex == """CA634CAE0D49ACB401D8A4C6B6FE8C55B70D115BF400769CC1400F3258 - CD31387574077F301B421BC84DF7266C44E9E6D569FC56BE00812904767BF5CCD1FC7F""".stripSpaces + s.toRaw.toHex == """CA634CAE0D49ACB401D8A4C6B6FE8C55B70D115BF400769CC1400F3258 + CD31387574077F301B421BC84DF7266C44E9E6D569FC56BE00812904767BF5CCD1FC7F""".stripSpaces.toLowerAscii - s.getRawCompressed.toHex == pubkeyCompressed + s.toRawCompressed.toHex == pubkeyCompressed diff --git a/tests/keys/test_private_public_key_consistency.nim b/tests/keys/test_private_public_key_consistency.nim index c5223de..a6f28b7 100644 --- a/tests/keys/test_private_public_key_consistency.nim +++ b/tests/keys/test_private_public_key_consistency.nim @@ -16,12 +16,12 @@ suite "Testing private -> public key conversion": test "Known private to known public keys (test data from Ethereum eth-keys)": for person in [alice, bob, eve]: let - privKey = initPrivateKey(person.privkey) - pubKey = privKey.getPublicKey + privKey = PrivateKey.fromHex(person.privkey)[] + pubKey = privKey.toPublicKey()[] check: # Compare as strings $pubKey == person.pubkey # Compare as keys - pubKey == initPublicKey(person.pubkey) + pubKey == PublicKey.fromHex(person.pubkey)[] diff --git a/tests/p2p/disabled_test_shh_connect_mocked.nim b/tests/p2p/disabled_test_shh_connect_mocked.nim index 17f1ec6..23689b2 100644 --- a/tests/p2p/disabled_test_shh_connect_mocked.nim +++ b/tests/p2p/disabled_test_shh_connect_mocked.nim @@ -22,7 +22,7 @@ template asyncTest(name, body: untyped) = asyncTest "network with 3 peers using the Whisper protocol": const useCompression = defined(useSnappy) - let localKeys = newKeyPair() + let localKeys = KeyPair.random()[] let localAddress = localAddress(30303) var localNode = newEthereumNode(localKeys, localAddress, 1, nil, addAllCapabilities = false, diff --git a/tests/p2p/p2p_test_helper.nim b/tests/p2p/p2p_test_helper.nim index 7bddcb1..5b5d029 100644 --- a/tests/p2p/p2p_test_helper.nim +++ b/tests/p2p/p2p_test_helper.nim @@ -17,13 +17,13 @@ proc startDiscoveryNode*(privKey: PrivateKey, address: Address, proc setupBootNode*(): Future[ENode] {.async.} = let - bootNodeKey = newPrivateKey() + bootNodeKey = KeyPair.random()[] bootNodeAddr = localAddress(30301) - bootNode = await startDiscoveryNode(bootNodeKey, bootNodeAddr, @[]) - result = initENode(bootNodeKey.getPublicKey, bootNodeAddr) + bootNode = await startDiscoveryNode(bootNodeKey.seckey, bootNodeAddr, @[]) + result = initENode(bootNodeKey.pubkey, bootNodeAddr) proc setupTestNode*(capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode = - let keys1 = newKeyPair() + let keys1 = KeyPair.random()[] result = newEthereumNode(keys1, localAddress(nextPort), 1, nil, addAllCapabilities = false) nextPort.inc @@ -45,7 +45,7 @@ template procSuite*(name, body: untyped) = proc packData*(payload: openArray[byte], pk: PrivateKey): seq[byte] = let payloadSeq = @payload - signature = @(pk.signMessage(payload).getRaw()) + signature = @(pk.sign(payload).tryGet().toRaw()) msgHash = keccak256.digest(signature & payloadSeq) result = @(msgHash.data) & signature & payloadSeq diff --git a/tests/p2p/shh_basic_client.nim b/tests/p2p/shh_basic_client.nim index 51a710d..2cb19c8 100644 --- a/tests/p2p/shh_basic_client.nim +++ b/tests/p2p/shh_basic_client.nim @@ -79,15 +79,17 @@ if config.main: else: netId = 15 -let keypair = newKeyPair() +let keypair = KeyPair.random()[] var node = newEthereumNode(keypair, address, netId, nil, addAllCapabilities = false) node.addCapability Whisper # lets prepare some prearranged keypairs -let encPrivateKey = initPrivateKey("5dc5381cae54ba3174dc0d46040fe11614d0cc94d41185922585198b4fcef9d3") -let encPublicKey = encPrivateKey.getPublicKey() -let signPrivateKey = initPrivateKey("365bda0757d22212b04fada4b9222f8c3da59b49398fa04cf612481cd893b0a3") -let signPublicKey = signPrivateKey.getPublicKey() +let encPrivateKey = PrivateKey.fromHex( + "5dc5381cae54ba3174dc0d46040fe11614d0cc94d41185922585198b4fcef9d3")[] +let encPublicKey = encPrivateKey.toPublicKey()[] +let signPrivateKey = PrivateKey.fromHex( + "365bda0757d22212b04fada4b9222f8c3da59b49398fa04cf612481cd893b0a3")[] +let signPublicKey = signPrivateKey.toPublicKey()[] var symKey: SymKey # To test with geth: all 0's key is invalid in geth console symKey[31] = 1 diff --git a/tests/p2p/test_auth.nim b/tests/p2p/test_auth.nim index 76decfa..35329a8 100644 --- a/tests/p2p/test_auth.nim +++ b/tests/p2p/test_auth.nim @@ -217,19 +217,19 @@ suite "Ethereum P2P handshake test suite": proc newTestHandshake(flags: set[HandshakeFlag]): Handshake = result = newHandshake(flags) if Initiator in flags: - result.host.seckey = initPrivateKey(testValue("initiator_private_key")) - result.host.pubkey = result.host.seckey.getPublicKey() + result.host.seckey = PrivateKey.fromHex(testValue("initiator_private_key"))[] + result.host.pubkey = result.host.seckey.toPublicKey()[] let epki = testValue("initiator_ephemeral_private_key") - result.ephemeral.seckey = initPrivateKey(epki) - result.ephemeral.pubkey = result.ephemeral.seckey.getPublicKey() + result.ephemeral.seckey = PrivateKey.fromHex(epki)[] + result.ephemeral.pubkey = result.ephemeral.seckey.toPublicKey()[] let nonce = fromHex(stripSpaces(testValue("initiator_nonce"))) result.initiatorNonce[0..^1] = nonce[0..^1] elif Responder in flags: - result.host.seckey = initPrivateKey(testValue("receiver_private_key")) - result.host.pubkey = result.host.seckey.getPublicKey() + result.host.seckey = PrivateKey.fromHex(testValue("receiver_private_key"))[] + result.host.pubkey = result.host.seckey.toPublicKey()[] let epkr = testValue("receiver_ephemeral_private_key") - result.ephemeral.seckey = initPrivateKey(epkr) - result.ephemeral.pubkey = result.ephemeral.seckey.getPublicKey() + result.ephemeral.seckey = PrivateKey.fromHex(epkr)[] + result.ephemeral.pubkey = result.ephemeral.seckey.toPublicKey()[] let nonce = fromHex(stripSpaces(testValue("receiver_nonce"))) result.responderNonce[0..^1] = nonce[0..^1] @@ -252,15 +252,15 @@ suite "Ethereum P2P handshake test suite": var responder = newTestHandshake({Responder}) var m0 = newSeq[byte](initiator.authSize()) var k0 = 0 - let remoteEPubkey0 = initiator.ephemeral.pubkey.data - let remoteHPubkey0 = initiator.host.pubkey.data + let remoteEPubkey0 = initiator.ephemeral.pubkey + let remoteHPubkey0 = initiator.host.pubkey check: initiator.authMessage(responder.host.pubkey, m0, k0) == AuthStatus.Success responder.decodeAuthMessage(m0) == AuthStatus.Success responder.initiatorNonce[0..^1] == initiator.initiatorNonce[0..^1] - responder.remoteEPubkey.data[0..^1] == remoteEPubkey0[0..^1] - responder.remoteHPubkey.data[0..^1] == remoteHPubkey0[0..^1] + responder.remoteEPubkey == remoteEPubkey0 + responder.remoteHPubkey == remoteHPubkey0 test "ACK message expectation": var initiator = newTestHandshake({Initiator}) @@ -291,11 +291,11 @@ suite "Ethereum P2P handshake test suite": responder.decodeAuthMessage(m0) == AuthStatus.Success responder.ackMessage(m1, k1) == AuthStatus.Success initiator.decodeAckMessage(m1) == AuthStatus.Success - let remoteEPubkey0 = responder.ephemeral.pubkey.data - let remoteHPubkey0 = responder.host.pubkey.data + let remoteEPubkey0 = responder.ephemeral.pubkey + let remoteHPubkey0 = responder.host.pubkey check: - initiator.remoteEPubkey.data[0..^1] == remoteEPubkey0[0..^1] - initiator.remoteHPubkey.data[0..^1] == remoteHPubkey0[0..^1] + initiator.remoteEPubkey == remoteEPubkey0 + initiator.remoteHPubkey == remoteHPubkey0 initiator.responderNonce == responder.responderNonce test "Check derived secrets": @@ -332,19 +332,19 @@ suite "Ethereum P2P handshake test suite": proc newTestHandshake(flags: set[HandshakeFlag]): Handshake = result = newHandshake(flags) if Initiator in flags: - result.host.seckey = initPrivateKey(testE8Value("initiator_private_key")) - result.host.pubkey = result.host.seckey.getPublicKey() + result.host.seckey = PrivateKey.fromHex(testE8Value("initiator_private_key"))[] + result.host.pubkey = result.host.seckey.toPublicKey()[] let esec = testE8Value("initiator_ephemeral_private_key") - result.ephemeral.seckey = initPrivateKey(esec) - result.ephemeral.pubkey = result.ephemeral.seckey.getPublicKey() + result.ephemeral.seckey = PrivateKey.fromHex(esec)[] + result.ephemeral.pubkey = result.ephemeral.seckey.toPublicKey()[] let nonce = fromHex(stripSpaces(testE8Value("initiator_nonce"))) result.initiatorNonce[0..^1] = nonce[0..^1] elif Responder in flags: - result.host.seckey = initPrivateKey(testE8Value("receiver_private_key")) - result.host.pubkey = result.host.seckey.getPublicKey() + result.host.seckey = PrivateKey.fromHex(testE8Value("receiver_private_key"))[] + result.host.pubkey = result.host.seckey.toPublicKey()[] let esec = testE8Value("receiver_ephemeral_private_key") - result.ephemeral.seckey = initPrivateKey(esec) - result.ephemeral.pubkey = result.ephemeral.seckey.getPublicKey() + result.ephemeral.seckey = PrivateKey.fromHex(esec)[] + result.ephemeral.pubkey = result.ephemeral.seckey.toPublicKey()[] let nonce = fromHex(stripSpaces(testE8Value("receiver_nonce"))) result.responderNonce[0..^1] = nonce[0..^1] @@ -355,16 +355,16 @@ suite "Ethereum P2P handshake test suite": check: responder.decodeAuthMessage(m0) == AuthStatus.Success responder.initiatorNonce[0..^1] == initiator.initiatorNonce[0..^1] - let remoteEPubkey0 = initiator.ephemeral.pubkey.data - let remoteHPubkey0 = initiator.host.pubkey.data + let remoteEPubkey0 = initiator.ephemeral.pubkey + let remoteHPubkey0 = initiator.host.pubkey check: - responder.remoteEPubkey.data[0..^1] == remoteEPubkey0[0..^1] - responder.remoteHPubkey.data[0..^1] == remoteHPubkey0[0..^1] + responder.remoteEPubkey == remoteEPubkey0 + responder.remoteHPubkey == remoteHPubkey0 var m1 = fromHex(stripSpaces(testE8Value("authack_ciphertext_v4"))) check initiator.decodeAckMessage(m1) == AuthStatus.Success - let remoteEPubkey1 = responder.ephemeral.pubkey.data + let remoteEPubkey1 = responder.ephemeral.pubkey check: - initiator.remoteEPubkey.data[0..^1] == remoteEPubkey1[0..^1] + initiator.remoteEPubkey == remoteEPubkey1 initiator.responderNonce[0..^1] == responder.responderNonce[0..^1] test "AUTH/ACK EIP-8 test vectors": @@ -374,15 +374,15 @@ suite "Ethereum P2P handshake test suite": check: responder.decodeAuthMessage(m0) == AuthStatus.Success responder.initiatorNonce[0..^1] == initiator.initiatorNonce[0..^1] - let remoteEPubkey0 = initiator.ephemeral.pubkey.data - check responder.remoteEPubkey.data[0..^1] == remoteEPubkey0[0..^1] - let remoteHPubkey0 = initiator.host.pubkey.data - check responder.remoteHPubkey.data[0..^1] == remoteHPubkey0[0..^1] + let remoteEPubkey0 = initiator.ephemeral.pubkey + check responder.remoteEPubkey == remoteEPubkey0 + let remoteHPubkey0 = initiator.host.pubkey + check responder.remoteHPubkey == remoteHPubkey0 var m1 = fromHex(stripSpaces(testE8Value("authack_ciphertext_eip8"))) check initiator.decodeAckMessage(m1) == AuthStatus.Success - let remoteEPubkey1 = responder.ephemeral.pubkey.data + let remoteEPubkey1 = responder.ephemeral.pubkey check: - initiator.remoteEPubkey.data[0..^1] == remoteEPubkey1[0..^1] + initiator.remoteEPubkey == remoteEPubkey1 initiator.responderNonce[0..^1] == responder.responderNonce[0..^1] var taes = fromHex(stripSpaces(testE8Value("auth2ack2_aes_secret"))) var tmac = fromHex(stripSpaces(testE8Value("auth2ack2_mac_secret"))) @@ -410,18 +410,18 @@ suite "Ethereum P2P handshake test suite": check: responder.decodeAuthMessage(m0) == AuthStatus.Success responder.initiatorNonce[0..^1] == initiator.initiatorNonce[0..^1] - let remoteEPubkey0 = initiator.ephemeral.pubkey.data - let remoteHPubkey0 = initiator.host.pubkey.data + let remoteEPubkey0 = initiator.ephemeral.pubkey + let remoteHPubkey0 = initiator.host.pubkey check: - responder.remoteEPubkey.data[0..^1] == remoteEPubkey0[0..^1] - responder.remoteHPubkey.data[0..^1] == remoteHPubkey0[0..^1] + responder.remoteEPubkey == remoteEPubkey0 + responder.remoteHPubkey == remoteHPubkey0 var m1 = fromHex(stripSpaces(testE8Value("authack_ciphertext_eip8_3f"))) check initiator.decodeAckMessage(m1) == AuthStatus.Success - let remoteEPubkey1 = responder.ephemeral.pubkey.data + let remoteEPubkey1 = responder.ephemeral.pubkey check: int(initiator.version) == 57 int(responder.version) == 56 - initiator.remoteEPubkey.data[0..^1] == remoteEPubkey1[0..^1] + initiator.remoteEPubkey == remoteEPubkey1 initiator.responderNonce[0..^1] == responder.responderNonce[0..^1] test "100 AUTH/ACK EIP-8 handshakes": diff --git a/tests/p2p/test_crypt.nim b/tests/p2p/test_crypt.nim index c23949f..09ddc52 100644 --- a/tests/p2p/test_crypt.nim +++ b/tests/p2p/test_crypt.nim @@ -90,19 +90,19 @@ suite "Ethereum RLPx encryption/decryption test suite": proc newTestHandshake(flags: set[HandshakeFlag]): Handshake = result = newHandshake(flags) if Initiator in flags: - result.host.seckey = initPrivateKey(testValue("initiator_private_key")) - result.host.pubkey = result.host.seckey.getPublicKey() + result.host.seckey = PrivateKey.fromHex(testValue("initiator_private_key"))[] + result.host.pubkey = result.host.seckey.toPublicKey()[] let epki = testValue("initiator_ephemeral_private_key") - result.ephemeral.seckey = initPrivateKey(epki) - result.ephemeral.pubkey = result.ephemeral.seckey.getPublicKey() + result.ephemeral.seckey = PrivateKey.fromHex(epki)[] + result.ephemeral.pubkey = result.ephemeral.seckey.toPublicKey()[] let nonce = fromHex(stripSpaces(testValue("initiator_nonce"))) result.initiatorNonce[0..^1] = nonce[0..^1] elif Responder in flags: - result.host.seckey = initPrivateKey(testValue("receiver_private_key")) - result.host.pubkey = result.host.seckey.getPublicKey() + result.host.seckey = PrivateKey.fromHex(testValue("receiver_private_key"))[] + result.host.pubkey = result.host.seckey.toPublicKey()[] let epkr = testValue("receiver_ephemeral_private_key") - result.ephemeral.seckey = initPrivateKey(epkr) - result.ephemeral.pubkey = result.ephemeral.seckey.getPublicKey() + result.ephemeral.seckey = PrivateKey.fromHex(epkr)[] + result.ephemeral.pubkey = result.ephemeral.seckey.toPublicKey()[] let nonce = fromHex(stripSpaces(testValue("receiver_nonce"))) result.responderNonce[0..^1] = nonce[0..^1] diff --git a/tests/p2p/test_discovery.nim b/tests/p2p/test_discovery.nim index 1a68b19..3c3f8ab 100644 --- a/tests/p2p/test_discovery.nim +++ b/tests/p2p/test_discovery.nim @@ -19,16 +19,20 @@ proc nodeIdInNodes(id: NodeId, nodes: openarray[Node]): bool = proc test() {.async.} = suite "Discovery Tests": let - bootNodeKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617") + bootNodeKey = PrivateKey.fromHex( + "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[] bootNodeAddr = localAddress(20301) - bootENode = initENode(bootNodeKey.getPublicKey, bootNodeAddr) + bootENode = initENode(bootNodeKey.toPublicKey()[], bootNodeAddr) bootNode = await startDiscoveryNode(bootNodeKey, bootNodeAddr, @[]) test "Discover nodes": let nodeKeys = [ - initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618"), - initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619"), - initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a620") + PrivateKey.fromHex( + "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[], + PrivateKey.fromHex( + "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619")[], + PrivateKey.fromHex( + "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a620")[] ] var nodeAddrs = newSeqOfCap[Address](nodeKeys.len) for i in 0 ..< nodeKeys.len: nodeAddrs.add(localAddress(20302 + i)) @@ -62,7 +66,8 @@ proc test() {.async.} = ] let address = localAddress(20302) - nodeKey = initPrivateKey("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + nodeKey = PrivateKey.fromHex( + "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")[] for data in validProtocolData: # none of these may raise @@ -80,7 +85,8 @@ proc test() {.async.} = ] let address = localAddress(20302) - nodeKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618") + nodeKey = PrivateKey.fromHex( + "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[] for data in invalidProtocolData: expect DiscProtocolError: diff --git a/tests/p2p/test_discoveryv5.nim b/tests/p2p/test_discoveryv5.nim index 8ceba2a..764056f 100644 --- a/tests/p2p/test_discoveryv5.nim +++ b/tests/p2p/test_discoveryv5.nim @@ -26,13 +26,13 @@ proc randomPacket(tag: PacketTag): seq[byte] = authTag: AuthTag msg: array[44, byte] - randomBytes(authTag) - randomBytes(msg) + randomBytes2(authTag) + randomBytes2(msg) result.add(tag) result.add(rlp.encode(authTag)) result.add(msg) -proc generateNode(privKey = newPrivateKey(), port: int): Node = +proc generateNode(privKey = PrivateKey.random()[], port: int): Node = let port = Port(port) let enr = enr.Record.init(1, privKey, some(parseIpAddress("127.0.0.1")), port, port) @@ -41,13 +41,17 @@ proc generateNode(privKey = newPrivateKey(), port: int): Node = suite "Discovery v5 Tests": asyncTest "Random nodes": let - bootNodeKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617") + bootNodeKey = PrivateKey.fromHex( + "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[] bootNode = initDiscoveryNode(bootNodeKey, localAddress(20301)) let nodeKeys = [ - initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618"), - initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619"), - initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a620") + PrivateKey.fromHex( + "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[], + PrivateKey.fromHex( + "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a619")[], + PrivateKey.fromHex( + "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a620")[] ] var nodeAddrs = newSeqOfCap[Address](nodeKeys.len) for i in 0 ..< nodeKeys.len: nodeAddrs.add(localAddress(20302 + i)) @@ -74,13 +78,13 @@ suite "Discovery v5 Tests": const nodeCount = 17 - let bootNode = initDiscoveryNode(newPrivateKey(), localAddress(20301)) + let bootNode = initDiscoveryNode(PrivateKey.random()[], localAddress(20301)) bootNode.start() var nodes = newSeqOfCap[discv5_protocol.Protocol](nodeCount) nodes.add(bootNode) for i in 1 ..< nodeCount: - nodes.add(initDiscoveryNode(newPrivateKey(), localAddress(20301 + i), + nodes.add(initDiscoveryNode(PrivateKey.random()[], localAddress(20301 + i), @[bootNode.localNode.record])) nodes[i].start() @@ -96,7 +100,7 @@ suite "Discovery v5 Tests": 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 for i in 0..<1000: @@ -110,7 +114,7 @@ suite "Discovery v5 Tests": debug "Closest neighbour", closestDistance, id=closest.id.toHex() let - testNode = initDiscoveryNode(newPrivateKey(), localAddress(20302), + testNode = initDiscoveryNode(PrivateKey.random()[], localAddress(20302), @[mainNode.localNode.record]) discovered = await discv5_protocol.findNode(testNode, mainNode.localNode, closestDistance) @@ -123,7 +127,7 @@ suite "Discovery v5 Tests": asyncTest "GetNode": # TODO: This could be tested in just a routing table only context let - node = initDiscoveryNode(newPrivateKey(), localAddress(20302)) + node = initDiscoveryNode(PrivateKey.random()[], localAddress(20302)) targetNode = generateNode(port = 20303) node.addNode(targetNode) @@ -137,10 +141,10 @@ suite "Discovery v5 Tests": asyncTest "Node deletion": let - bootnode = initDiscoveryNode(newPrivateKey(), localAddress(20301)) - node1 = initDiscoveryNode(newPrivateKey(), localAddress(20302), + bootnode = initDiscoveryNode(PrivateKey.random()[], localAddress(20301)) + node1 = initDiscoveryNode(PrivateKey.random()[], localAddress(20302), @[bootnode.localNode.record]) - node2 = initDiscoveryNode(newPrivateKey(), localAddress(20303), + node2 = initDiscoveryNode(PrivateKey.random()[], localAddress(20303), @[bootnode.localNode.record]) pong1 = await discv5_protocol.ping(node1, bootnode.localNode) pong2 = await discv5_protocol.ping(node1, node2.localNode) @@ -160,12 +164,12 @@ suite "Discovery v5 Tests": asyncTest "Handshake cleanup": - let node = initDiscoveryNode(newPrivateKey(), localAddress(20302)) + let node = initDiscoveryNode(PrivateKey.random()[], localAddress(20302)) var tag: PacketTag let a = localAddress(20303) for i in 0 ..< 5: - randomBytes(tag) + randomBytes2(tag) node.receive(a, randomPacket(tag)) # Checking different nodeIds but same address @@ -179,7 +183,7 @@ suite "Discovery v5 Tests": await node.closeWait() asyncTest "Handshake different address": - let node = initDiscoveryNode(newPrivateKey(), localAddress(20302)) + let node = initDiscoveryNode(PrivateKey.random()[], localAddress(20302)) var tag: PacketTag for i in 0 ..< 5: @@ -191,7 +195,7 @@ suite "Discovery v5 Tests": await node.closeWait() asyncTest "Handshake duplicates": - let node = initDiscoveryNode(newPrivateKey(), localAddress(20302)) + let node = initDiscoveryNode(PrivateKey.random()[], localAddress(20302)) var tag: PacketTag let a = localAddress(20303) @@ -235,8 +239,8 @@ suite "Discovery v5 Tests": ("8c5b422155d33ea8e9d46f71d1ad3e7b24cb40051413ffa1a81cff613d243ba9", 256'u32) ] - let targetId = toNodeId(initPublicKey(targetKey)) + let targetId = toNodeId(PublicKey.fromHex(targetKey)[]) for (key, d) in testValues: - let id = toNodeId(initPrivateKey(key).getPublicKey()) + let id = toNodeId(PrivateKey.fromHex(key)[].toPublicKey()[]) check logDist(targetId, id) == d diff --git a/tests/p2p/test_discv5_encoding.nim b/tests/p2p/test_discv5_encoding.nim index 3b665b7..e82958e 100644 --- a/tests/p2p/test_discv5_encoding.nim +++ b/tests/p2p/test_discv5_encoding.nim @@ -132,13 +132,12 @@ suite "Discovery v5 Cryptographic Primitives": sharedSecret = "0x033b11a2a1f214567e1537ce5e509ffd9b21373247f2a3ff6841f4976f53165e7e" let - pub = initPublicKey(publicKey) - priv = initPrivateKey(secretKey) - var eph: SharedSecretFull + pub = PublicKey.fromHex(publicKey)[] + priv = PrivateKey.fromHex(secretKey)[] + let eph = ecdhRawFull(priv, pub) check: - ecdhAgree(priv, pub, eph) == EthKeysStatus.Success - eph.data == hexToSeqByte(sharedSecret) + eph[].data == hexToSeqByte(sharedSecret) test "Key Derivation": # const @@ -167,10 +166,10 @@ suite "Discovery v5 Cryptographic Primitives": idNonceSig = "0xc5036e702a79902ad8aa147dabfe3958b523fd6fa36cc78e2889b912d682d8d35fdea142e141f690736d86f50b39746ba2d2fc510b46f82ee08f08fd55d133a4" let - c = Codec(privKey: initPrivateKey(localSecretKey)) + c = Codec(privKey: PrivateKey.fromHex(localSecretKey)[]) signature = signIDNonce(c, hexToByteArray[idNonceSize](idNonce), hexToByteArray[64](ephemeralKey)) - check signature.getRaw() == hexToByteArray[64](idNonceSig) + check signature.toRaw() == hexToByteArray[64](idNonceSig) test "Encryption/Decryption": const diff --git a/tests/p2p/test_ecies.nim b/tests/p2p/test_ecies.nim index e8eb681..d0b0d33 100644 --- a/tests/p2p/test_ecies.nim +++ b/tests/p2p/test_ecies.nim @@ -69,8 +69,8 @@ suite "ECIES test suite": var encr = newSeq[byte](eciesEncryptedLength(len(m))) var decr = newSeq[byte](len(m)) var shmac = [0x13'u8, 0x13'u8] - var s = newPrivateKey() - var p = s.getPublicKey() + var s = PrivateKey.random()[] + var p = s.toPublicKey()[] check: # Without additional mac data eciesEncrypt(plain, encr, p) == EciesStatus.Success @@ -123,7 +123,7 @@ suite "ECIES test suite": ] var data: array[1024, byte] for i in 0..1: - var s = initPrivateKey(secretKeys[i]) + var s = PrivateKey.fromHex(secretKeys[i])[] var cipher = fromHex(stripSpaces(cipherText[i])) var expect = fromHex(stripSpaces(expectText[i])) check: @@ -164,7 +164,7 @@ suite "ECIES test suite": ] var data: array[1024, byte] for i in 0..3: - var s = initPrivateKey(secretKeys[i]) + var s = PrivateKey.fromHex(secretKeys[i])[] var cipher = fromHex(stripSpaces(cipherData[i])) check: eciesDecrypt(cipher, data, s) == EciesStatus.Success diff --git a/tests/p2p/test_enode.nim b/tests/p2p/test_enode.nim index a3ba56f..e64f93f 100644 --- a/tests/p2p/test_enode.nim +++ b/tests/p2p/test_enode.nim @@ -97,5 +97,5 @@ suite "ENode": check isCorrect(node) == false node.address.udpPort = Port(25) check isCorrect(node) == false - node.pubkey.data[0] = 1'u8 + node.pubkey = PrivateKey.random()[].toPublicKey()[] check isCorrect(node) == true diff --git a/tests/p2p/test_enr.nim b/tests/p2p/test_enr.nim index 3a2afe1..7344578 100644 --- a/tests/p2p/test_enr.nim +++ b/tests/p2p/test_enr.nim @@ -5,7 +5,8 @@ import suite "ENR": 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]}) doAssert($r == """(id: "v4", ip: 0x05060708, secp256k1: 0x02E51EFA66628CE09F689BC2B82F165A75A9DDECBB6A804BE15AC3FDF41F3B34E7, udp: 1234)""") let uri = r.toURI() @@ -32,14 +33,14 @@ suite "ENR": test "Create from ENode address": let - keys = newKeyPair() + keys = KeyPair.random()[] ip = parseIpAddress("10.20.30.40") enr = Record.init(100, keys.seckey, some(ip), Port(9000), Port(9000)) typedEnr = get enr.toTypedRecord() check: typedEnr.secp256k1.isSome() - typedEnr.secp256k1.get == keys.pubkey.getRawCompressed() + typedEnr.secp256k1.get == keys.pubkey.toRawCompressed() typedEnr.ip.isSome() typedEnr.ip.get() == [byte 10, 20, 30, 40] @@ -52,13 +53,13 @@ suite "ENR": test "ENR without address": let - keys = newKeyPair() + keys = KeyPair.random()[] enr = Record.init(100, keys.seckey, none(IpAddress), Port(9000), Port(9000)) typedEnr = get enr.toTypedRecord() check: typedEnr.secp256k1.isSome() - typedEnr.secp256k1.get() == keys.pubkey.getRawCompressed() + typedEnr.secp256k1.get() == keys.pubkey.toRawCompressed() typedEnr.ip.isNone() typedEnr.tcp.isSome() diff --git a/tests/p2p/test_shh.nim b/tests/p2p/test_shh.nim index d12d23a..e4df3b2 100644 --- a/tests/p2p/test_shh.nim +++ b/tests/p2p/test_shh.nim @@ -36,7 +36,7 @@ suite "Whisper payload": decoded.get().padding.get().len == 251 # 256 -1 -1 -3 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 encoded = whisper.encode(payload) @@ -45,13 +45,13 @@ suite "Whisper payload": check: decoded.isSome() 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 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]) let encoded = whisper.encode(payload) @@ -84,7 +84,7 @@ suite "Whisper payload padding": decoded.get().padding.get().len == 256 # as dataLen == 256 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 encoded = whisper.encode(payload) @@ -93,7 +93,7 @@ suite "Whisper payload padding": check: decoded.isSome() payload.payload == decoded.get().payload - privKey.getPublicKey() == decoded.get().src.get() + privKey.toPublicKey()[] == decoded.get().src.get() decoded.get().padding.isSome() 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 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 encoded = whisper.encode(payload) @@ -118,7 +118,7 @@ suite "Whisper payload padding": check: decoded.isSome() payload.payload == decoded.get().payload - privKey.getPublicKey() == decoded.get().src.get() + privKey.toPublicKey()[] == decoded.get().src.get() decoded.get().padding.isSome() decoded.get().padding.get().len == 1 # as dataLen == 255 @@ -147,7 +147,7 @@ suite "Whisper payload padding": decoded.get().padding.isNone() 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), padding: some(repeat(byte 2, 100))) let encoded = whisper.encode(payload) @@ -156,13 +156,13 @@ suite "Whisper payload padding": check: decoded.isSome() payload.payload == decoded.get().payload - privKey.getPublicKey() == decoded.get().src.get() + privKey.toPublicKey()[] == decoded.get().src.get() decoded.get().padding.isSome() payload.padding.get() == decoded.get().padding.get() test "should roundtrip custom 0 padding with signature": let padding: seq[byte] = @[] - let privKey = keys.newPrivateKey() + let privKey = PrivateKey.random()[] let payload = Payload(src: some(privKey), payload: repeat(byte 1, 10), padding: some(padding)) let encoded = whisper.encode(payload) @@ -171,7 +171,7 @@ suite "Whisper payload padding": check: decoded.isSome() payload.payload == decoded.get().payload - privKey.getPublicKey() == decoded.get().src.get() + privKey.toPublicKey()[] == decoded.get().src.get() decoded.get().padding.isNone() # 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() 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 msg = prepFilterTestMsg(pubKey = some(privKey.getPublicKey()), + let msg = prepFilterTestMsg(pubKey = some(privKey.toPublicKey()[]), topic = topic) var filters = initTable[string, Filter]() @@ -318,12 +318,12 @@ suite "Whisper filter": messages[0].dst.isSome() test "should notify filter on message with signature": - let privKey = keys.newPrivateKey() + let privKey = PrivateKey.random()[] let topic = [byte 0, 0, 0, 0] let msg = prepFilterTestMsg(src = some(privKey), topic = topic) var filters = initTable[string, Filter]() - let filter = initFilter(src = some(privKey.getPublicKey()), + let filter = initFilter(src = some(privKey.toPublicKey()[]), topics = @[topic]) let filterId = filters.subscribeFilter(filter) diff --git a/tests/p2p/test_shh_connect.nim b/tests/p2p/test_shh_connect.nim index c090333..3d536a3 100644 --- a/tests/p2p/test_shh_connect.nim +++ b/tests/p2p/test_shh_connect.nim @@ -30,8 +30,8 @@ procSuite "Whisper connections": node1.peerPool.connectedNodes.len() == 1 asyncTest "Filters with encryption and signing": - let encryptKeyPair = newKeyPair() - let signKeyPair = newKeyPair() + let encryptKeyPair = KeyPair.random()[] + let signKeyPair = KeyPair.random()[] var symKey: SymKey let topic = [byte 0x12, 0, 0, 0] var filters: seq[string] = @[] diff --git a/tests/p2p/tserver.nim b/tests/p2p/tserver.nim index 138e5c8..8da5313 100644 --- a/tests/p2p/tserver.nim +++ b/tests/p2p/tserver.nim @@ -97,7 +97,7 @@ template sendResponse(peer: Peer, proto, msg: untyped, data: varargs[untyped]): asyncTest "network with 3 peers using custom protocols": const useCompression = defined(useSnappy) - let localKeys = newKeyPair() + let localKeys = KeyPair.random()[] let localAddress = localAddress(30303) var localNode = newEthereumNode(localKeys, localAddress, 1, nil, useCompression = useCompression) localNode.startListening()