diff --git a/examples/directchat.nim b/examples/directchat.nim
index a0d7f9e43..8e5d06658 100644
--- a/examples/directchat.nim
+++ b/examples/directchat.nim
@@ -152,7 +152,7 @@ proc readInput(wfd: AsyncFD) {.thread.} =
proc processInput(rfd: AsyncFD) {.async.} =
let transp = fromPipe(rfd)
- let seckey = PrivateKey.random(RSA)
+ let seckey = PrivateKey.random(RSA).get()
let peerInfo = PeerInfo.init(seckey)
var localAddress = DefaultAddr
while true:
diff --git a/libp2p/cid.nim b/libp2p/cid.nim
index 2212bafea..c7b7bd014 100644
--- a/libp2p/cid.nim
+++ b/libp2p/cid.nim
@@ -95,7 +95,7 @@ proc decode(data: openarray[byte], cid: var Cid): CidStatus =
if mcodec == InvalidMultiCodec:
return CidStatus.Incorrect
if not MultiHash.validate(vb.buffer.toOpenArray(vb.offset,
- len(vb.buffer) - 1)):
+ vb.buffer.high)):
return CidStatus.Incorrect
vb.finish()
cid.cidver = CIDv1
@@ -133,7 +133,7 @@ proc validate*(ctype: typedesc[Cid], data: openarray[byte]): bool =
var res: VarintStatus
if len(data) < 2:
return false
- let last = len(data) - 1
+ let last = data.high
if len(data) == 34:
if data[0] == 0x12'u8 and data[1] == 0x20'u8:
return true
@@ -161,8 +161,8 @@ proc mhash*(cid: Cid): MultiHash =
## Returns MultiHash part of CID.
if cid.cidver notin {CIDv0, CIDv1}:
raise newException(CidError, "Incorrect CID!")
- result = MultiHash.init(cid.data.buffer.toOpenArray(cid.hpos,
- len(cid.data) - 1))
+ result = MultiHash.init(
+ cid.data.buffer.toOpenArray(cid.hpos, cid.data.high)).tryGet()
proc contentType*(cid: Cid): MultiCodec =
## Returns content type part of CID
@@ -221,11 +221,11 @@ proc `==`*(a: Cid, b: Cid): bool =
## are equal, ``false`` otherwise.
if a.mcodec == b.mcodec:
var ah, bh: MultiHash
- if MultiHash.decode(a.data.buffer.toOpenArray(a.hpos,
- len(a.data) - 1), ah) == -1:
+ if MultiHash.decode(
+ a.data.buffer.toOpenArray(a.hpos, a.data.high), ah).isErr:
return false
- if MultiHash.decode(b.data.buffer.toOpenArray(b.hpos,
- len(b.data) - 1), bh) == -1:
+ if MultiHash.decode(
+ b.data.buffer.toOpenArray(b.hpos, b.data.high), bh).isErr:
return false
result = (ah == bh)
diff --git a/libp2p/crypto/crypto.nim b/libp2p/crypto/crypto.nim
index ec5de7ffc..10a1d8edd 100644
--- a/libp2p/crypto/crypto.nim
+++ b/libp2p/crypto/crypto.nim
@@ -8,6 +8,9 @@
## those terms.
## This module implements Public Key and Private Key interface for libp2p.
+
+{.push raises: [Defect].}
+
import rsa, ecnist, ed25519/ed25519, secp
import ../protobuf/minprotobuf, ../vbuffer, ../multihash, ../multicodec
import nimcrypto/[rijndael, blowfish, twofish, sha, sha2, hash, hmac, utils]
@@ -79,172 +82,177 @@ type
Signature* = object
data*: seq[byte]
- P2pKeyError* = object of CatchableError
- P2pSigError* = object of CatchableError
+ CryptoError* = enum
+ KeyError,
+ SigError,
+ HashError,
+ SchemeError
+
+ CryptoResult*[T] = Result[T, CryptoError]
const
SupportedSchemes* = {RSA, Ed25519, Secp256k1, ECDSA}
SupportedSchemesInt* = {int8(RSA), int8(Ed25519), int8(Secp256k1),
int8(ECDSA)}
+template orError(exp: untyped, err: CryptoError): untyped =
+ (exp.mapErr do (_: auto) -> auto: err)
+
proc random*(t: typedesc[PrivateKey], scheme: PKScheme,
- bits = DefaultKeySize): PrivateKey =
+ bits = DefaultKeySize): CryptoResult[PrivateKey] =
## Generate random private key for scheme ``scheme``.
##
## ``bits`` is number of bits for RSA key, ``bits`` value must be in
## [512, 4096], default value is 2048 bits.
- doAssert(scheme in SupportedSchemes)
- result = PrivateKey(scheme: scheme)
- if scheme == RSA:
- result.rsakey = RsaPrivateKey.random(bits)
- elif scheme == Ed25519:
- result.edkey = EdPrivateKey.random()
- elif scheme == ECDSA:
- result.eckey = EcPrivateKey.random(Secp256r1)
- elif scheme == Secp256k1:
- result.skkey = SkPrivateKey.random()
+ case scheme
+ of RSA:
+ let rsakey = ? RsaPrivateKey.random(bits).orError(KeyError)
+ ok(PrivateKey(scheme: scheme, rsakey: rsakey))
+ of Ed25519:
+ let edkey = ? EdPrivateKey.random().orError(KeyError)
+ ok(PrivateKey(scheme: scheme, edkey: edkey))
+ of ECDSA:
+ let eckey = ? EcPrivateKey.random(Secp256r1).orError(KeyError)
+ ok(PrivateKey(scheme: scheme, eckey: eckey))
+ of Secp256k1:
+ let skkey = ? SkPrivateKey.random().orError(KeyError)
+ ok(PrivateKey(scheme: scheme, skkey: skkey))
+ else:
+ err(SchemeError)
proc random*(t: typedesc[KeyPair], scheme: PKScheme,
- bits = DefaultKeySize): KeyPair =
+ bits = DefaultKeySize): CryptoResult[KeyPair] =
## Generate random key pair for scheme ``scheme``.
##
## ``bits`` is number of bits for RSA key, ``bits`` value must be in
## [512, 4096], default value is 2048 bits.
- doAssert(scheme in SupportedSchemes)
- result.seckey = PrivateKey(scheme: scheme)
- result.pubkey = PublicKey(scheme: scheme)
- if scheme == RSA:
- var pair = RsaKeyPair.random(bits)
- result.seckey.rsakey = pair.seckey
- result.pubkey.rsakey = pair.pubkey
- elif scheme == Ed25519:
- var pair = EdKeyPair.random()
- result.seckey.edkey = pair.seckey
- result.pubkey.edkey = pair.pubkey
- elif scheme == ECDSA:
- var pair = EcKeyPair.random(Secp256r1)
- result.seckey.eckey = pair.seckey
- result.pubkey.eckey = pair.pubkey
- elif scheme == Secp256k1:
- var pair = SkKeyPair.random()
- result.seckey.skkey = pair.seckey
- result.pubkey.skkey = pair.pubkey
+ case scheme
+ of RSA:
+ let pair = ? RsaKeyPair.random(bits).orError(KeyError)
+ ok(KeyPair(
+ seckey: PrivateKey(scheme: scheme, rsakey: pair.seckey),
+ pubkey: PublicKey(scheme: scheme, rsakey: pair.pubkey)))
+ of Ed25519:
+ let pair = ? EdKeyPair.random().orError(KeyError)
+ ok(KeyPair(
+ seckey: PrivateKey(scheme: scheme, edkey: pair.seckey),
+ pubkey: PublicKey(scheme: scheme, edkey: pair.pubkey)))
+ of ECDSA:
+ let pair = ? EcKeyPair.random(Secp256r1).orError(KeyError)
+ ok(KeyPair(
+ seckey: PrivateKey(scheme: scheme, eckey: pair.seckey),
+ pubkey: PublicKey(scheme: scheme, eckey: pair.pubkey)))
+ of Secp256k1:
+ let pair = ? SkKeyPair.random().orError(KeyError)
+ ok(KeyPair(
+ seckey: PrivateKey(scheme: scheme, skkey: pair.seckey),
+ pubkey: PublicKey(scheme: scheme, skkey: pair.pubkey)))
+ else:
+ err(SchemeError)
-proc getKey*(key: PrivateKey): PublicKey =
+proc getKey*(key: PrivateKey): CryptoResult[PublicKey] =
## Get public key from corresponding private key ``key``.
- result = PublicKey(scheme: key.scheme)
- if key.scheme == RSA:
- result.rsakey = key.rsakey.getKey()
- elif key.scheme == Ed25519:
- result.edkey = key.edkey.getKey()
- elif key.scheme == ECDSA:
- result.eckey = key.eckey.getKey()
- elif key.scheme == Secp256k1:
- result.skkey = key.skkey.getKey()
+ case key.scheme
+ of RSA:
+ let rsakey = key.rsakey.getKey()
+ ok(PublicKey(scheme: RSA, rsakey: rsakey))
+ of Ed25519:
+ let edkey = key.edkey.getKey()
+ ok(PublicKey(scheme: Ed25519, edkey: edkey))
+ of ECDSA:
+ let eckey = ? key.eckey.getKey().orError(KeyError)
+ ok(PublicKey(scheme: ECDSA, eckey: eckey))
+ of Secp256k1:
+ let skkey = ? key.skkey.getKey().orError(KeyError)
+ ok(PublicKey(scheme: Secp256k1, skkey: skkey))
+ else:
+ err(KeyError)
-proc toRawBytes*(key: PrivateKey, data: var openarray[byte]): int =
+proc toRawBytes*(key: PrivateKey | PublicKey, data: var openarray[byte]): CryptoResult[int] =
## Serialize private key ``key`` (using scheme's own serialization) and store
## it to ``data``.
##
## Returns number of bytes (octets) needed to store private key ``key``.
- if key.scheme == RSA:
- result = key.rsakey.toBytes(data)
- elif key.scheme == Ed25519:
- result = key.edkey.toBytes(data)
- elif key.scheme == ECDSA:
- result = key.eckey.toBytes(data)
- elif key.scheme == Secp256k1:
- result = key.skkey.toBytes(data)
+ case key.scheme
+ of RSA:
+ key.rsakey.toBytes(data).orError(KeyError)
+ of Ed25519:
+ ok(key.edkey.toBytes(data))
+ of ECDSA:
+ key.eckey.toBytes(data).orError(KeyError)
+ of Secp256k1:
+ key.skkey.toBytes(data).orError(KeyError)
+ else:
+ err(KeyError)
-proc toRawBytes*(key: PublicKey, data: var openarray[byte]): int =
- ## Serialize public key ``key`` (using scheme's own serialization) and store
- ## it to ``data``.
- ##
- ## Returns number of bytes (octets) needed to store public key ``key``.
- if key.scheme == RSA:
- result = key.rsakey.toBytes(data)
- elif key.scheme == Ed25519:
- result = key.edkey.toBytes(data)
- elif key.scheme == ECDSA:
- result = key.eckey.toBytes(data)
- elif key.scheme == Secp256k1:
- result = key.skkey.toBytes(data)
-
-proc getRawBytes*(key: PrivateKey): seq[byte] =
+proc getRawBytes*(key: PrivateKey | PublicKey): CryptoResult[seq[byte]] =
## Return private key ``key`` in binary form (using scheme's own
## serialization).
- if key.scheme == RSA:
- result = key.rsakey.getBytes()
- elif key.scheme == Ed25519:
- result = key.edkey.getBytes()
- elif key.scheme == ECDSA:
- result = key.eckey.getBytes()
- elif key.scheme == Secp256k1:
- result = key.skkey.getBytes()
+ case key.scheme
+ of RSA:
+ key.rsakey.getBytes().orError(KeyError)
+ of Ed25519:
+ ok(key.edkey.getBytes())
+ of ECDSA:
+ key.eckey.getBytes().orError(KeyError)
+ of Secp256k1:
+ ok(key.skkey.getBytes())
+ else:
+ err(KeyError)
-proc getRawBytes*(key: PublicKey): seq[byte] =
- ## Return public key ``key`` in binary form (using scheme's own
- ## serialization).
- if key.scheme == RSA:
- result = key.rsakey.getBytes()
- elif key.scheme == Ed25519:
- result = key.edkey.getBytes()
- elif key.scheme == ECDSA:
- result = key.eckey.getBytes()
- elif key.scheme == Secp256k1:
- result = key.skkey.getBytes()
-
-proc toBytes*(key: PrivateKey, data: var openarray[byte]): int =
+proc toBytes*(key: PrivateKey, data: var openarray[byte]): CryptoResult[int] =
## Serialize private key ``key`` (using libp2p protobuf scheme) and store
## it to ``data``.
##
## Returns number of bytes (octets) needed to store private key ``key``.
var msg = initProtoBuffer()
msg.write(initProtoField(1, cast[uint64](key.scheme)))
- msg.write(initProtoField(2, key.getRawBytes()))
+ msg.write(initProtoField(2, ? key.getRawBytes()))
msg.finish()
- result = len(msg.buffer)
- if len(data) >= result:
- copyMem(addr data[0], addr msg.buffer[0], len(msg.buffer))
+ var blen = len(msg.buffer)
+ if len(data) >= blen:
+ copyMem(addr data[0], addr msg.buffer[0], blen)
+ ok(blen)
-proc toBytes*(key: PublicKey, data: var openarray[byte]): int =
+proc toBytes*(key: PublicKey, data: var openarray[byte]): CryptoResult[int] =
## Serialize public key ``key`` (using libp2p protobuf scheme) and store
## it to ``data``.
##
## Returns number of bytes (octets) needed to store public key ``key``.
var msg = initProtoBuffer()
msg.write(initProtoField(1, cast[uint64](key.scheme)))
- msg.write(initProtoField(2, key.getRawBytes()))
+ msg.write(initProtoField(2, ? key.getRawBytes()))
msg.finish()
- result = len(msg.buffer)
- if len(data) >= result:
- copyMem(addr data[0], addr msg.buffer[0], len(msg.buffer))
+ var blen = len(msg.buffer)
+ if len(data) >= blen and blen > 0:
+ copyMem(addr data[0], addr msg.buffer[0], blen)
+ ok(blen)
proc toBytes*(sig: Signature, data: var openarray[byte]): int =
## Serialize signature ``sig`` and store it to ``data``.
##
## Returns number of bytes (octets) needed to store signature ``sig``.
result = len(sig.data)
- if len(data) >= result:
+ if len(data) >= result and result > 0:
copyMem(addr data[0], unsafeAddr sig.data[0], len(sig.data))
-proc getBytes*(key: PrivateKey): seq[byte] =
+proc getBytes*(key: PrivateKey): CryptoResult[seq[byte]] =
## Return private key ``key`` in binary form (using libp2p's protobuf
## serialization).
var msg = initProtoBuffer()
msg.write(initProtoField(1, cast[uint64](key.scheme)))
- msg.write(initProtoField(2, key.getRawBytes()))
+ msg.write(initProtoField(2, ? key.getRawBytes()))
msg.finish()
- result = msg.buffer
+ ok(msg.buffer)
-proc getBytes*(key: PublicKey): seq[byte] =
+proc getBytes*(key: PublicKey): CryptoResult[seq[byte]] =
## Return public key ``key`` in binary form (using libp2p's protobuf
## serialization).
var msg = initProtoBuffer()
msg.write(initProtoField(1, cast[uint64](key.scheme)))
- msg.write(initProtoField(2, key.getRawBytes()))
+ msg.write(initProtoField(2, ? key.getRawBytes()))
msg.finish()
- result = msg.buffer
+ ok(msg.buffer)
proc getBytes*(sig: Signature): seq[byte] =
## Return signature ``sig`` in binary form.
@@ -277,7 +285,7 @@ proc init*(key: var PrivateKey, data: openarray[byte]): bool =
key = nkey
result = true
elif scheme == Secp256k1:
- if init(nkey.skkey, buffer):
+ if init(nkey.skkey, buffer).isOk:
key = nkey
result = true
@@ -308,7 +316,7 @@ proc init*(key: var PublicKey, data: openarray[byte]): bool =
key = nkey
result = true
elif scheme == Secp256k1:
- if init(nkey.skkey, buffer):
+ if init(nkey.skkey, buffer).isOk:
key = nkey
result = true
@@ -325,50 +333,77 @@ proc init*(key: var PrivateKey, data: string): bool =
## hexadecimal string representation.
##
## Returns ``true`` on success.
- result = key.init(fromHex(data))
+ try:
+ key.init(fromHex(data))
+ except ValueError:
+ false
proc init*(key: var PublicKey, data: string): bool =
## Initialize public key ``key`` from libp2p's protobuf serialized
## hexadecimal string representation.
##
## Returns ``true`` on success.
- result = key.init(fromHex(data))
+ try:
+ key.init(fromHex(data))
+ except ValueError:
+ false
proc init*(sig: var Signature, data: string): bool =
## Initialize signature ``sig`` from serialized hexadecimal string
## representation.
##
## Returns ``true`` on success.
- result = sig.init(fromHex(data))
+ try:
+ sig.init(fromHex(data))
+ except ValueError:
+ false
-proc init*(t: typedesc[PrivateKey], data: openarray[byte]): PrivateKey =
+proc init*(t: typedesc[PrivateKey], data: openarray[byte]): CryptoResult[PrivateKey] =
## Create new private key from libp2p's protobuf serialized binary form.
- if not result.init(data):
- raise newException(P2pKeyError, "Incorrect binary form")
+ var res: t
+ if not res.init(data):
+ err(KeyError)
+ else:
+ ok(res)
-proc init*(t: typedesc[PublicKey], data: openarray[byte]): PublicKey =
+proc init*(t: typedesc[PublicKey], data: openarray[byte]): CryptoResult[PublicKey] =
## Create new public key from libp2p's protobuf serialized binary form.
- if not result.init(data):
- raise newException(P2pKeyError, "Incorrect binary form")
+ var res: t
+ if not res.init(data):
+ err(KeyError)
+ else:
+ ok(res)
-proc init*(t: typedesc[Signature], data: openarray[byte]): Signature =
+proc init*(t: typedesc[Signature], data: openarray[byte]): CryptoResult[Signature] =
## Create new public key from libp2p's protobuf serialized binary form.
- if not result.init(data):
- raise newException(P2pSigError, "Incorrect binary form")
+ var res: t
+ if not res.init(data):
+ err(SigError)
+ else:
+ ok(res)
-proc init*(t: typedesc[PrivateKey], data: string): PrivateKey =
+proc init*(t: typedesc[PrivateKey], data: string): CryptoResult[PrivateKey] =
## Create new private key from libp2p's protobuf serialized hexadecimal string
## form.
- result = t.init(fromHex(data))
+ try:
+ t.init(fromHex(data))
+ except ValueError:
+ err(KeyError)
-proc init*(t: typedesc[PublicKey], data: string): PublicKey =
+proc init*(t: typedesc[PublicKey], data: string): CryptoResult[PublicKey] =
## Create new public key from libp2p's protobuf serialized hexadecimal string
## form.
- result = t.init(fromHex(data))
+ try:
+ t.init(fromHex(data))
+ except ValueError:
+ err(KeyError)
-proc init*(t: typedesc[Signature], data: string): Signature =
+proc init*(t: typedesc[Signature], data: string): CryptoResult[Signature] =
## Create new signature from serialized hexadecimal string form.
- result = t.init(fromHex(data))
+ try:
+ t.init(fromHex(data))
+ except ValueError:
+ err(SigError)
proc `==`*(key1, key2: PublicKey): bool =
## Return ``true`` if two public keys ``key1`` and ``key2`` of the same
@@ -464,24 +499,30 @@ proc `$`*(sig: Signature): string =
## Get string representation of signature ``sig``.
result = toHex(sig.data)
-proc sign*(key: PrivateKey, data: openarray[byte]): Signature {.gcsafe.} =
+proc sign*(key: PrivateKey, data: openarray[byte]): CryptoResult[Signature] {.gcsafe.} =
## Sign message ``data`` using private key ``key`` and return generated
## signature in raw binary form.
+ var res: Signature
if key.scheme == RSA:
- var sig = key.rsakey.sign(data)
- result.data = sig.getBytes()
+ let sig = ? key.rsakey.sign(data).orError(SigError)
+ res.data = ? sig.getBytes().orError(SigError)
+ ok(res)
elif key.scheme == Ed25519:
- var sig = key.edkey.sign(data)
- result.data = sig.getBytes()
+ let sig = key.edkey.sign(data)
+ res.data = sig.getBytes()
+ ok(res)
elif key.scheme == ECDSA:
- var sig = key.eckey.sign(data)
- result.data = sig.getBytes()
+ let sig = ? key.eckey.sign(data).orError(SigError)
+ res.data = ? sig.getBytes().orError(SigError)
+ ok(res)
elif key.scheme == Secp256k1:
- var sig = key.skkey.sign(data)
- result.data = sig.getBytes()
+ let sig = ? key.skkey.sign(data).orError(SigError)
+ res.data = sig.getBytes()
+ ok(res)
+ else:
+ err(SigError)
-proc verify*(sig: Signature, message: openarray[byte],
- key: PublicKey): bool =
+proc verify*(sig: Signature, message: openarray[byte], key: PublicKey): bool =
## Verify signature ``sig`` using message ``message`` and public key ``key``.
## Return ``true`` if message signature is valid.
if key.scheme == RSA:
@@ -498,7 +539,7 @@ proc verify*(sig: Signature, message: openarray[byte],
result = signature.verify(message, key.eckey)
elif key.scheme == Secp256k1:
var signature: SkSignature
- if signature.init(sig.data):
+ if signature.init(sig.data).isOk:
result = signature.verify(message, key.skkey)
template makeSecret(buffer, hmactype, secret, seed: untyped) {.dirty.}=
@@ -510,11 +551,11 @@ template makeSecret(buffer, hmactype, secret, seed: untyped) {.dirty.}=
if secret[i] != 0x00'u8:
break
inc(offset)
- ctx.init(secret.toOpenArray(offset, len(secret) - 1))
+ ctx.init(secret.toOpenArray(offset, secret.high))
ctx.update(seed)
var a = ctx.finish()
while j < len(buffer):
- ctx.init(secret.toOpenArray(offset, len(secret) - 1))
+ ctx.init(secret.toOpenArray(offset, secret.high))
ctx.update(a.data)
ctx.update(seed)
var b = ctx.finish()
@@ -523,7 +564,7 @@ template makeSecret(buffer, hmactype, secret, seed: untyped) {.dirty.}=
todo = len(buffer) - j
copyMem(addr buffer[j], addr b.data[0], todo)
j += todo
- ctx.init(secret.toOpenArray(offset, len(secret) - 1))
+ ctx.init(secret.toOpenArray(offset, secret.high))
ctx.update(a.data)
a = ctx.finish()
@@ -588,33 +629,32 @@ proc mac*(secret: Secret, id: int): seq[byte] {.inline.} =
offset += secret.ivsize + secret.keysize
copyMem(addr result[0], unsafeAddr secret.data[offset], secret.macsize)
-proc ephemeral*(scheme: ECDHEScheme): KeyPair =
+proc ephemeral*(scheme: ECDHEScheme): CryptoResult[KeyPair] =
## Generate ephemeral keys used to perform ECDHE.
var keypair: EcKeyPair
if scheme == Secp256r1:
- keypair = EcKeyPair.random(Secp256r1)
+ keypair = ? EcKeyPair.random(Secp256r1).orError(KeyError)
elif scheme == Secp384r1:
- keypair = EcKeyPair.random(Secp384r1)
+ keypair = ? EcKeyPair.random(Secp384r1).orError(KeyError)
elif scheme == Secp521r1:
- keypair = EcKeyPair.random(Secp521r1)
- result.seckey = PrivateKey(scheme: ECDSA)
- result.pubkey = PublicKey(scheme: ECDSA)
- result.seckey.eckey = keypair.seckey
- result.pubkey.eckey = keypair.pubkey
+ keypair = ? EcKeyPair.random(Secp521r1).orError(KeyError)
+ ok(KeyPair(
+ seckey: PrivateKey(scheme: ECDSA, eckey: keypair.seckey),
+ pubkey: PublicKey(scheme: ECDSA, eckey: keypair.pubkey)))
-proc ephemeral*(scheme: string): KeyPair {.inline.} =
+proc ephemeral*(scheme: string): CryptoResult[KeyPair] {.inline.} =
## Generate ephemeral keys used to perform ECDHE using string encoding.
##
## Currently supported encoding strings are P-256, P-384, P-521, if encoding
## string is not supported P-521 key will be generated.
if scheme == "P-256":
- result = ephemeral(Secp256r1)
+ ephemeral(Secp256r1)
elif scheme == "P-384":
- result = ephemeral(Secp384r1)
+ ephemeral(Secp384r1)
elif scheme == "P-521":
- result = ephemeral(Secp521r1)
+ ephemeral(Secp521r1)
else:
- result = ephemeral(Secp521r1)
+ ephemeral(Secp521r1)
proc makeSecret*(remoteEPublic: PublicKey, localEPrivate: PrivateKey,
data: var openarray[byte]): int =
@@ -644,7 +684,7 @@ proc getSecret*(remoteEPublic: PublicKey,
result = getSecret(remoteEPublic.eckey, localEPrivate.eckey)
proc getOrder*(remotePubkey, localNonce: openarray[byte],
- localPubkey, remoteNonce: openarray[byte]): int =
+ localPubkey, remoteNonce: openarray[byte]): CryptoResult[int] =
## Compare values and calculate `order` parameter.
var ctx: sha256
ctx.init()
@@ -655,16 +695,18 @@ proc getOrder*(remotePubkey, localNonce: openarray[byte],
ctx.update(localPubkey)
ctx.update(remoteNonce)
var digest2 = ctx.finish()
- var mh1 = MultiHash.init(multiCodec("sha2-256"), digest1)
- var mh2 = MultiHash.init(multiCodec("sha2-256"), digest2)
+ var mh1 = ? MultiHash.init(multiCodec("sha2-256"), digest1).orError(HashError)
+ var mh2 = ? MultiHash.init(multiCodec("sha2-256"), digest2).orError(HashError)
+ var res = 0;
for i in 0 ..< len(mh1.data.buffer):
- result = int(mh1.data.buffer[i]) - int(mh2.data.buffer[i])
- if result != 0:
- if result < 0:
- result = -1
- elif result > 0:
- result = 1
+ res = int(mh1.data.buffer[i]) - int(mh2.data.buffer[i])
+ if res != 0:
+ if res < 0:
+ res = -1
+ elif res > 0:
+ res = 1
break
+ ok(res)
proc selectBest*(order: int, p1, p2: string): string =
## Determines which algorithm to use from list `p1` and `p2`.
@@ -741,25 +783,25 @@ proc decodeExchange*(message: seq[byte],
## Serialization/Deserialization helpers
-proc write*(vb: var VBuffer, pubkey: PublicKey) {.inline.} =
+proc write*(vb: var VBuffer, pubkey: PublicKey) {.inline, raises: [Defect, ResultError[CryptoError]].} =
## Write PublicKey value ``pubkey`` to buffer ``vb``.
- vb.writeSeq(pubkey.getBytes())
+ vb.writeSeq(pubkey.getBytes().tryGet())
-proc write*(vb: var VBuffer, seckey: PrivateKey) {.inline.} =
+proc write*(vb: var VBuffer, seckey: PrivateKey) {.inline, raises: [Defect, ResultError[CryptoError]].} =
## Write PrivateKey value ``seckey`` to buffer ``vb``.
- vb.writeSeq(seckey.getBytes())
+ vb.writeSeq(seckey.getBytes().tryGet())
-proc write*(vb: var VBuffer, sig: PrivateKey) {.inline.} =
+proc write*(vb: var VBuffer, sig: PrivateKey) {.inline, raises: [Defect, ResultError[CryptoError]].} =
## Write Signature value ``sig`` to buffer ``vb``.
- vb.writeSeq(sig.getBytes())
+ vb.writeSeq(sig.getBytes().tryGet())
-proc initProtoField*(index: int, pubkey: PublicKey): ProtoField =
+proc initProtoField*(index: int, pubkey: PublicKey): ProtoField {.raises: [Defect, ResultError[CryptoError]].} =
## Initialize ProtoField with PublicKey ``pubkey``.
- result = initProtoField(index, pubkey.getBytes())
+ result = initProtoField(index, pubkey.getBytes().tryGet())
-proc initProtoField*(index: int, seckey: PrivateKey): ProtoField =
+proc initProtoField*(index: int, seckey: PrivateKey): ProtoField {.raises: [Defect, ResultError[CryptoError]].} =
## Initialize ProtoField with PrivateKey ``seckey``.
- result = initProtoField(index, seckey.getBytes())
+ result = initProtoField(index, seckey.getBytes().tryGet())
proc initProtoField*(index: int, sig: Signature): ProtoField =
## Initialize ProtoField with Signature ``sig``.
diff --git a/libp2p/crypto/ecnist.nim b/libp2p/crypto/ecnist.nim
index 645e9556e..03209305b 100644
--- a/libp2p/crypto/ecnist.nim
+++ b/libp2p/crypto/ecnist.nim
@@ -14,6 +14,8 @@
## BearSSL library
## Copyright(C) 2018 Thomas Pornin .
+{.push raises: [Defect].}
+
import bearssl
import nimcrypto/utils
import minasn1
@@ -58,11 +60,14 @@ type
EcPKI* = EcPrivateKey | EcPublicKey | EcSignature
- EcError* = object of CatchableError
- EcKeyIncorrectError* = object of EcError
- EcRngError* = object of EcError
- EcPublicKeyError* = object of EcError
- EcSignatureError* = object of EcError
+ EcError* = enum
+ EcRngError,
+ EcKeyGenError,
+ EcPublicKeyError,
+ EcKeyIncorrectError,
+ EcSignatureError
+
+ EcResult*[T] = Result[T, EcError]
const
EcSupportedCurvesCint* = {cint(Secp256r1), cint(Secp384r1), cint(Secp521r1)}
@@ -222,7 +227,7 @@ proc clear*[T: EcPKI|EcKeyPair](pki: var T) =
pki.pubkey.key.qlen = 0
pki.pubkey.key.curve = 0
-proc random*(t: typedesc[EcPrivateKey], kind: EcCurveKind): EcPrivateKey =
+proc random*(t: typedesc[EcPrivateKey], kind: EcCurveKind): EcResult[EcPrivateKey] =
## Generate new random EC private key using BearSSL's HMAC-SHA256-DRBG
## algorithm.
##
@@ -232,37 +237,46 @@ proc random*(t: typedesc[EcPrivateKey], kind: EcCurveKind): EcPrivateKey =
var seeder = brPrngSeederSystem(nil)
brHmacDrbgInit(addr rng, addr sha256Vtable, nil, 0)
if seeder(addr rng.vtable) == 0:
- raise newException(ValueError, "Could not seed RNG")
+ return err(EcRngError)
var ecimp = brEcGetDefault()
- result = new EcPrivateKey
- result.buffer = newSeq[byte](BR_EC_KBUF_PRIV_MAX_SIZE)
+ var res = new EcPrivateKey
+ res.buffer = newSeq[byte](BR_EC_KBUF_PRIV_MAX_SIZE)
if brEcKeygen(addr rng.vtable, ecimp,
- addr result.key, addr result.buffer[0],
+ addr res.key, addr res.buffer[0],
cast[cint](kind)) == 0:
- raise newException(ValueError, "Could not generate private key")
+ err(EcKeyGenError)
+ else:
+ ok(res)
-proc getKey*(seckey: EcPrivateKey): EcPublicKey =
+proc getKey*(seckey: EcPrivateKey): EcResult[EcPublicKey] =
## Calculate and return EC public key from private key ``seckey``.
- doAssert(not isNil(seckey))
+ if isNil(seckey):
+ return err(EcKeyIncorrectError)
+
var ecimp = brEcGetDefault()
if seckey.key.curve in EcSupportedCurvesCint:
var length = getPublicKeyLength(cast[EcCurveKind](seckey.key.curve))
- result = new EcPublicKey
- result.buffer = newSeq[byte](length)
- if brEcComputePublicKey(ecimp, addr result.key,
- addr result.buffer[0], unsafeAddr seckey.key) == 0:
- raise newException(EcKeyIncorrectError, "Could not calculate public key")
+ var res = new EcPublicKey
+ res.buffer = newSeq[byte](length)
+ if brEcComputePublicKey(ecimp, addr res.key,
+ addr res.buffer[0], unsafeAddr seckey.key) == 0:
+ err(EcKeyIncorrectError)
+ else:
+ ok(res)
else:
- raise newException(EcKeyIncorrectError, "Incorrect private key")
+ err(EcKeyIncorrectError)
-proc random*(t: typedesc[EcKeyPair], kind: EcCurveKind): EcKeyPair {.inline.} =
+proc random*(t: typedesc[EcKeyPair], kind: EcCurveKind): EcResult[EcKeyPair] =
## Generate new random EC private and public keypair using BearSSL's
## HMAC-SHA256-DRBG algorithm.
##
## ``kind`` elliptic curve kind of your choice (secp256r1, secp384r1 or
## secp521r1).
- result.seckey = EcPrivateKey.random(kind)
- result.pubkey = result.seckey.getKey()
+ let
+ seckey = ? EcPrivateKey.random(kind)
+ pubkey = ? seckey.getKey()
+ key = EcKeyPair(seckey: seckey, pubkey: pubkey)
+ ok(key)
proc `$`*(seckey: EcPrivateKey): string =
## Return string representation of EC private key.
@@ -303,29 +317,37 @@ proc `$`*(sig: EcSignature): string =
else:
result = toHex(sig.buffer)
-proc toRawBytes*(seckey: EcPrivateKey, data: var openarray[byte]): int =
+proc toRawBytes*(seckey: EcPrivateKey, data: var openarray[byte]): EcResult[int] =
## Serialize EC private key ``seckey`` to raw binary form and store it
## to ``data``.
##
## Returns number of bytes (octets) needed to store EC private key, or `0`
## if private key is not in supported curve.
- doAssert(not isNil(seckey))
+ if isNil(seckey):
+ return err(EcKeyIncorrectError)
if seckey.key.curve in EcSupportedCurvesCint:
- result = getPrivateKeyLength(cast[EcCurveKind](seckey.key.curve))
- if len(data) >= result:
- copyMem(addr data[0], unsafeAddr seckey.buffer[0], result)
+ let klen = getPrivateKeyLength(cast[EcCurveKind](seckey.key.curve))
+ if len(data) >= klen:
+ copyMem(addr data[0], unsafeAddr seckey.buffer[0], klen)
+ ok(klen)
+ else:
+ err(EcKeyIncorrectError)
-proc toRawBytes*(pubkey: EcPublicKey, data: var openarray[byte]): int =
+proc toRawBytes*(pubkey: EcPublicKey, data: var openarray[byte]): EcResult[int] =
## Serialize EC public key ``pubkey`` to uncompressed form specified in
## section 4.3.6 of ANSI X9.62.
##
## Returns number of bytes (octets) needed to store EC public key, or `0`
## if public key is not in supported curve.
- doAssert(not isNil(pubkey))
+ if isNil(pubkey):
+ return err(EcKeyIncorrectError)
if pubkey.key.curve in EcSupportedCurvesCint:
- result = getPublicKeyLength(cast[EcCurveKind](pubkey.key.curve))
- if len(data) >= result:
- copyMem(addr data[0], unsafeAddr pubkey.buffer[0], result)
+ let klen = getPublicKeyLength(cast[EcCurveKind](pubkey.key.curve))
+ if len(data) >= klen:
+ copyMem(addr data[0], unsafeAddr pubkey.buffer[0], klen)
+ ok(klen)
+ else:
+ err(EcKeyIncorrectError)
proc toRawBytes*(sig: EcSignature, data: var openarray[byte]): int =
## Serialize EC signature ``sig`` to raw binary form and store it to ``data``.
@@ -338,16 +360,17 @@ proc toRawBytes*(sig: EcSignature, data: var openarray[byte]): int =
if len(sig.buffer) > 0:
copyMem(addr data[0], unsafeAddr sig.buffer[0], len(sig.buffer))
-proc toBytes*(seckey: EcPrivateKey, data: var openarray[byte]): int =
+proc toBytes*(seckey: EcPrivateKey, data: var openarray[byte]): EcResult[int] =
## Serialize EC private key ``seckey`` to ASN.1 DER binary form and store it
## to ``data``.
##
## Procedure returns number of bytes (octets) needed to store EC private key,
## or `0` if private key is not in supported curve.
- doAssert(not isNil(seckey))
+ if isNil(seckey):
+ return err(EcKeyIncorrectError)
if seckey.key.curve in EcSupportedCurvesCint:
var offset, length: int
- var pubkey = seckey.getKey()
+ var pubkey = ? seckey.getKey()
var b = Asn1Buffer.init()
var p = Asn1Composite.init(Asn1Tag.Sequence)
var c0 = Asn1Composite.init(0)
@@ -374,17 +397,23 @@ proc toBytes*(seckey: EcPrivateKey, data: var openarray[byte]): int =
p.finish()
b.write(p)
b.finish()
- result = len(b)
- if len(data) >= result:
- copyMem(addr data[0], addr b.buffer[0], result)
+ var blen = len(b)
+ if len(data) >= blen:
+ copyMem(addr data[0], addr b.buffer[0], blen)
+ # ok anyway, since it might have been a query...
+ ok(blen)
+ else:
+ err(EcKeyIncorrectError)
-proc toBytes*(pubkey: EcPublicKey, data: var openarray[byte]): int =
+
+proc toBytes*(pubkey: EcPublicKey, data: var openarray[byte]): EcResult[int] =
## Serialize EC public key ``pubkey`` to ASN.1 DER binary form and store it
## to ``data``.
##
## Procedure returns number of bytes (octets) needed to store EC public key,
## or `0` if public key is not in supported curve.
- doAssert(not isNil(pubkey))
+ if isNil(pubkey):
+ return err(EcKeyIncorrectError)
if pubkey.key.curve in EcSupportedCurvesCint:
var b = Asn1Buffer.init()
var p = Asn1Composite.init(Asn1Tag.Sequence)
@@ -405,80 +434,97 @@ proc toBytes*(pubkey: EcPublicKey, data: var openarray[byte]): int =
p.finish()
b.write(p)
b.finish()
- result = len(b)
- if len(data) >= result:
- copyMem(addr data[0], addr b.buffer[0], result)
+ var blen = len(b)
+ if len(data) >= blen:
+ copyMem(addr data[0], addr b.buffer[0], blen)
+ ok(blen)
+ else:
+ err(EcKeyIncorrectError)
-proc toBytes*(sig: EcSignature, data: var openarray[byte]): int =
+proc toBytes*(sig: EcSignature, data: var openarray[byte]): EcResult[int] =
## Serialize EC signature ``sig`` to ASN.1 DER binary form and store it
## to ``data``.
##
## Procedure returns number of bytes (octets) needed to store EC signature,
## or `0` if signature is not in supported curve.
- doAssert(not isNil(sig))
- result = len(sig.buffer)
- if len(data) >= result:
- copyMem(addr data[0], unsafeAddr sig.buffer[0], result)
+ if isNil(sig):
+ return err(EcSignatureError)
+ let slen = len(sig.buffer)
+ if len(data) >= slen:
+ copyMem(addr data[0], unsafeAddr sig.buffer[0], slen)
+ ok(slen)
-proc getBytes*(seckey: EcPrivateKey): seq[byte] =
+proc getBytes*(seckey: EcPrivateKey): EcResult[seq[byte]] =
## Serialize EC private key ``seckey`` to ASN.1 DER binary form and return it.
- doAssert(not isNil(seckey))
+ if isNil(seckey):
+ return err(EcKeyIncorrectError)
if seckey.key.curve in EcSupportedCurvesCint:
- result = newSeq[byte]()
- let length = seckey.toBytes(result)
- result.setLen(length)
- discard seckey.toBytes(result)
+ var res = newSeq[byte]()
+ let length = ? seckey.toBytes(res)
+ res.setLen(length)
+ discard ? seckey.toBytes(res)
+ ok(res)
else:
- raise newException(EcKeyIncorrectError, "Incorrect private key")
+ err(EcKeyIncorrectError)
-proc getBytes*(pubkey: EcPublicKey): seq[byte] =
+proc getBytes*(pubkey: EcPublicKey): EcResult[seq[byte]] =
## Serialize EC public key ``pubkey`` to ASN.1 DER binary form and return it.
- doAssert(not isNil(pubkey))
+ if isNil(pubkey):
+ return err(EcKeyIncorrectError)
if pubkey.key.curve in EcSupportedCurvesCint:
- result = newSeq[byte]()
- let length = pubkey.toBytes(result)
- result.setLen(length)
- discard pubkey.toBytes(result)
+ var res = newSeq[byte]()
+ let length = ? pubkey.toBytes(res)
+ res.setLen(length)
+ discard ? pubkey.toBytes(res)
+ ok(res)
else:
- raise newException(EcKeyIncorrectError, "Incorrect public key")
+ err(EcKeyIncorrectError)
-proc getBytes*(sig: EcSignature): seq[byte] =
+proc getBytes*(sig: EcSignature): EcResult[seq[byte]] =
## Serialize EC signature ``sig`` to ASN.1 DER binary form and return it.
- doAssert(not isNil(sig))
- result = newSeq[byte]()
- let length = sig.toBytes(result)
- result.setLen(length)
- discard sig.toBytes(result)
+ if isNil(sig):
+ return err(EcSignatureError)
+ var res = newSeq[byte]()
+ let length = ? sig.toBytes(res)
+ res.setLen(length)
+ discard ? sig.toBytes(res)
+ ok(res)
-proc getRawBytes*(seckey: EcPrivateKey): seq[byte] =
+proc getRawBytes*(seckey: EcPrivateKey): EcResult[seq[byte]] =
## Serialize EC private key ``seckey`` to raw binary form and return it.
- doAssert(not isNil(seckey))
+ if isNil(seckey):
+ return err(EcKeyIncorrectError)
if seckey.key.curve in EcSupportedCurvesCint:
- result = newSeq[byte]()
- let length = seckey.toRawBytes(result)
- result.setLen(length)
- discard seckey.toRawBytes(result)
+ var res = newSeq[byte]()
+ let length = ? seckey.toRawBytes(res)
+ res.setLen(length)
+ discard ? seckey.toRawBytes(res)
+ ok(res)
else:
- raise newException(EcKeyIncorrectError, "Incorrect private key")
+ err(EcKeyIncorrectError)
-proc getRawBytes*(pubkey: EcPublicKey): seq[byte] =
+proc getRawBytes*(pubkey: EcPublicKey): EcResult[seq[byte]] =
## Serialize EC public key ``pubkey`` to raw binary form and return it.
- doAssert(not isNil(pubkey))
+ if isNil(pubkey):
+ return err(EcKeyIncorrectError)
if pubkey.key.curve in EcSupportedCurvesCint:
- result = newSeq[byte]()
- let length = pubkey.toRawBytes(result)
- result.setLen(length)
- discard pubkey.toRawBytes(result)
+ var res = newSeq[byte]()
+ let length = ? pubkey.toRawBytes(res)
+ res.setLen(length)
+ discard ? pubkey.toRawBytes(res)
+ ok(res)
else:
- raise newException(EcKeyIncorrectError, "Incorrect public key")
+ return err(EcKeyIncorrectError)
-proc getRawBytes*(sig: EcSignature): seq[byte] =
+proc getRawBytes*(sig: EcSignature): EcResult[seq[byte]] =
## Serialize EC signature ``sig`` to raw binary form and return it.
- doAssert(not isNil(sig))
- result = newSeq[byte]()
- let length = sig.toBytes(result)
- result.setLen(length)
- discard sig.toBytes(result)
+ if isNil(sig):
+ return err(EcSignatureError)
+ var res = newSeq[byte]()
+ let length = ? sig.toBytes(res)
+ res.setLen(length)
+ discard ? sig.toBytes(res)
+ ok(res)
proc `==`*(pubkey1, pubkey2: EcPublicKey): bool =
## Returns ``true`` if both keys ``pubkey1`` and ``pubkey2`` are equal.
@@ -663,34 +709,43 @@ proc init*[T: EcPKI](sospk: var T, data: string): Result[void, Asn1Error] {.inli
## Procedure returns ``Asn1Status``.
sospk.init(fromHex(data))
-proc init*(t: typedesc[EcPrivateKey], data: openarray[byte]): EcPrivateKey =
+proc init*(t: typedesc[EcPrivateKey], data: openarray[byte]): EcResult[EcPrivateKey] =
## Initialize EC private key from ASN.1 DER binary representation ``data`` and
## return constructed object.
- let res = result.init(data)
+ var key: EcPrivateKey
+ let res = key.init(data)
if res.isErr:
- raise newException(EcKeyIncorrectError,
- "Incorrect private key (" & $res.error & ")")
+ err(EcKeyIncorrectError)
+ else:
+ ok(key)
-proc init*(t: typedesc[EcPublicKey], data: openarray[byte]): EcPublicKey =
+proc init*(t: typedesc[EcPublicKey], data: openarray[byte]): EcResult[EcPublicKey] =
## Initialize EC public key from ASN.1 DER binary representation ``data`` and
## return constructed object.
- let res = result.init(data)
+ var key: EcPublicKey
+ let res = key.init(data)
if res.isErr:
- raise newException(EcKeyIncorrectError,
- "Incorrect public key (" & $res.error & ")")
+ err(EcKeyIncorrectError)
+ else:
+ ok(key)
-proc init*(t: typedesc[EcSignature], data: openarray[byte]): EcSignature =
+proc init*(t: typedesc[EcSignature], data: openarray[byte]): EcResult[EcSignature] =
## Initialize EC signature from raw binary representation ``data`` and
## return constructed object.
- let res = result.init(data)
+ var sig: EcSignature
+ let res = sig.init(data)
if res.isErr:
- raise newException(EcKeyIncorrectError,
- "Incorrect signature (" & $res.error & ")")
+ err(EcSignatureError)
+ else:
+ ok(sig)
-proc init*[T: EcPKI](t: typedesc[T], data: string): T {.inline.} =
+proc init*[T: EcPKI](t: typedesc[T], data: string): EcResult[T] =
## Initialize EC `private key`, `public key` or `signature` from hexadecimal
## string representation ``data`` and return constructed object.
- result = t.init(fromHex(data))
+ try:
+ t.init(fromHex(data))
+ except ValueError:
+ err(EcKeyIncorrectError)
proc initRaw*(key: var EcPrivateKey, data: openarray[byte]): bool =
## Initialize EC `private key` or `scalar` ``key`` from raw binary
@@ -776,23 +831,32 @@ proc initRaw*[T: EcPKI](sospk: var T, data: string): bool {.inline.} =
## Procedure returns ``true`` on success, ``false`` otherwise.
result = sospk.initRaw(fromHex(data))
-proc initRaw*(t: typedesc[EcPrivateKey], data: openarray[byte]): EcPrivateKey =
+proc initRaw*(t: typedesc[EcPrivateKey], data: openarray[byte]): EcResult[EcPrivateKey] =
## Initialize EC private key from raw binary representation ``data`` and
## return constructed object.
- if not result.initRaw(data):
- raise newException(EcKeyIncorrectError, "Incorrect private key")
+ var res: EcPrivateKey
+ if not res.initRaw(data):
+ err(EcKeyIncorrectError)
+ else:
+ ok(res)
-proc initRaw*(t: typedesc[EcPublicKey], data: openarray[byte]): EcPublicKey =
+proc initRaw*(t: typedesc[EcPublicKey], data: openarray[byte]): EcResult[EcPublicKey] =
## Initialize EC public key from raw binary representation ``data`` and
## return constructed object.
- if not result.initRaw(data):
- raise newException(EcKeyIncorrectError, "Incorrect public key")
+ var res: EcPublicKey
+ if not res.initRaw(data):
+ err(EcKeyIncorrectError)
+ else:
+ ok(res)
-proc initRaw*(t: typedesc[EcSignature], data: openarray[byte]): EcSignature =
+proc initRaw*(t: typedesc[EcSignature], data: openarray[byte]): EcResult[EcSignature] =
## Initialize EC signature from raw binary representation ``data`` and
## return constructed object.
- if not result.initRaw(data):
- raise newException(EcKeyIncorrectError, "Incorrect signature")
+ var res: EcSignature
+ if not res.initRaw(data):
+ err(EcSignatureError)
+ else:
+ ok(res)
proc initRaw*[T: EcPKI](t: typedesc[T], data: string): T {.inline.} =
## Initialize EC `private key`, `public key` or `signature` from raw
@@ -858,15 +922,16 @@ proc getSecret*(pubkey: EcPublicKey, seckey: EcPrivateKey): seq[byte] =
copyMem(addr result[0], addr data[0], res)
proc sign*[T: byte|char](seckey: EcPrivateKey,
- message: openarray[T]): EcSignature {.gcsafe.} =
+ message: openarray[T]): EcResult[EcSignature] {.gcsafe.} =
## Get ECDSA signature of data ``message`` using private key ``seckey``.
- doAssert(not isNil(seckey))
+ if isNil(seckey):
+ return err(EcKeyIncorrectError)
var hc: BrHashCompatContext
var hash: array[32, byte]
var impl = brEcGetDefault()
if seckey.key.curve in EcSupportedCurvesCint:
- result = new EcSignature
- result.buffer = newSeq[byte](256)
+ var sig = new EcSignature
+ sig.buffer = newSeq[byte](256)
var kv = addr sha256Vtable
kv.init(addr hc.vtable)
if len(message) > 0:
@@ -875,15 +940,16 @@ proc sign*[T: byte|char](seckey: EcPrivateKey,
kv.update(addr hc.vtable, nil, 0)
kv.output(addr hc.vtable, addr hash[0])
let res = brEcdsaSignAsn1(impl, kv, addr hash[0], addr seckey.key,
- addr result.buffer[0])
+ addr sig.buffer[0])
# Clear context with initial value
kv.init(addr hc.vtable)
if res != 0:
- result.buffer.setLen(res)
+ sig.buffer.setLen(res)
+ ok(sig)
else:
- raise newException(EcSignatureError, "Could not make signature")
+ err(EcSignatureError)
else:
- raise newException(EcKeyIncorrectError, "Incorrect private key")
+ err(EcKeyIncorrectError)
proc verify*[T: byte|char](sig: EcSignature, message: openarray[T],
pubkey: EcPublicKey): bool {.inline.} =
diff --git a/libp2p/crypto/ed25519/ed25519.nim b/libp2p/crypto/ed25519/ed25519.nim
index 20c17b7ea..64305fd4e 100644
--- a/libp2p/crypto/ed25519/ed25519.nim
+++ b/libp2p/crypto/ed25519/ed25519.nim
@@ -10,8 +10,13 @@
## This module implements ED25519.
## This code is a port of the public domain, "ref10" implementation of ed25519
## from SUPERCOP.
+
+{.push raises: Defect.}
+
import constants
import nimcrypto/[hash, sha2, sysrand, utils]
+import stew/results
+export results
# This workaround needed because of some bugs in Nim Static[T].
export hash, sha2
@@ -38,9 +43,9 @@ type
seckey*: EdPrivateKey
pubkey*: EdPublicKey
- EdError* = object of CatchableError
- EdRngError* = object of EdError
- EdIncorrectError* = object of EdError
+ EdError* = enum
+ EdRngError,
+ EdIncorrectError
proc `-`(x: uint32): uint32 {.inline.} =
result = (0xFFFF_FFFF'u32 - x) + 1'u32
@@ -1632,40 +1637,47 @@ proc checkScalar*(scalar: openarray[byte]): uint32 =
for u in scalar:
z = z or u
if len(scalar) == len(CurveOrder):
- for i in countdown(len(scalar) - 1, 0):
+ for i in countdown(scalar.high, 0):
c = c or (-(cast[int32](EQ0(c))) and CMP(scalar[i], CurveOrder[i]))
else:
c = -1
result = NEQ(z, 0'u32) and LT0(c)
-proc random*(t: typedesc[EdPrivateKey]): EdPrivateKey =
+proc random*(t: typedesc[EdPrivateKey]): Result[EdPrivateKey, EdError] =
## Generate new random ED25519 private key using OS specific CSPRNG.
var
point: GeP3
pk: array[EdPublicKeySize, byte]
- if randomBytes(result.data.toOpenArray(0, 31)) != 32:
- raise newException(EdRngError, "Could not generate random data")
- var hh = sha512.digest(result.data.toOpenArray(0, 31))
- hh.data[0] = hh.data[0] and 0xF8'u8
- hh.data[31] = hh.data[31] and 0x3F'u8
- hh.data[31] = hh.data[31] or 0x40'u8
- geScalarMultBase(point, hh.data)
- geP3ToBytes(pk, point)
- copyMem(addr result.data[32], addr pk[0], 32)
+ res: EdPrivateKey
+ if randomBytes(res.data.toOpenArray(0, 31)) != 32:
+ err(EdRngError)
+ else:
+ var hh = sha512.digest(res.data.toOpenArray(0, 31))
+ hh.data[0] = hh.data[0] and 0xF8'u8
+ hh.data[31] = hh.data[31] and 0x3F'u8
+ hh.data[31] = hh.data[31] or 0x40'u8
+ geScalarMultBase(point, hh.data)
+ geP3ToBytes(pk, point)
+ copyMem(addr res.data[32], addr pk[0], 32)
+ ok(res)
-proc random*(t: typedesc[EdKeyPair]): EdKeyPair =
+proc random*(t: typedesc[EdKeyPair]): Result[EdKeyPair, EdError] =
## Generate new random ED25519 private and public keypair using OS specific
## CSPRNG.
- var point: GeP3
- if randomBytes(result.seckey.data.toOpenArray(0, 31)) != 32:
- raise newException(EdRngError, "Could not generate random data")
- var hh = sha512.digest(result.seckey.data.toOpenArray(0, 31))
- hh.data[0] = hh.data[0] and 0xF8'u8
- hh.data[31] = hh.data[31] and 0x3F'u8
- hh.data[31] = hh.data[31] or 0x40'u8
- geScalarMultBase(point, hh.data)
- geP3ToBytes(result.pubkey.data, point)
- copyMem(addr result.seckey.data[32], addr result.pubkey.data[0], 32)
+ var
+ point: GeP3
+ res: EdKeyPair
+ if randomBytes(res.seckey.data.toOpenArray(0, 31)) != 32:
+ err(EdRngError)
+ else:
+ var hh = sha512.digest(res.seckey.data.toOpenArray(0, 31))
+ hh.data[0] = hh.data[0] and 0xF8'u8
+ hh.data[31] = hh.data[31] and 0x3F'u8
+ hh.data[31] = hh.data[31] or 0x40'u8
+ geScalarMultBase(point, hh.data)
+ geP3ToBytes(res.pubkey.data, point)
+ copyMem(addr res.seckey.data[32], addr res.pubkey.data[0], 32)
+ ok(res)
proc getKey*(key: EdPrivateKey): EdPublicKey =
## Calculate and return ED25519 public key from private key ``key``.
@@ -1766,57 +1778,84 @@ proc init*(key: var EdPrivateKey, data: string): bool =
## representation ``data``.
##
## Procedure returns ``true`` on success.
- result = init(key, fromHex(data))
+ try:
+ init(key, fromHex(data))
+ except ValueError:
+ false
proc init*(key: var EdPublicKey, data: string): bool =
## Initialize ED25519 `public key` ``key`` from hexadecimal string
## representation ``data``.
##
## Procedure returns ``true`` on success.
- result = init(key, fromHex(data))
+ try:
+ init(key, fromHex(data))
+ except ValueError:
+ false
proc init*(sig: var EdSignature, data: string): bool =
## Initialize ED25519 `signature` ``sig`` from hexadecimal string
## representation ``data``.
##
## Procedure returns ``true`` on success.
- result = init(sig, fromHex(data))
+ try:
+ init(sig, fromHex(data))
+ except ValueError:
+ false
-proc init*(t: typedesc[EdPrivateKey], data: openarray[byte]): EdPrivateKey =
+proc init*(t: typedesc[EdPrivateKey], data: openarray[byte]): Result[EdPrivateKey, EdError] =
## Initialize ED25519 `private key` from raw binary representation ``data``
## and return constructed object.
- if not init(result, data):
- raise newException(EdIncorrectError, "Incorrect binary form")
+ var res: t
+ if not init(res, data):
+ err(EdIncorrectError)
+ else:
+ ok(res)
-proc init*(t: typedesc[EdPublicKey], data: openarray[byte]): EdPublicKey =
+proc init*(t: typedesc[EdPublicKey], data: openarray[byte]): Result[EdPublicKey, EdError] =
## Initialize ED25519 `public key` from raw binary representation ``data``
## and return constructed object.
- if not init(result, data):
- raise newException(EdIncorrectError, "Incorrect binary form")
+ var res: t
+ if not init(res, data):
+ err(EdIncorrectError)
+ else:
+ ok(res)
-proc init*(t: typedesc[EdSignature], data: openarray[byte]): EdSignature =
+proc init*(t: typedesc[EdSignature], data: openarray[byte]): Result[EdSignature, EdError] =
## Initialize ED25519 `signature` from raw binary representation ``data``
## and return constructed object.
- if not init(result, data):
- raise newException(EdIncorrectError, "Incorrect binary form")
+ var res: t
+ if not init(res, data):
+ err(EdIncorrectError)
+ else:
+ ok(res)
-proc init*(t: typedesc[EdPrivateKey], data: string): EdPrivateKey =
+proc init*(t: typedesc[EdPrivateKey], data: string): Result[EdPrivateKey, EdError] =
## Initialize ED25519 `private key` from hexadecimal string representation
## ``data`` and return constructed object.
- if not init(result, data):
- raise newException(EdIncorrectError, "Incorrect binary form")
+ var res: t
+ if not init(res, data):
+ err(EdIncorrectError)
+ else:
+ ok(res)
-proc init*(t: typedesc[EdPublicKey], data: string): EdPublicKey =
+proc init*(t: typedesc[EdPublicKey], data: string): Result[EdPublicKey, EdError] =
## Initialize ED25519 `public key` from hexadecimal string representation
## ``data`` and return constructed object.
- if not init(result, data):
- raise newException(EdIncorrectError, "Incorrect binary form")
+ var res: t
+ if not init(res, data):
+ err(EdIncorrectError)
+ else:
+ ok(res)
-proc init*(t: typedesc[EdSignature], data: string): EdSignature =
+proc init*(t: typedesc[EdSignature], data: string): Result[EdSignature, EdError] =
## Initialize ED25519 `signature` from hexadecimal string representation
## ``data`` and return constructed object.
- if not init(result, data):
- raise newException(EdIncorrectError, "Incorrect binary form")
+ var res: t
+ if not init(res, data):
+ err(EdIncorrectError)
+ else:
+ ok(res)
proc clear*(key: var EdPrivateKey) =
## Wipe and clear memory of ED25519 `private key`.
diff --git a/libp2p/crypto/minasn1.nim b/libp2p/crypto/minasn1.nim
index a8bc6e03a..63545f221 100644
--- a/libp2p/crypto/minasn1.nim
+++ b/libp2p/crypto/minasn1.nim
@@ -106,10 +106,10 @@ const
## Encoded ``NULL`` value.
template toOpenArray*(ab: Asn1Buffer): untyped =
- toOpenArray(ab.buffer, ab.offset, len(ab.buffer) - 1)
+ toOpenArray(ab.buffer, ab.offset, ab.buffer.high)
template toOpenArray*(ac: Asn1Composite): untyped =
- toOpenArray(ac.buffer, ac.offset, len(ac.buffer) - 1)
+ toOpenArray(ac.buffer, ac.offset, ac.buffer.high)
template toOpenArray*(af: Asn1Field): untyped =
toOpenArray(af.buffer, af.offset, af.offset + af.length - 1)
@@ -336,7 +336,7 @@ proc asn1EncodeOid*(dest: var openarray[byte], value: openarray[int]): int =
result += asn1EncodeLength(buffer, oidlen)
result += oidlen
if len(dest) >= result:
- let last = len(dest) - 1
+ let last = dest.high
var offset = 1
dest[0] = Asn1Tag.Oid.code()
offset += asn1EncodeLength(dest.toOpenArray(offset, last), oidlen)
diff --git a/libp2p/crypto/rsa.nim b/libp2p/crypto/rsa.nim
index 79be34e2a..5f40140c2 100644
--- a/libp2p/crypto/rsa.nim
+++ b/libp2p/crypto/rsa.nim
@@ -12,6 +12,9 @@
## This module uses unmodified parts of code from
## BearSSL library
## Copyright(C) 2018 Thomas Pornin .
+
+{.push raises: Defect.}
+
import nimcrypto/utils
import bearssl
import minasn1
@@ -72,11 +75,13 @@ type
RsaPKI* = RsaPrivateKey | RsaPublicKey | RsaSignature
RsaKP* = RsaPrivateKey | RsaKeyPair
- RsaError* = object of CatchableError
- RsaRngError* = object of RsaError
- RsaGenError* = object of RsaError
- RsaKeyIncorrectError* = object of RsaError
- RsaSignatureError* = object of RsaError
+ RsaError* = enum
+ RsaRngError,
+ RsaGenError,
+ RsaKeyIncorrectError,
+ RsaSignatureError
+
+ RsaResult*[T] = Result[T, RsaError]
template getStart(bs, os, ls: untyped): untyped =
let p = cast[uint](os)
@@ -108,7 +113,7 @@ template trimZeroes(b: seq[byte], pt, ptlen: untyped) =
ptlen -= 1
proc random*[T: RsaKP](t: typedesc[T], bits = DefaultKeySize,
- pubexp = DefaultPublicExponent): T =
+ pubexp = DefaultPublicExponent): RsaResult[T] =
## Generate new random RSA private key using BearSSL's HMAC-SHA256-DRBG
## algorithm.
##
@@ -121,7 +126,8 @@ proc random*[T: RsaKP](t: typedesc[T], bits = DefaultKeySize,
var seeder = brPrngSeederSystem(nil)
brHmacDrbgInit(addr rng, addr sha256Vtable, nil, 0)
if seeder(addr rng.vtable) == 0:
- raise newException(RsaRngError, "Could not seed RNG")
+ return err(RsaRngError)
+
keygen = brRsaKeygenGetDefault()
let length = brRsaPrivateKeyBufferSize(bits) +
@@ -131,34 +137,38 @@ proc random*[T: RsaKP](t: typedesc[T], bits = DefaultKeySize,
let pko = brRsaPrivateKeyBufferSize(bits)
let eko = pko + brRsaPublicKeyBufferSize(bits)
- when T is RsaKeyPair:
- result = new RsaKeyPair
- else:
- result = new RsaPrivateKey
+ var res: T
- result.buffer = newSeq[byte](length)
+ when T is RsaKeyPair:
+ res = new T
+ else:
+ res = new RsaPrivateKey
+
+ res.buffer = newSeq[byte](length)
if keygen(addr rng.vtable,
- addr result.seck, addr result.buffer[sko],
- addr result.pubk, addr result.buffer[pko],
+ addr res.seck, addr res.buffer[sko],
+ addr res.pubk, addr res.buffer[pko],
cuint(bits), pubexp) == 0:
- raise newException(RsaGenError, "Could not create private key")
+ return err(RsaGenError)
let compute = brRsaComputePrivexpGetDefault()
- let res = compute(addr result.buffer[eko], addr result.seck, pubexp)
- if res == 0:
- raise newException(RsaGenError, "Could not create private key")
+ let computed = compute(addr res.buffer[eko], addr res.seck, pubexp)
+ if computed == 0:
+ return err(RsaGenError)
- result.pexp = cast[ptr cuchar](addr result.buffer[eko])
- result.pexplen = res
+ res.pexp = cast[ptr cuchar](addr res.buffer[eko])
+ res.pexplen = computed
- trimZeroes(result.buffer, result.seck.p, result.seck.plen)
- trimZeroes(result.buffer, result.seck.q, result.seck.qlen)
- trimZeroes(result.buffer, result.seck.dp, result.seck.dplen)
- trimZeroes(result.buffer, result.seck.dq, result.seck.dqlen)
- trimZeroes(result.buffer, result.seck.iq, result.seck.iqlen)
- trimZeroes(result.buffer, result.pubk.n, result.pubk.nlen)
- trimZeroes(result.buffer, result.pubk.e, result.pubk.elen)
- trimZeroes(result.buffer, result.pexp, result.pexplen)
+ trimZeroes(res.buffer, res.seck.p, res.seck.plen)
+ trimZeroes(res.buffer, res.seck.q, res.seck.qlen)
+ trimZeroes(res.buffer, res.seck.dp, res.seck.dplen)
+ trimZeroes(res.buffer, res.seck.dq, res.seck.dqlen)
+ trimZeroes(res.buffer, res.seck.iq, res.seck.iqlen)
+ trimZeroes(res.buffer, res.pubk.n, res.pubk.nlen)
+ trimZeroes(res.buffer, res.pubk.e, res.pubk.elen)
+ trimZeroes(res.buffer, res.pexp, res.pexplen)
+
+ ok(res)
proc copy*[T: RsaPKI](key: T): T =
## Create copy of RSA private key, public key or signature.
@@ -275,14 +285,15 @@ proc clear*[T: RsaPKI|RsaKeyPair](pki: var T) =
burnMem(pki.buffer)
pki.buffer.setLen(0)
-proc toBytes*(key: RsaPrivateKey, data: var openarray[byte]): int =
+proc toBytes*(key: RsaPrivateKey, data: var openarray[byte]): RsaResult[int] =
## Serialize RSA private key ``key`` to ASN.1 DER binary form and store it
## to ``data``.
##
## Procedure returns number of bytes (octets) needed to store RSA private key,
## or `0` if private key is is incorrect.
- doAssert(not isNil(key))
- if len(key.buffer) > 0:
+ if isNil(key):
+ err(RsaKeyIncorrectError)
+ elif len(key.buffer) > 0:
var b = Asn1Buffer.init()
var p = Asn1Composite.init(Asn1Tag.Sequence)
p.write(0'u64)
@@ -304,18 +315,22 @@ proc toBytes*(key: RsaPrivateKey, data: var openarray[byte]): int =
p.finish()
b.write(p)
b.finish()
- result = len(b)
- if len(data) >= result:
- copyMem(addr data[0], addr b.buffer[0], result)
+ var blen = len(b)
+ if len(data) >= blen:
+ copyMem(addr data[0], addr b.buffer[0], blen)
+ ok(blen)
+ else:
+ err(RsaKeyIncorrectError)
-proc toBytes*(key: RsaPublicKey, data: var openarray[byte]): int =
+proc toBytes*(key: RsaPublicKey, data: var openarray[byte]): RsaResult[int] =
## Serialize RSA public key ``key`` to ASN.1 DER binary form and store it
## to ``data``.
##
## Procedure returns number of bytes (octets) needed to store RSA public key,
## or `0` if public key is incorrect.
- doAssert(not isNil(key))
- if len(key.buffer) > 0:
+ if isNil(key):
+ err(RsaKeyIncorrectError)
+ elif len(key.buffer) > 0:
var b = Asn1Buffer.init()
var p = Asn1Composite.init(Asn1Tag.Sequence)
var c0 = Asn1Composite.init(Asn1Tag.Sequence)
@@ -334,52 +349,64 @@ proc toBytes*(key: RsaPublicKey, data: var openarray[byte]): int =
p.finish()
b.write(p)
b.finish()
- result = len(b)
- if len(data) >= result:
- copyMem(addr data[0], addr b.buffer[0], result)
+ var blen = len(b)
+ if len(data) >= blen:
+ copyMem(addr data[0], addr b.buffer[0], blen)
+ ok(blen)
+ else:
+ err(RsaKeyIncorrectError)
-proc toBytes*(sig: RsaSignature, data: var openarray[byte]): int =
+proc toBytes*(sig: RsaSignature, data: var openarray[byte]): RSaResult[int] =
## Serialize RSA signature ``sig`` to raw binary form and store it
## to ``data``.
##
## Procedure returns number of bytes (octets) needed to store RSA public key,
## or `0` if public key is incorrect.
- doAssert(not isNil(sig))
- result = len(sig.buffer)
- if len(data) >= result:
- copyMem(addr data[0], addr sig.buffer[0], result)
+ if isNil(sig):
+ err(RsaSignatureError)
+ else:
+ var slen = len(sig.buffer)
+ if len(data) >= slen:
+ copyMem(addr data[0], addr sig.buffer[0], slen)
+ ok(slen)
-proc getBytes*(key: RsaPrivateKey): seq[byte] =
+proc getBytes*(key: RsaPrivateKey): RsaResult[seq[byte]] =
## Serialize RSA private key ``key`` to ASN.1 DER binary form and
## return it.
- doAssert(not isNil(key))
- result = newSeq[byte](4096)
- let length = key.toBytes(result)
+ if isNil(key):
+ return err(RsaKeyIncorrectError)
+ var res = newSeq[byte](4096)
+ let length = ? key.toBytes(res)
if length > 0:
- result.setLen(length)
+ res.setLen(length)
+ ok(res)
else:
- raise newException(RsaKeyIncorrectError, "Incorrect private key")
+ err(RsaKeyIncorrectError)
-proc getBytes*(key: RsaPublicKey): seq[byte] =
+proc getBytes*(key: RsaPublicKey): RsaResult[seq[byte]] =
## Serialize RSA public key ``key`` to ASN.1 DER binary form and
## return it.
- doAssert(not isNil(key))
- result = newSeq[byte](4096)
- let length = key.toBytes(result)
+ if isNil(key):
+ return err(RsaKeyIncorrectError)
+ var res = newSeq[byte](4096)
+ let length = ? key.toBytes(res)
if length > 0:
- result.setLen(length)
+ res.setLen(length)
+ ok(res)
else:
- raise newException(RsaKeyIncorrectError, "Incorrect private key")
+ err(RsaKeyIncorrectError)
-proc getBytes*(sig: RsaSignature): seq[byte] =
+proc getBytes*(sig: RsaSignature): RsaResult[seq[byte]] =
## Serialize RSA signature ``sig`` to raw binary form and return it.
- doAssert(not isNil(sig))
- result = newSeq[byte](4096)
- let length = sig.toBytes(result)
+ if isNil(sig):
+ return err(RsaSignatureError)
+ var res = newSeq[byte](4096)
+ let length = ? sig.toBytes(res)
if length > 0:
- result.setLen(length)
+ res.setLen(length)
+ ok(res)
else:
- raise newException(RsaSignatureError, "Incorrect signature")
+ err(RsaSignatureError)
proc init*(key: var RsaPrivateKey, data: openarray[byte]): Result[void, Asn1Error] =
## Initialize RSA private key ``key`` from ASN.1 DER binary representation
@@ -560,29 +587,32 @@ proc init*[T: RsaPKI](sospk: var T, data: string): Result[void, Asn1Error] {.inl
## Procedure returns ``Result[void, Asn1Status]``.
sospk.init(fromHex(data))
-proc init*(t: typedesc[RsaPrivateKey], data: openarray[byte]): RsaPrivateKey =
+proc init*(t: typedesc[RsaPrivateKey], data: openarray[byte]): RsaResult[RsaPrivateKey] =
## Initialize RSA private key from ASN.1 DER binary representation ``data``
## and return constructed object.
- let res = result.init(data)
- if res.isErr:
- raise newException(RsaKeyIncorrectError,
- "Incorrect private key (" & $res.error & ")")
+ var res: RsaPrivateKey
+ if res.init(data).isErr:
+ err(RsaKeyIncorrectError)
+ else:
+ ok(res)
-proc init*(t: typedesc[RsaPublicKey], data: openarray[byte]): RsaPublicKey =
+proc init*(t: typedesc[RsaPublicKey], data: openarray[byte]): RsaResult[RsaPublicKey] =
## Initialize RSA public key from ASN.1 DER binary representation ``data``
## and return constructed object.
- let res = result.init(data)
- if res.isErr:
- raise newException(RsaKeyIncorrectError,
- "Incorrect public key (" & $res.error & ")")
+ var res: RsaPublicKey
+ if res.init(data).isErr:
+ err(RsaKeyIncorrectError)
+ else:
+ ok(res)
-proc init*(t: typedesc[RsaSignature], data: openarray[byte]): RsaSignature =
+proc init*(t: typedesc[RsaSignature], data: openarray[byte]): RsaResult[RsaSignature] =
## Initialize RSA signature from raw binary representation ``data`` and
## return constructed object.
- let res = result.init(data)
- if res.isErr:
- raise newException(RsaKeyIncorrectError,
- "Incorrect signature (" & $res.error & ")")
+ var res: RsaSignature
+ if res.init(data).isErr:
+ err(RsaSignatureError)
+ else:
+ ok(res)
proc init*[T: RsaPKI](t: typedesc[T], data: string): T {.inline.} =
## Initialize RSA `private key`, `public key` or `signature` from hexadecimal
@@ -714,15 +744,17 @@ proc `==`*(a, b: RsaPublicKey): bool =
result = r1 and r2
proc sign*[T: byte|char](key: RsaPrivateKey,
- message: openarray[T]): RsaSignature {.gcsafe.} =
+ message: openarray[T]): RsaResult[RsaSignature] {.gcsafe.} =
## Get RSA PKCS1.5 signature of data ``message`` using SHA256 and private
## key ``key``.
- doAssert(not isNil(key))
+ if isNil(key):
+ return err(RsaKeyIncorrectError)
+
var hc: BrHashCompatContext
var hash: array[32, byte]
let impl = BrRsaPkcs1SignGetDefault()
- result = new RsaSignature
- result.buffer = newSeq[byte]((key.seck.nBitlen + 7) shr 3)
+ var res = new RsaSignature
+ res.buffer = newSeq[byte]((key.seck.nBitlen + 7) shr 3)
var kv = addr sha256Vtable
kv.init(addr hc.vtable)
if len(message) > 0:
@@ -731,11 +763,13 @@ proc sign*[T: byte|char](key: RsaPrivateKey,
kv.update(addr hc.vtable, nil, 0)
kv.output(addr hc.vtable, addr hash[0])
var oid = RsaOidSha256
- let res = impl(cast[ptr cuchar](addr oid[0]),
+ let implRes = impl(cast[ptr cuchar](addr oid[0]),
cast[ptr cuchar](addr hash[0]), len(hash),
- addr key.seck, cast[ptr cuchar](addr result.buffer[0]))
- if res == 0:
- raise newException(RsaSignatureError, "Signature generation error")
+ addr key.seck, cast[ptr cuchar](addr res.buffer[0]))
+ if implRes == 0:
+ err(RsaSignatureError)
+ else:
+ ok(res)
proc verify*[T: byte|char](sig: RsaSignature, message: openarray[T],
pubkey: RsaPublicKey): bool {.inline.} =
diff --git a/libp2p/crypto/secp.nim b/libp2p/crypto/secp.nim
index d1a547564..71164035f 100644
--- a/libp2p/crypto/secp.nim
+++ b/libp2p/crypto/secp.nim
@@ -6,8 +6,15 @@
## at your option.
## This file may not be copied, modified, or distributed except according to
## those terms.
-import secp256k1 as s, stew/byteutils, nimcrypto/hash, nimcrypto/sha2
+
+{.push raises: [Defect].}
+
+import secp256k1, stew/byteutils, nimcrypto/hash, nimcrypto/sha2
export sha2
+import stew/results
+
+export results
+export secp256k1
const
SkRawPrivateKeySize* = 256 div 8
@@ -18,169 +25,125 @@ const
## Size of public key in octets (bytes)
type
- SkPublicKey* = distinct s.SkPublicKey
- SkPrivateKey* = distinct s.SkSecretKey
- SkKeyPair* = distinct s.SkKeyPair
- SkSignature* = distinct s.SkSignature
+ SkPrivateKey* = SkSecretKey
- Secp256k1Error* = object of CatchableError
- ## Exceptions generated by `libsecp256k1`
+template pubkey*(v: SkKeyPair): SkPublicKey = SkPublicKey(SkKeyPair(v).pubkey)
+template seckey*(v: SkKeyPair): SkPrivateKey = SkPrivateKey(SkKeyPair(v).seckey)
-template toException(v: cstring): (ref Secp256k1Error) =
- (ref Secp256k1Error)(msg: $v)
-
-template pubkey*(v: SkKeyPair): SkPublicKey = SkPublicKey(s.SkKeyPair(v).pubkey)
-template seckey*(v: SkKeyPair): SkPrivateKey = SkPrivateKey(s.SkKeyPair(v).seckey)
-
-proc init*(key: var SkPrivateKey, data: openarray[byte]): bool {.raises: [Defect].} =
+proc init*(key: var SkPrivateKey, data: openarray[byte]): SkResult[void] =
## Initialize Secp256k1 `private key` ``key`` from raw binary
## representation ``data``.
- ##
- ## Procedure returns ``true`` on success.
- if (let v = SkSecretKey.fromRaw(data); v.isOk):
- key = SkPrivateKey(v[])
- return true
+ key = ? SkSecretKey.fromRaw(data)
+ ok()
-proc init*(key: var SkPrivateKey, data: string): bool {.raises: [Defect].} =
+proc init*(key: var SkPrivateKey, data: string): SkResult[void] =
## Initialize Secp256k1 `private key` ``key`` from hexadecimal string
## representation ``data``.
- ##
- ## Procedure returns ``true`` on success.
- try:
- key = SkPrivateKey(SkSecretKey.fromHex(data).tryGet())
- return true
- except Secp256k1Error:
- discard
+ key = ? SkSecretKey.fromHex(data)
+ ok()
-proc init*(key: var SkPublicKey, data: openarray[byte]): bool {.raises: [Defect].} =
+proc init*(key: var SkPublicKey, data: openarray[byte]): SkResult[void] =
## Initialize Secp256k1 `public key` ``key`` from raw binary
## representation ``data``.
- ##
- ## Procedure returns ``true`` on success.
- try:
- key = SkPublicKey(s.SkPublicKey.fromRaw(data).tryGet())
- return true
- except Secp256k1Error:
- discard
+ key = ? SkPublicKey.fromRaw(data)
+ ok()
-proc init*(key: var SkPublicKey, data: string): bool {.raises: [Defect].} =
+proc init*(key: var SkPublicKey, data: string): SkResult[void] =
## Initialize Secp256k1 `public key` ``key`` from hexadecimal string
## representation ``data``.
- ##
- ## Procedure returns ``true`` on success.
- try:
- key = SkPublicKey(s.SkPublicKey.fromHex(data).tryGet())
- return true
- except Secp256k1Error:
- discard
+ key = ? SkPublicKey.fromHex(data)
+ ok()
-proc init*(sig: var SkSignature, data: openarray[byte]): bool {.raises: [Defect].} =
+proc init*(sig: var SkSignature, data: openarray[byte]): SkResult[void] =
## Initialize Secp256k1 `signature` ``sig`` from raw binary
## representation ``data``.
- ##
- ## Procedure returns ``true`` on success.
- try:
- sig = SkSignature(s.SkSignature.fromDer(data).tryGet())
- return true
- except Secp256k1Error:
- discard
+ sig = ? SkSignature.fromDer(data)
+ ok()
-proc init*(sig: var SkSignature, data: string): bool {.raises: [Defect].} =
+proc init*(sig: var SkSignature, data: string): SkResult[void] =
## Initialize Secp256k1 `signature` ``sig`` from hexadecimal string
## representation ``data``.
- ##
- ## Procedure returns ``true`` on success.
# TODO DER vs raw here is fishy
var buffer: seq[byte]
try:
buffer = hexToSeqByte(data)
except ValueError:
- return false
- result = init(sig, buffer)
+ return err("Hex to bytes failed")
+ init(sig, buffer)
-proc init*(t: typedesc[SkPrivateKey],
- data: openarray[byte]): SkPrivateKey {.raises: [Defect, Secp256k1Error].} =
+proc init*(t: typedesc[SkPrivateKey], data: openarray[byte]): SkResult[SkPrivateKey] =
## Initialize Secp256k1 `private key` from raw binary
## representation ``data``.
##
## Procedure returns `private key` on success.
- SkPrivateKey(s.SkSecretKey.fromRaw(data).tryGet())
+ SkSecretKey.fromRaw(data)
-proc init*(t: typedesc[SkPrivateKey],
- data: string): SkPrivateKey {.raises: [Defect, Secp256k1Error].} =
+proc init*(t: typedesc[SkPrivateKey], data: string): SkResult[SkPrivateKey] =
## Initialize Secp256k1 `private key` from hexadecimal string
## representation ``data``.
##
## Procedure returns `private key` on success.
- s.SkSecretKey.fromHex(data).tryGet()
+ SkSecretKey.fromHex(data)
-proc init*(t: typedesc[SkPublicKey],
- data: openarray[byte]): SkPublicKey {.raises: [Defect, Secp256k1Error].} =
+proc init*(t: typedesc[SkPublicKey], data: openarray[byte]): SkResult[SkPublicKey] =
## Initialize Secp256k1 `public key` from raw binary
## representation ``data``.
##
## Procedure returns `public key` on success.
- if not init(result, data):
- raise newException(Secp256k1Error, "Incorrect binary form")
+ var key: SkPublicKey
+ key.init(data) and ok(key)
-proc init*(t: typedesc[SkPublicKey],
- data: string): SkPublicKey {.raises: [Defect, Secp256k1Error].} =
+proc init*(t: typedesc[SkPublicKey], data: string): SkResult[SkPublicKey] =
## Initialize Secp256k1 `public key` from hexadecimal string
## representation ``data``.
##
## Procedure returns `public key` on success.
- if not init(result, data):
- raise newException(Secp256k1Error, "Incorrect binary form")
+ var key: SkPublicKey
+ key.init(data) and ok(key)
-proc init*(t: typedesc[SkSignature],
- data: openarray[byte]): SkSignature {.raises: [Defect, Secp256k1Error].} =
+proc init*(t: typedesc[SkSignature], data: openarray[byte]): SkResult[SkSignature] =
## Initialize Secp256k1 `signature` from raw binary
## representation ``data``.
##
## Procedure returns `signature` on success.
- if not init(result, data):
- raise newException(Secp256k1Error, "Incorrect binary form")
+ var sig: SkSignature
+ sig.init(data) and ok(sig)
-proc init*(t: typedesc[SkSignature],
- data: string): SkSignature {.raises: [Defect, Secp256k1Error].} =
+proc init*(t: typedesc[SkSignature], data: string): SkResult[SkSignature] =
## Initialize Secp256k1 `signature` from hexadecimal string
## representation ``data``.
##
## Procedure returns `signature` on success.
- if not init(result, data):
- raise newException(Secp256k1Error, "Incorrect binary form")
+ var sig: SkSignature
+ sig.init(data) and ok(sig)
-proc getKey*(key: SkPrivateKey): SkPublicKey {.raises: [Defect, Secp256k1Error].} =
+proc getKey*(key: SkPrivateKey): SkResult[SkPublicKey] =
## Calculate and return Secp256k1 `public key` from `private key` ``key``.
- SkPublicKey(s.SkSecretKey(key).toPublicKey().tryGet())
+ key.toPublicKey()
-proc random*(t: typedesc[SkPrivateKey]): SkPrivateKey =
- ## Generates new random private key.
- SkPrivateKey(s.SkSecretKey.random().tryGet())
-
-proc random*(t: typedesc[SkKeyPair]): SkKeyPair {.inline.} =
- ## Generates new random key pair.
- SkKeyPair(s.SkKeyPair.random().tryGet())
-
-proc toBytes*(key: SkPrivateKey, data: var openarray[byte]): int =
+proc toBytes*(key: SkPrivateKey, data: var openarray[byte]): SkResult[int] =
## Serialize Secp256k1 `private key` ``key`` to raw binary form and store it
## to ``data``.
##
## Procedure returns number of bytes (octets) needed to store
## Secp256k1 private key.
- result = SkRawPrivateKeySize
if len(data) >= SkRawPrivateKeySize:
- data[0..= SkRawPublicKeySize:
- data[0..= 0:
+ if MultiHash.decode(data, mh).isOk:
vb.writeSeq(data)
result = true
except:
@@ -151,7 +151,7 @@ proc p2pBtS(vb: var VBuffer, s: var string): bool =
var address = newSeq[byte]()
if vb.readSeq(address) > 0:
var mh: MultiHash
- if MultiHash.decode(address, mh) >= 0:
+ if MultiHash.decode(address, mh).isOk:
s = Base58.encode(address)
result = true
@@ -160,7 +160,7 @@ proc p2pVB(vb: var VBuffer): bool =
var address = newSeq[byte]()
if vb.readSeq(address) > 0:
var mh: MultiHash
- if MultiHash.decode(address, mh) >= 0:
+ if MultiHash.decode(address, mh).isOk:
result = true
proc onionStB(s: string, vb: var VBuffer): bool =
@@ -426,12 +426,12 @@ const
proc trimRight(s: string, ch: char): string =
## Consume trailing characters ``ch`` from string ``s`` and return result.
var m = 0
- for i in countdown(len(s) - 1, 0):
+ for i in countdown(s.high, 0):
if s[i] == ch:
inc(m)
else:
break
- result = s[0..(len(s) - 1 - m)]
+ result = s[0..(s.high - m)]
proc shcopy*(m1: var MultiAddress, m2: MultiAddress) =
shallowCopy(m1.data.buffer, m2.data.buffer)
diff --git a/libp2p/multibase.nim b/libp2p/multibase.nim
index fb7117562..6fc888673 100644
--- a/libp2p/multibase.nim
+++ b/libp2p/multibase.nim
@@ -392,7 +392,7 @@ proc encode*(mbtype: typedesc[MultiBase], encoding: string,
if isNil(mb.encr) or isNil(mb.encl):
return MultibaseStatus.NotSupported
if len(outbytes) > 1:
- result = mb.encr(inbytes, outbytes.toOpenArray(1, len(outbytes) - 1),
+ result = mb.encr(inbytes, outbytes.toOpenArray(1, outbytes.high),
outlen)
if result == MultiBaseStatus.Overrun:
outlen += 1
@@ -452,7 +452,7 @@ proc encode*(mbtype: typedesc[MultiBase], encoding: string,
if length > 0:
buffer = newString(mb.encl(length) + 1)
var outlen = 0
- let res = mb.encr(inbytes, buffer.toOpenArray(1, len(buffer) - 1), outlen)
+ let res = mb.encr(inbytes, buffer.toOpenArray(1, buffer.high), outlen)
if res != MultiBaseStatus.Success:
raise newException(MultiBaseError, "Encoding error [" & $res & "]")
buffer.setLen(outlen + 1)
diff --git a/libp2p/multicodec.nim b/libp2p/multicodec.nim
index bace64863..33ef889bb 100644
--- a/libp2p/multicodec.nim
+++ b/libp2p/multicodec.nim
@@ -8,8 +8,13 @@
## those terms.
## This module implements MultiCodec.
+
+{.push raises: [Defect].}
+
import tables, hashes
import varint, vbuffer
+import stew/results
+export results
{.deadCodeElim: on.}
@@ -230,7 +235,8 @@ const MultiCodecList = [
type
MultiCodec* = distinct int
- MultiCodecError* = object of CatchableError
+ MultiCodecError* = enum
+ MultiCodecNotSupported
const
InvalidMultiCodec* = MultiCodec(-1)
@@ -251,37 +257,32 @@ const
proc multiCodec*(name: string): MultiCodec {.compileTime.} =
## Generate MultiCodec from string ``name`` at compile time.
- var code = NameCodecs.getOrDefault(name, -1)
- if code == -1:
- raise newException(MultiCodecError,
- "MultiCodec `" & name & "` not supported!")
- result = MultiCodec(code)
+ let code = NameCodecs.getOrDefault(name, -1)
+ doAssert(code != -1)
+ MultiCodec(code)
proc multiCodec*(code: int): MultiCodec {.compileTime.} =
## Generate MultiCodec from integer ``code`` at compile time.
- var name = CodeCodecs.getOrDefault(code, "")
- if name == "":
- raise newException(MultiCodecError,
- "MultiCodec with code " & $code & " not supported!")
- result = MultiCodec(code)
+ let name = CodeCodecs.getOrDefault(code, "")
+ doAssert(name != "")
+ MultiCodec(code)
proc `$`*(mc: MultiCodec): string =
## Returns string representation of MultiCodec ``mc``.
- result = CodeCodecs.getOrDefault(int(mc), "")
- if result == "":
- raise newException(MultiCodecError,
- "MultiCodec with code " & $int(mc) & " not supported!")
+ let name = CodeCodecs.getOrDefault(int(mc), "")
+ doAssert(name != "")
+ name
proc `==`*(mc: MultiCodec, name: string): bool {.inline.} =
## Compares MultiCodec ``mc`` with string ``name``.
- var mcname = CodeCodecs.getOrDefault(int(mc), "")
+ let mcname = CodeCodecs.getOrDefault(int(mc), "")
if mcname == "":
return false
result = (mcname == name)
proc `==`*(mc: MultiCodec, code: int): bool {.inline.} =
## Compares MultiCodec ``mc`` with integer ``code``.
- result = (int(mc) == code)
+ (int(mc) == code)
proc `==`*(a, b: MultiCodec): bool =
## Returns ``true`` if MultiCodecs ``a`` and ``b`` are equal.
@@ -293,13 +294,13 @@ proc `!=`*(a, b: MultiCodec): bool =
proc hash*(m: MultiCodec): Hash {.inline.} =
## Hash procedure for tables.
- result = hash(int(m))
+ hash(int(m))
proc codec*(mt: typedesc[MultiCodec], name: string): MultiCodec {.inline.} =
## Return MultiCodec from string representation ``name``.
## If ``name`` is not valid multicodec name, then ``InvalidMultiCodec`` will
## be returned.
- result = MultiCodec(NameCodecs.getOrDefault(name, -1))
+ MultiCodec(NameCodecs.getOrDefault(name, -1))
proc codec*(mt: typedesc[MultiCodec], code: int): MultiCodec {.inline.} =
## Return MultiCodec from integer representation ``code``.
@@ -307,9 +308,9 @@ proc codec*(mt: typedesc[MultiCodec], code: int): MultiCodec {.inline.} =
## be returned.
let res = CodeCodecs.getOrDefault(code, "")
if res == "":
- result = InvalidMultiCodec
+ InvalidMultiCodec
else:
- result = MultiCodec(code)
+ MultiCodec(code)
proc write*(vb: var VBuffer, mc: MultiCodec) {.inline.} =
## Write MultiCodec to buffer ``vb``.
diff --git a/libp2p/multihash.nim b/libp2p/multihash.nim
index df69167b3..a0845a6bf 100644
--- a/libp2p/multihash.nim
+++ b/libp2p/multihash.nim
@@ -20,19 +20,29 @@
## Hashes which are not yet supported
## 1. SKEIN
## 2. MURMUR
+
+{.push raises: [Defect].}
+
import tables
import nimcrypto/[sha, sha2, keccak, blake2, hash, utils]
import varint, vbuffer, multicodec, multibase
import stew/base58
+import stew/results
+export results
# This is workaround for Nim `import` bug.
export sha, sha2, keccak, blake2, hash, utils
const
MaxHashSize* = 128
+ ErrIncorrectName = "Incorrect hash name"
+ ErrNotSupported = "Hash not supported"
+ ErrWrongDigestSize = "Incorrect digest size"
+ ErrDecodeError = "Decoding error from bytes"
+ ErrParseError = "Parse error fromHex"
type
MHashCoderProc* = proc(data: openarray[byte],
- output: var openarray[byte]) {.nimcall, gcsafe.}
+ output: var openarray[byte]) {.nimcall, gcsafe, raises: [Defect].}
MHash* = object
mcodec*: MultiCodec
size*: int
@@ -44,7 +54,7 @@ type
size*: int
dpos*: int
- MultiHashError* = object of CatchableError
+ MhResult*[T] = Result[T, cstring]
proc identhash(data: openarray[byte], output: var openarray[byte]) =
if len(output) > 0:
@@ -345,78 +355,87 @@ proc digestImplWithoutHash(hash: MHash, data: openarray[byte]): MultiHash =
result.data.finish()
proc digest*(mhtype: typedesc[MultiHash], hashname: string,
- data: openarray[byte]): MultiHash {.inline.} =
+ data: openarray[byte]): MhResult[MultiHash] {.inline.} =
## Perform digest calculation using hash algorithm with name ``hashname`` on
## data array ``data``.
let mc = MultiCodec.codec(hashname)
if mc == InvalidMultiCodec:
- raise newException(MultihashError, "Incorrect hash name")
- let hash = CodeHashes.getOrDefault(mc)
- if isNil(hash.coder):
- raise newException(MultihashError, "Hash not supported")
- result = digestImplWithHash(hash, data)
+ err(ErrIncorrectName)
+ else:
+ let hash = CodeHashes.getOrDefault(mc)
+ if isNil(hash.coder):
+ err(ErrNotSupported)
+ else:
+ ok(digestImplWithHash(hash, data))
proc digest*(mhtype: typedesc[MultiHash], hashcode: int,
- data: openarray[byte]): MultiHash {.inline.} =
+ data: openarray[byte]): MhResult[MultiHash] {.inline.} =
## Perform digest calculation using hash algorithm with code ``hashcode`` on
## data array ``data``.
let hash = CodeHashes.getOrDefault(hashcode)
if isNil(hash.coder):
- raise newException(MultihashError, "Hash not supported")
- result = digestImplWithHash(hash, data)
+ err(ErrNotSupported)
+ else:
+ ok(digestImplWithHash(hash, data))
proc init*[T](mhtype: typedesc[MultiHash], hashname: string,
- mdigest: MDigest[T]): MultiHash {.inline.} =
+ mdigest: MDigest[T]): MhResult[MultiHash] {.inline.} =
## Create MultiHash from nimcrypto's `MDigest` object and hash algorithm name
## ``hashname``.
let mc = MultiCodec.codec(hashname)
if mc == InvalidMultiCodec:
- raise newException(MultihashError, "Incorrect hash name")
- let hash = CodeHashes.getOrDefault(mc)
- if isNil(hash.coder):
- raise newException(MultihashError, "Hash not supported")
- if hash.size != len(mdigest.data):
- raise newException(MultiHashError, "Incorrect MDigest[T] size")
- result = digestImplWithoutHash(hash, mdigest.data)
+ err(ErrIncorrectName)
+ else:
+ let hash = CodeHashes.getOrDefault(mc)
+ if isNil(hash.coder):
+ err(ErrNotSupported)
+ elif hash.size != len(mdigest.data):
+ err(ErrWrongDigestSize)
+ else:
+ ok(digestImplWithoutHash(hash, mdigest.data))
proc init*[T](mhtype: typedesc[MultiHash], hashcode: MultiCodec,
- mdigest: MDigest[T]): MultiHash {.inline.} =
+ mdigest: MDigest[T]): MhResult[MultiHash] {.inline.} =
## Create MultiHash from nimcrypto's `MDigest` and hash algorithm code
## ``hashcode``.
let hash = CodeHashes.getOrDefault(hashcode)
if isNil(hash.coder):
- raise newException(MultihashError, "Hash not supported")
- if (hash.size != 0) and (hash.size != len(mdigest.data)):
- raise newException(MultiHashError, "Incorrect MDigest[T] size")
- result = digestImplWithoutHash(hash, mdigest.data)
+ err(ErrNotSupported)
+ elif (hash.size != 0) and (hash.size != len(mdigest.data)):
+ err(ErrWrongDigestSize)
+ else:
+ ok(digestImplWithoutHash(hash, mdigest.data))
proc init*(mhtype: typedesc[MultiHash], hashname: string,
- bdigest: openarray[byte]): MultiHash {.inline.} =
+ bdigest: openarray[byte]): MhResult[MultiHash] {.inline.} =
## Create MultiHash from array of bytes ``bdigest`` and hash algorithm code
## ``hashcode``.
let mc = MultiCodec.codec(hashname)
if mc == InvalidMultiCodec:
- raise newException(MultihashError, "Incorrect hash name")
- let hash = CodeHashes.getOrDefault(mc)
- if isNil(hash.coder):
- raise newException(MultihashError, "Hash not supported")
- if (hash.size != 0) and (hash.size != len(bdigest)):
- raise newException(MultiHashError, "Incorrect bdigest size")
- result = digestImplWithoutHash(hash, bdigest)
+ err(ErrIncorrectName)
+ else:
+ let hash = CodeHashes.getOrDefault(mc)
+ if isNil(hash.coder):
+ err(ErrNotSupported)
+ elif (hash.size != 0) and (hash.size != len(bdigest)):
+ err(ErrWrongDigestSize)
+ else:
+ ok(digestImplWithoutHash(hash, bdigest))
proc init*(mhtype: typedesc[MultiHash], hashcode: MultiCodec,
- bdigest: openarray[byte]): MultiHash {.inline.} =
+ bdigest: openarray[byte]): MhResult[MultiHash] {.inline.} =
## Create MultiHash from array of bytes ``bdigest`` and hash algorithm code
## ``hashcode``.
let hash = CodeHashes.getOrDefault(hashcode)
if isNil(hash.coder):
- raise newException(MultihashError, "Hash not supported")
- if (hash.size != 0) and (hash.size != len(bdigest)):
- raise newException(MultiHashError, "Incorrect bdigest size")
- result = digestImplWithoutHash(hash, bdigest)
+ err(ErrNotSupported)
+ elif (hash.size != 0) and (hash.size != len(bdigest)):
+ err(ErrWrongDigestSize)
+ else:
+ ok(digestImplWithoutHash(hash, bdigest))
proc decode*(mhtype: typedesc[MultiHash], data: openarray[byte],
- mhash: var MultiHash): int =
+ mhash: var MultiHash): MhResult[int] =
## Decode MultiHash value from array of bytes ``data``.
##
## On success decoded MultiHash will be stored into ``mhash`` and number of
@@ -426,31 +445,39 @@ proc decode*(mhtype: typedesc[MultiHash], data: openarray[byte],
var code, size: uint64
var res, dpos: int
if len(data) < 2:
- return -1
+ return err(ErrDecodeError)
+
var vb = initVBuffer(data)
if vb.isEmpty():
- return -1
+ return err(ErrDecodeError)
+
res = vb.readVarint(code)
if res == -1:
- return -1
+ return err(ErrDecodeError)
+
dpos += res
res = vb.readVarint(size)
if res == -1:
- return -1
+ return err(ErrDecodeError)
+
dpos += res
if size > 0x7FFF_FFFF'u64:
- return -1
+ return err(ErrDecodeError)
+
let hash = CodeHashes.getOrDefault(MultiCodec(code))
if isNil(hash.coder):
- return -1
+ return err(ErrDecodeError)
+
if (hash.size != 0) and (hash.size != int(size)):
- return -1
+ return err(ErrDecodeError)
+
if not vb.isEnough(int(size)):
- return -1
- mhash = MultiHash.init(MultiCodec(code),
+ return err(ErrDecodeError)
+
+ mhash = ? MultiHash.init(MultiCodec(code),
vb.buffer.toOpenArray(vb.offset,
vb.offset + int(size) - 1))
- result = vb.offset + int(size)
+ ok(vb.offset + int(size))
proc validate*(mhtype: typedesc[MultiHash], data: openarray[byte]): bool =
## Returns ``true`` if array of bytes ``data`` has correct MultiHash inside.
@@ -458,7 +485,7 @@ proc validate*(mhtype: typedesc[MultiHash], data: openarray[byte]): bool =
var res: VarintStatus
if len(data) < 2:
return false
- let last = len(data) - 1
+ let last = data.high
var offset = 0
var length = 0
res = LP.getUVarint(data.toOpenArray(offset, last), length, code)
@@ -483,15 +510,20 @@ proc validate*(mhtype: typedesc[MultiHash], data: openarray[byte]): bool =
result = true
proc init*(mhtype: typedesc[MultiHash],
- data: openarray[byte]): MultiHash {.inline.} =
+ data: openarray[byte]): MhResult[MultiHash] {.inline.} =
## Create MultiHash from bytes array ``data``.
- if MultiHash.decode(data, result) == -1:
- raise newException(MultihashError, "Incorrect MultiHash binary format")
+ var hash: MultiHash
+ discard ? MultiHash.decode(data, hash)
+ ok(hash)
-proc init*(mhtype: typedesc[MultiHash], data: string): MultiHash {.inline.} =
+proc init*(mhtype: typedesc[MultiHash], data: string): MhResult[MultiHash] {.inline.} =
## Create MultiHash from hexadecimal string representation ``data``.
- if MultiHash.decode(fromHex(data), result) == -1:
- raise newException(MultihashError, "Incorrect MultiHash binary format")
+ var hash: MultiHash
+ try:
+ discard ? MultiHash.decode(fromHex(data), hash)
+ ok(hash)
+ except ValueError:
+ err(ErrParseError)
proc init58*(mhtype: typedesc[MultiHash],
data: string): MultiHash {.inline.} =
@@ -518,7 +550,7 @@ proc `==`*[T](mh: MultiHash, mdigest: MDigest[T]): bool =
if len(mdigest.data) != mh.size:
return false
result = cmp(mh.data.buffer.toOpenArray(mh.dpos, mh.dpos + mh.size - 1),
- mdigest.data.toOpenArray(0, len(mdigest.data) - 1))
+ mdigest.data.toOpenArray(0, mdigest.data.high))
proc `==`*[T](mdigest: MDigest[T], mh: MultiHash): bool {.inline.} =
## Compares MultiHash with nimcrypto's MDigest[T], returns ``true`` if
diff --git a/libp2p/peer.nim b/libp2p/peer.nim
index 4f49983df..a8d90af87 100644
--- a/libp2p/peer.nim
+++ b/libp2p/peer.nim
@@ -91,7 +91,7 @@ proc hasPublicKey*(pid: PeerID): bool =
## Returns ``true`` if ``pid`` is small enough to hold public key inside.
if len(pid.data) > 0:
var mh: MultiHash
- if MultiHash.decode(pid.data, mh) > 0:
+ if MultiHash.decode(pid.data, mh).isOk:
if mh.mcodec == multiCodec("identity"):
result = true
@@ -102,7 +102,7 @@ proc extractPublicKey*(pid: PeerID, pubkey: var PublicKey): bool =
## Returns ``false`` otherwise.
var mh: MultiHash
if len(pid.data) > 0:
- if MultiHash.decode(pid.data, mh) > 0:
+ if MultiHash.decode(pid.data, mh).isOk:
if mh.mcodec == multiCodec("identity"):
let length = len(mh.data.buffer)
result = pubkey.init(mh.data.buffer.toOpenArray(mh.dpos, length - 1))
@@ -117,7 +117,7 @@ proc `$`*(pid: PeerID): string =
for i in 0..<2:
result.add(spid[i])
result.add("*")
- for i in (len(spid) - 6)..(len(spid) - 1):
+ for i in (len(spid) - 6)..spid.high:
result.add(spid[i])
proc init*(pid: var PeerID, data: openarray[byte]): bool =
@@ -155,17 +155,17 @@ proc init*(t: typedesc[PeerID], data: string): PeerID {.inline.} =
proc init*(t: typedesc[PeerID], pubkey: PublicKey): PeerID =
## Create new peer id from public key ``pubkey``.
- var pubraw = pubkey.getBytes()
+ var pubraw = pubkey.getBytes().tryGet()
var mh: MultiHash
if len(pubraw) <= maxInlineKeyLength:
- mh = MultiHash.digest("identity", pubraw)
+ mh = MultiHash.digest("identity", pubraw).tryGet()
else:
- mh = MultiHash.digest("sha2-256", pubraw)
+ mh = MultiHash.digest("sha2-256", pubraw).tryGet()
result.data = mh.data.buffer
proc init*(t: typedesc[PeerID], seckey: PrivateKey): PeerID {.inline.} =
## Create new peer id from private key ``seckey``.
- result = PeerID.init(seckey.getKey())
+ result = PeerID.init(seckey.getKey().tryGet())
proc match*(pid: PeerID, pubkey: PublicKey): bool {.inline.} =
## Returns ``true`` if ``pid`` matches public key ``pubkey``.
diff --git a/libp2p/peerinfo.nim b/libp2p/peerinfo.nim
index bad3f4466..2868ed0d5 100644
--- a/libp2p/peerinfo.nim
+++ b/libp2p/peerinfo.nim
@@ -118,4 +118,4 @@ proc publicKey*(p: PeerInfo): Option[PublicKey] {.inline.} =
elif p.key.isSome:
result = p.key
else:
- result = some(p.privateKey.getKey())
+ result = some(p.privateKey.getKey().tryGet())
diff --git a/libp2p/protocols/identify.nim b/libp2p/protocols/identify.nim
index d4a85e18c..60e1f36ec 100644
--- a/libp2p/protocols/identify.nim
+++ b/libp2p/protocols/identify.nim
@@ -47,7 +47,7 @@ type
proc encodeMsg*(peerInfo: PeerInfo, observedAddrs: Multiaddress): ProtoBuffer =
result = initProtoBuffer()
- result.write(initProtoField(1, peerInfo.publicKey.get().getBytes()))
+ result.write(initProtoField(1, peerInfo.publicKey.get().getBytes().tryGet()))
for ma in peerInfo.addrs:
result.write(initProtoField(2, ma.data.buffer))
diff --git a/libp2p/protocols/pubsub/rpc/message.nim b/libp2p/protocols/pubsub/rpc/message.nim
index 11109eab0..61ef194ac 100644
--- a/libp2p/protocols/pubsub/rpc/message.nim
+++ b/libp2p/protocols/pubsub/rpc/message.nim
@@ -33,7 +33,7 @@ proc sign*(msg: Message, p: PeerInfo): Message {.gcsafe.} =
if buff.buffer.len > 0:
result = msg
result.signature = p.privateKey.
- sign(cast[seq[byte]](PubSubPrefix) & buff.buffer).
+ sign(cast[seq[byte]](PubSubPrefix) & buff.buffer).tryGet().
getBytes()
proc verify*(m: Message, p: PeerInfo): bool =
@@ -57,7 +57,7 @@ proc newMessage*(p: PeerInfo,
sign: bool = true): Message {.gcsafe.} =
var seqno: seq[byte] = newSeq[byte](20)
if p.publicKey.isSome and randomBytes(addr seqno[0], 20) > 0:
- var key: seq[byte] = p.publicKey.get().getBytes()
+ var key: seq[byte] = p.publicKey.get().getBytes().tryGet()
result = Message(fromPeer: p.peerId.getBytes(),
data: data,
diff --git a/libp2p/protocols/secure/noise.nim b/libp2p/protocols/secure/noise.nim
index 46d3d69f0..cdbad727b 100644
--- a/libp2p/protocols/secure/noise.nim
+++ b/libp2p/protocols/secure/noise.nim
@@ -470,7 +470,8 @@ method handshake*(p: Noise, conn: Connection, initiator: bool = false): Future[S
# https://github.com/libp2p/specs/tree/master/noise#libp2p-data-in-handshake-messages
let
- signedPayload = p.localPrivateKey.sign(PayloadString.toBytes & p.noisePublicKey.getBytes)
+ signedPayload = p.localPrivateKey.sign(
+ PayloadString.toBytes & p.noisePublicKey.getBytes).tryGet()
var
libp2pProof = initProtoBuffer()
@@ -532,7 +533,7 @@ proc newNoise*(privateKey: PrivateKey; outgoing: bool = true; commonPrologue: se
new result
result.outgoing = outgoing
result.localPrivateKey = privateKey
- result.localPublicKey = privateKey.getKey()
+ result.localPublicKey = privateKey.getKey().tryGet()
discard randomBytes(result.noisePrivateKey)
result.noisePublicKey = result.noisePrivateKey.public()
result.commonPrologue = commonPrologue
diff --git a/libp2p/protocols/secure/secio.nim b/libp2p/protocols/secure/secio.nim
index da5735346..d5fa7421a 100644
--- a/libp2p/protocols/secure/secio.nim
+++ b/libp2p/protocols/secure/secio.nim
@@ -166,7 +166,7 @@ proc macCheckAndDecode(sconn: SecioConn, data: var seq[byte]): bool =
if not equalMem(addr data[mark], addr macData[0], macsize):
trace "Invalid MAC",
calculated = toHex(macData.toOpenArray(0, macsize - 1)),
- stored = toHex(data.toOpenArray(mark, len(data) - 1))
+ stored = toHex(data.toOpenArray(mark, data.high))
return false
sconn.readerCoder.decrypt(data.toOpenArray(0, mark - 1),
@@ -303,7 +303,7 @@ method handshake*(s: Secio, conn: Connection, initiator: bool = false): Future[S
remoteHashes: string
remotePeerId: PeerID
localPeerId: PeerID
- localBytesPubkey = s.localPublicKey.getBytes()
+ localBytesPubkey = s.localPublicKey.getBytes().tryGet()
if randomBytes(localNonce) != SecioNonceSize:
raise (ref SecioError)(msg: "Could not generate random data")
@@ -341,7 +341,7 @@ method handshake*(s: Secio, conn: Connection, initiator: bool = false): Future[S
# TODO: PeerID check against supplied PeerID
let order = getOrder(remoteBytesPubkey, localNonce, localBytesPubkey,
- remoteNonce)
+ remoteNonce).tryGet()
trace "Remote proposal", schemes = remoteExchanges, ciphers = remoteCiphers,
hashes = remoteHashes,
pubkey = remoteBytesPubkey.shortLog, order = order,
@@ -357,11 +357,11 @@ method handshake*(s: Secio, conn: Connection, initiator: bool = false): Future[S
trace "Encryption scheme selected", scheme = scheme, cipher = cipher,
hash = hash
- var ekeypair = ephemeral(scheme)
+ var ekeypair = ephemeral(scheme).tryGet()
# We need EC public key in raw binary form
- var epubkey = ekeypair.pubkey.eckey.getRawBytes()
+ var epubkey = ekeypair.pubkey.eckey.getRawBytes().tryGet()
var localCorpus = request[4..^1] & answer & epubkey
- var signature = s.localPrivateKey.sign(localCorpus)
+ var signature = s.localPrivateKey.sign(localCorpus).tryGet()
var localExchange = createExchange(epubkey, signature.getBytes())
var remoteExchange = await transactMessage(conn, localExchange)
@@ -430,5 +430,5 @@ method init(s: Secio) {.gcsafe.} =
proc newSecio*(localPrivateKey: PrivateKey): Secio =
new result
result.localPrivateKey = localPrivateKey
- result.localPublicKey = localPrivateKey.getKey()
+ result.localPublicKey = localPrivateKey.getKey().tryGet()
result.init()
diff --git a/libp2p/standard_setup.nim b/libp2p/standard_setup.nim
index cd0328b36..2709ad3d7 100644
--- a/libp2p/standard_setup.nim
+++ b/libp2p/standard_setup.nim
@@ -31,7 +31,7 @@ proc newStandardSwitch*(privKey = none(PrivateKey),
result = newMplex(conn)
let
- seckey = privKey.get(otherwise = PrivateKey.random(ECDSA))
+ seckey = privKey.get(otherwise = PrivateKey.random(ECDSA).tryGet())
peerInfo = PeerInfo.init(seckey, [address])
mplexProvider = newMuxerProvider(createMplex, MplexCodec)
transports = @[Transport(newTransport(TcpTransport, transportFlags))]
diff --git a/libp2p/vbuffer.nim b/libp2p/vbuffer.nim
index 585a12a13..1ee9b521a 100644
--- a/libp2p/vbuffer.nim
+++ b/libp2p/vbuffer.nim
@@ -24,9 +24,15 @@ template isEnough*(vb: VBuffer, length: int): bool =
## Returns ``true`` if buffer ``vb`` holds at least ``length`` bytes.
len(vb.buffer) - vb.offset - length >= 0
+proc high*(vb: VBuffer): int =
+ ## Returns number of bytes left in buffer ``vb``.
+ result = vb.buffer.high - vb.offset
+ doAssert(result >= 0)
+
proc len*(vb: VBuffer): int =
## Returns number of bytes left in buffer ``vb``.
result = len(vb.buffer) - vb.offset
+ doAssert(result >= 0)
proc isLiteral[T](s: seq[T]): bool {.inline.} =
type
@@ -58,7 +64,7 @@ proc writePBVarint*(vb: var VBuffer, value: PBSomeUVarint) =
var length = 0
var v = value and cast[type(value)](0xFFFF_FFFF_FFFF_FFFF)
vb.buffer.setLen(len(vb.buffer) + vsizeof(v))
- let res = PB.putUVarint(toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1),
+ let res = PB.putUVarint(toOpenArray(vb.buffer, vb.offset, vb.buffer.high),
length, v)
doAssert(res == VarintStatus.Success)
vb.offset += length
@@ -69,7 +75,7 @@ proc writeLPVarint*(vb: var VBuffer, value: LPSomeUVarint) =
# LibP2P varint supports only 63 bits.
var v = value and cast[type(value)](0x7FFF_FFFF_FFFF_FFFF)
vb.buffer.setLen(len(vb.buffer) + vsizeof(v))
- let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1),
+ let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, vb.buffer.high),
length, v)
doAssert(res == VarintStatus.Success)
vb.offset += length
@@ -82,7 +88,7 @@ proc writeSeq*[T: byte|char](vb: var VBuffer, value: openarray[T]) =
## varint length of the array.
var length = 0
vb.buffer.setLen(len(vb.buffer) + vsizeof(uint(len(value))) + len(value))
- let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1),
+ let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, vb.buffer.high),
length, uint(len(value)))
doAssert(res == VarintStatus.Success)
vb.offset += length
@@ -113,7 +119,7 @@ proc peekVarint*(vb: var VBuffer, value: var LPSomeUVarint): int =
var length = 0
if not vb.isEmpty():
let res = LP.getUVarint(
- toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1), length, value)
+ toOpenArray(vb.buffer, vb.offset, vb.buffer.high), length, value)
if res == VarintStatus.Success:
result = length
@@ -129,7 +135,7 @@ proc peekSeq*[T: string|seq[byte]](vb: var VBuffer, value: var T): int =
var length = 0
var size = 0'u64
if not vb.isEmpty() and
- LP.getUVarint(toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1),
+ LP.getUVarint(toOpenArray(vb.buffer, vb.offset, vb.buffer.high),
length, size) == VarintStatus.Success:
vb.offset += length
result = length
diff --git a/tests/pubsub/testgossipinternal.nim b/tests/pubsub/testgossipinternal.nim
index cf63c3c1f..e25ae8b6c 100644
--- a/tests/pubsub/testgossipinternal.nim
+++ b/tests/pubsub/testgossipinternal.nim
@@ -19,7 +19,7 @@ suite "GossipSub internal":
test "`rebalanceMesh` Degree Lo":
proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub,
- PeerInfo.init(PrivateKey.random(RSA)))
+ PeerInfo.init(PrivateKey.random(RSA).get()))
let topic = "foobar"
gossipSub.mesh[topic] = initHashSet[string]()
@@ -28,7 +28,7 @@ suite "GossipSub internal":
for i in 0..<15:
let conn = newConnection(newBufferStream())
conns &= conn
- let peerInfo = PeerInfo.init(PrivateKey.random(RSA))
+ let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].conn = conn
@@ -48,7 +48,7 @@ suite "GossipSub internal":
test "`rebalanceMesh` Degree Hi":
proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub,
- PeerInfo.init(PrivateKey.random(RSA)))
+ PeerInfo.init(PrivateKey.random(RSA).get()))
let topic = "foobar"
gossipSub.gossipsub[topic] = initHashSet[string]()
@@ -57,7 +57,7 @@ suite "GossipSub internal":
for i in 0..<15:
let conn = newConnection(newBufferStream())
conns &= conn
- let peerInfo = PeerInfo.init(PrivateKey.random(RSA))
+ let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].conn = conn
@@ -77,7 +77,7 @@ suite "GossipSub internal":
test "`replenishFanout` Degree Lo":
proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub,
- PeerInfo.init(PrivateKey.random(RSA)))
+ PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard
@@ -89,7 +89,7 @@ suite "GossipSub internal":
for i in 0..<15:
let conn = newConnection(newBufferStream())
conns &= conn
- var peerInfo = PeerInfo.init(PrivateKey.random(RSA))
+ var peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler
@@ -109,7 +109,7 @@ suite "GossipSub internal":
test "`dropFanoutPeers` drop expired fanout topics":
proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub,
- PeerInfo.init(PrivateKey.random(RSA)))
+ PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard
@@ -122,7 +122,7 @@ suite "GossipSub internal":
for i in 0..<6:
let conn = newConnection(newBufferStream())
conns &= conn
- let peerInfo = PeerInfo.init(PrivateKey.random(RSA))
+ let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler
@@ -143,7 +143,7 @@ suite "GossipSub internal":
test "`dropFanoutPeers` leave unexpired fanout topics":
proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub,
- PeerInfo.init(PrivateKey.random(RSA)))
+ PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard
@@ -159,7 +159,7 @@ suite "GossipSub internal":
for i in 0..<6:
let conn = newConnection(newBufferStream())
conns &= conn
- let peerInfo = PeerInfo.init(PrivateKey.random(RSA))
+ let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler
@@ -183,7 +183,7 @@ suite "GossipSub internal":
test "`getGossipPeers` - should gather up to degree D non intersecting peers":
proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub,
- PeerInfo.init(PrivateKey.random(RSA)))
+ PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard
@@ -196,7 +196,7 @@ suite "GossipSub internal":
for i in 0..<30:
let conn = newConnection(newBufferStream())
conns &= conn
- let peerInfo = PeerInfo.init(PrivateKey.random(RSA))
+ let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler
@@ -208,7 +208,7 @@ suite "GossipSub internal":
for i in 0..<15:
let conn = newConnection(newBufferStream())
conns &= conn
- let peerInfo = PeerInfo.init(PrivateKey.random(RSA))
+ let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler
@@ -234,7 +234,7 @@ suite "GossipSub internal":
test "`getGossipPeers` - should not crash on missing topics in mesh":
proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub,
- PeerInfo.init(PrivateKey.random(RSA)))
+ PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard
@@ -246,7 +246,7 @@ suite "GossipSub internal":
for i in 0..<30:
let conn = newConnection(newBufferStream())
conns &= conn
- let peerInfo = PeerInfo.init(PrivateKey.random(RSA))
+ let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler
@@ -268,7 +268,7 @@ suite "GossipSub internal":
test "`getGossipPeers` - should not crash on missing topics in gossip":
proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub,
- PeerInfo.init(PrivateKey.random(RSA)))
+ PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard
@@ -280,7 +280,7 @@ suite "GossipSub internal":
for i in 0..<30:
let conn = newConnection(newBufferStream())
conns &= conn
- let peerInfo = PeerInfo.init(PrivateKey.random(RSA))
+ let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler
@@ -302,7 +302,7 @@ suite "GossipSub internal":
test "`getGossipPeers` - should not crash on missing topics in gossip":
proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub,
- PeerInfo.init(PrivateKey.random(RSA)))
+ PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard
@@ -314,7 +314,7 @@ suite "GossipSub internal":
for i in 0..<30:
let conn = newConnection(newBufferStream())
conns &= conn
- let peerInfo = PeerInfo.init(PrivateKey.random(RSA))
+ let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler
diff --git a/tests/pubsub/testgossipsub.nim b/tests/pubsub/testgossipsub.nim
index 05d5c490d..c45ceecbb 100644
--- a/tests/pubsub/testgossipsub.nim
+++ b/tests/pubsub/testgossipsub.nim
@@ -25,7 +25,7 @@ import utils, ../../libp2p/[errors,
import ../helpers
proc createGossipSub(): GossipSub =
- var peerInfo = PeerInfo.init(PrivateKey.random(RSA))
+ var peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
result = newPubSub(GossipSub, peerInfo)
proc waitSub(sender, receiver: auto; key: string) {.async, gcsafe.} =
diff --git a/tests/pubsub/testmcache.nim b/tests/pubsub/testmcache.nim
index 7eec8d342..afdcba49a 100644
--- a/tests/pubsub/testmcache.nim
+++ b/tests/pubsub/testmcache.nim
@@ -11,7 +11,7 @@ import ../../libp2p/[peer,
suite "MCache":
test "put/get":
var mCache = newMCache(3, 5)
- var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA)).data,
+ var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA).get()).data,
seqno: cast[seq[byte]]("12345"))
mCache.put(msg)
check mCache.get(msg.msgId).isSome and mCache.get(msg.msgId).get() == msg
@@ -20,13 +20,13 @@ suite "MCache":
var mCache = newMCache(3, 5)
for i in 0..<3:
- var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA)).data,
+ var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA).get()).data,
seqno: cast[seq[byte]]("12345"),
topicIDs: @["foo"])
mCache.put(msg)
for i in 0..<5:
- var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA)).data,
+ var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA).get()).data,
seqno: cast[seq[byte]]("12345"),
topicIDs: @["bar"])
mCache.put(msg)
@@ -41,7 +41,7 @@ suite "MCache":
var mCache = newMCache(1, 5)
for i in 0..<3:
- var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA)).data,
+ var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA).get()).data,
seqno: cast[seq[byte]]("12345"),
topicIDs: @["foo"])
mCache.put(msg)
@@ -50,7 +50,7 @@ suite "MCache":
check mCache.window("foo").len == 0
for i in 0..<3:
- var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA)).data,
+ var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA).get()).data,
seqno: cast[seq[byte]]("12345"),
topicIDs: @["bar"])
mCache.put(msg)
@@ -59,7 +59,7 @@ suite "MCache":
check mCache.window("bar").len == 0
for i in 0..<3:
- var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA)).data,
+ var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA).get()).data,
seqno: cast[seq[byte]]("12345"),
topicIDs: @["baz"])
mCache.put(msg)
@@ -71,19 +71,19 @@ suite "MCache":
var mCache = newMCache(1, 5)
for i in 0..<3:
- var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA)).data,
+ var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA).get()).data,
seqno: cast[seq[byte]]("12345"),
topicIDs: @["foo"])
mCache.put(msg)
for i in 0..<3:
- var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA)).data,
+ var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA).get()).data,
seqno: cast[seq[byte]]("12345"),
topicIDs: @["bar"])
mCache.put(msg)
for i in 0..<3:
- var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA)).data,
+ var msg = Message(fromPeer: PeerID.init(PrivateKey.random(RSA).get()).data,
seqno: cast[seq[byte]]("12345"),
topicIDs: @["baz"])
mCache.put(msg)
diff --git a/tests/testcid.nim b/tests/testcid.nim
index d714626c2..b9df56b7c 100644
--- a/tests/testcid.nim
+++ b/tests/testcid.nim
@@ -38,17 +38,17 @@ suite "Content identifier CID test suite":
var bmsg = cast[seq[byte]](msg)
var bmmsg = cast[seq[byte]](mmsg)
var cid0 = Cid.init(CIDv0, multiCodec("dag-pb"),
- MultiHash.digest("sha2-256", bmsg))
+ MultiHash.digest("sha2-256", bmsg).get())
var cid1 = Cid.init(CIDv1, multiCodec("dag-pb"),
- MultiHash.digest("sha2-256", bmsg))
+ MultiHash.digest("sha2-256", bmsg).get())
var cid2 = cid1
var cid3 = cid0
var cid4 = Cid.init(CIDv1, multiCodec("dag-cbor"),
- MultiHash.digest("sha2-256", bmsg))
+ MultiHash.digest("sha2-256", bmsg).get())
var cid5 = Cid.init(CIDv1, multiCodec("dag-pb"),
- MultiHash.digest("sha2-256", bmmsg))
+ MultiHash.digest("sha2-256", bmmsg).get())
var cid6 = Cid.init(CIDv1, multiCodec("dag-pb"),
- MultiHash.digest("keccak-256", bmsg))
+ MultiHash.digest("keccak-256", bmsg).get())
check:
cid0 == cid1
cid1 == cid2
diff --git a/tests/testcrypto.nim b/tests/testcrypto.nim
index c0e230c1a..0b61101dd 100644
--- a/tests/testcrypto.nim
+++ b/tests/testcrypto.nim
@@ -378,13 +378,13 @@ suite "Key interface test suite":
test "Go test vectors":
for i in 0.. 0
+ key.toBytes(skey2).expect("bytes") > 0
check:
rkey1.init(skey1).isOk
rkey2.init(skey2).isOk
- var rkey3 = EcPrivateKey.init(skey1)
- var rkey4 = EcPrivateKey.init(skey2)
+ var rkey3 = EcPrivateKey.init(skey1).expect("private key")
+ var rkey4 = EcPrivateKey.init(skey2).expect("private key")
check:
rkey1 == key
rkey2 == key
@@ -319,14 +319,14 @@ suite "EC NIST-P256/384/521 test suite":
for i in 0.. 0
+ pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk
rkey2.init(skey2).isOk
- var rkey3 = EcPublicKey.init(skey1)
- var rkey4 = EcPublicKey.init(skey2)
+ var rkey3 = EcPublicKey.init(skey1).expect("public key")
+ var rkey4 = EcPublicKey.init(skey2).expect("public key")
check:
rkey1 == pair.pubkey
rkey2 == pair.pubkey
@@ -335,8 +335,8 @@ suite "EC NIST-P256/384/521 test suite":
test "[secp256r1] ECDHE test":
for i in 0.. 0
+ key.toBytes(skey2).expect("bytes") > 0
check:
rkey1.init(skey1).isOk
rkey2.init(skey2).isOk
- var rkey3 = EcPrivateKey.init(skey1)
- var rkey4 = EcPrivateKey.init(skey2)
+ var rkey3 = EcPrivateKey.init(skey1).expect("private key")
+ var rkey4 = EcPrivateKey.init(skey2).expect("private key")
check:
rkey1 == key
rkey2 == key
@@ -426,14 +426,14 @@ suite "EC NIST-P256/384/521 test suite":
for i in 0.. 0
+ pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk
rkey2.init(skey2).isOk
- var rkey3 = EcPublicKey.init(skey1)
- var rkey4 = EcPublicKey.init(skey2)
+ var rkey3 = EcPublicKey.init(skey1).expect("public key")
+ var rkey4 = EcPublicKey.init(skey2).expect("public key")
check:
rkey1 == pair.pubkey
rkey2 == pair.pubkey
@@ -442,8 +442,8 @@ suite "EC NIST-P256/384/521 test suite":
test "[secp384r1] ECDHE test":
for i in 0.. 0
+ key.toBytes(skey2).expect("bytes") > 0
check:
rkey1.init(skey1).isOk
rkey2.init(skey2).isOk
- var rkey3 = EcPrivateKey.init(skey1)
- var rkey4 = EcPrivateKey.init(skey2)
+ var rkey3 = EcPrivateKey.init(skey1).expect("private key")
+ var rkey4 = EcPrivateKey.init(skey2).expect("private key")
check:
rkey1 == key
rkey2 == key
@@ -533,14 +533,14 @@ suite "EC NIST-P256/384/521 test suite":
for i in 0.. 0
+ pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk
rkey2.init(skey2).isOk
- var rkey3 = EcPublicKey.init(skey1)
- var rkey4 = EcPublicKey.init(skey2)
+ var rkey3 = EcPublicKey.init(skey1).expect("public key")
+ var rkey4 = EcPublicKey.init(skey2).expect("public key")
check:
rkey1 == pair.pubkey
rkey2 == pair.pubkey
@@ -549,8 +549,8 @@ suite "EC NIST-P256/384/521 test suite":
test "[secp521r1] ECDHE test":
for i in 0.. 0
check:
rkey1.init(skey1) == true
rkey2.init(skey2) == true
- var rkey3 = EdPrivateKey.init(skey1)
- var rkey4 = EdPrivateKey.init(skey2)
+ var rkey3 = EdPrivateKey.init(skey1).expect("key/sig")
+ var rkey4 = EdPrivateKey.init(skey2).expect("key/sig")
check:
rkey1 == key
rkey2 == key
@@ -135,14 +135,14 @@ suite "Ed25519 test suite":
for i in 0.. 0
rkey1.init(skey1) == true
rkey2.init(skey2) == true
- var rkey3 = EdPublicKey.init(skey1)
- var rkey4 = EdPublicKey.init(skey2)
+ var rkey3 = EdPublicKey.init(skey1).expect("key/sig")
+ var rkey4 = EdPublicKey.init(skey2).expect("key/sig")
check:
rkey1 == pair.pubkey
rkey2 == pair.pubkey
@@ -156,13 +156,13 @@ suite "Ed25519 test suite":
test "RFC8032 test vectors":
for i in 0..<5:
- var key = EdPrivateKey.init(stripSpaces(SecretKeys[i]))
- var exppub = EdPublicKey.init(stripSpaces(PublicKeys[i]))
+ var key = EdPrivateKey.init(stripSpaces(SecretKeys[i])).expect("key/sig")
+ var exppub = EdPublicKey.init(stripSpaces(PublicKeys[i])).expect("key/sig")
var pubkey = key.getKey()
check pubkey == exppub
var msg = fromHex(stripSpaces(Messages[i]))
var sig = key.sign(msg)
- var expsig = EdSignature.init(fromHex(stripSpaces(Signatures[i])))
+ var expsig = EdSignature.init(fromHex(stripSpaces(Signatures[i]))).expect("key/sig")
check sig == expsig
check sig.verify(msg, pubkey) == true
sig.data[32] = not(sig.data[32])
@@ -171,15 +171,15 @@ suite "Ed25519 test suite":
test "Generate/Sign/Serialize/Deserialize/Verify test":
var message = "message to sign"
for i in 0.. 0
+ var key = RsaPrivateKey.random(512).expect("random key")
+ var skey1 = key.getBytes().expect("bytes")
+ check key.toBytes(skey2).expect("bytes") > 0
check:
rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk()
- var rkey3 = RsaPrivateKey.init(skey1)
- var rkey4 = RsaPrivateKey.init(skey2)
+ var rkey3 = RsaPrivateKey.init(skey1).expect("key initialization")
+ var rkey4 = RsaPrivateKey.init(skey2).expect("key initialization")
check:
rkey1 == key
rkey2 == key
@@ -291,14 +291,14 @@ suite "RSA 512/1024/2048/4096 test suite":
for i in 0.. 0
+ var key = RsaPrivateKey.random(1024).expect("random failed")
+ var skey1 = key.getBytes().expect("bytes")
+ check key.toBytes(skey2).expect("bytes") > 0
check:
rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk()
- var rkey3 = RsaPrivateKey.init(skey1)
- var rkey4 = RsaPrivateKey.init(skey2)
+ var rkey3 = RsaPrivateKey.init(skey1).expect("key initialization")
+ var rkey4 = RsaPrivateKey.init(skey2).expect("key initialization")
check:
rkey1 == key
rkey2 == key
@@ -308,14 +308,14 @@ suite "RSA 512/1024/2048/4096 test suite":
test "[rsa2048] Private key serialize/deserialize test":
var rkey1, rkey2: RsaPrivateKey
var skey2 = newSeq[byte](4096)
- var key = RsaPrivateKey.random(2048)
- var skey1 = key.getBytes()
- check key.toBytes(skey2) > 0
+ var key = RsaPrivateKey.random(2048).expect("random failed")
+ var skey1 = key.getBytes().expect("bytes")
+ check key.toBytes(skey2).expect("bytes") > 0
check:
rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk()
- var rkey3 = RsaPrivateKey.init(skey1)
- var rkey4 = RsaPrivateKey.init(skey2)
+ var rkey3 = RsaPrivateKey.init(skey1).expect("key initialization")
+ var rkey4 = RsaPrivateKey.init(skey2).expect("key initialization")
check:
rkey1 == key
rkey2 == key
@@ -327,14 +327,14 @@ suite "RSA 512/1024/2048/4096 test suite":
when defined(release):
var rkey1, rkey2: RsaPrivateKey
var skey2 = newSeq[byte](4096)
- var key = RsaPrivateKey.random(4096)
- var skey1 = key.getBytes()
- check key.toBytes(skey2) > 0
+ var key = RsaPrivateKey.random(4096).expect("random failed")
+ var skey1 = key.getBytes().expect("bytes")
+ check key.toBytes(skey2).expect("bytes") > 0
check:
rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk()
- var rkey3 = RsaPrivateKey.init(skey1)
- var rkey4 = RsaPrivateKey.init(skey2)
+ var rkey3 = RsaPrivateKey.init(skey1).expect("key initialization")
+ var rkey4 = RsaPrivateKey.init(skey2).expect("key initialization")
check:
rkey1 == key
rkey2 == key
@@ -345,14 +345,14 @@ suite "RSA 512/1024/2048/4096 test suite":
for i in 0.. 0
+ pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk()
- var rkey3 = RsaPublicKey.init(skey1)
- var rkey4 = RsaPublicKey.init(skey2)
+ var rkey3 = RsaPublicKey.init(skey1).expect("key initialization")
+ var rkey4 = RsaPublicKey.init(skey2).expect("key initialization")
check:
rkey1 == pair.pubkey
rkey2 == pair.pubkey
@@ -363,14 +363,14 @@ suite "RSA 512/1024/2048/4096 test suite":
for i in 0.. 0
+ pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk()
- var rkey3 = RsaPublicKey.init(skey1)
- var rkey4 = RsaPublicKey.init(skey2)
+ var rkey3 = RsaPublicKey.init(skey1).expect("key initialization")
+ var rkey4 = RsaPublicKey.init(skey2).expect("key initialization")
check:
rkey1 == pair.pubkey
rkey2 == pair.pubkey
@@ -380,14 +380,14 @@ suite "RSA 512/1024/2048/4096 test suite":
test "[rsa2048] Public key serialize/deserialize test":
var rkey1, rkey2: RsaPublicKey
var skey2 = newSeq[byte](4096)
- var pair = RsaKeyPair.random(2048)
- var skey1 = pair.pubkey.getBytes()
+ var pair = RsaKeyPair.random(2048).expect("random failed")
+ var skey1 = pair.pubkey.getBytes().expect("bytes")
check:
- pair.pubkey.toBytes(skey2) > 0
+ pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk()
- var rkey3 = RsaPublicKey.init(skey1)
- var rkey4 = RsaPublicKey.init(skey2)
+ var rkey3 = RsaPublicKey.init(skey1).expect("key initialization")
+ var rkey4 = RsaPublicKey.init(skey2).expect("key initialization")
check:
rkey1 == pair.pubkey
rkey2 == pair.pubkey
@@ -398,14 +398,14 @@ suite "RSA 512/1024/2048/4096 test suite":
when defined(release):
var rkey1, rkey2: RsaPublicKey
var skey2 = newSeq[byte](4096)
- var pair = RsaKeyPair.random(4096)
- var skey1 = pair.pubkey.getBytes()
+ var pair = RsaKeyPair.random(4096).expect("random failed")
+ var skey1 = pair.pubkey.getBytes().expect("bytes")
check:
- pair.pubkey.toBytes(skey2) > 0
+ pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk()
- var rkey3 = RsaPublicKey.init(skey1)
- var rkey4 = RsaPublicKey.init(skey2)
+ var rkey3 = RsaPublicKey.init(skey1).expect("key initialization")
+ var rkey4 = RsaPublicKey.init(skey2).expect("key initialization")
check:
rkey1 == pair.pubkey
rkey2 == pair.pubkey
@@ -415,154 +415,154 @@ suite "RSA 512/1024/2048/4096 test suite":
test "[rsa512] Generate/Sign/Serialize/Deserialize/Verify test":
var message = "message to sign"
for i in 0.. 0
+ key.toBytes(skey2).expect("bytes len") > 0
check:
- rkey1.init(skey1) == true
- rkey2.init(skey2) == true
- var rkey3 = SkPrivateKey.init(skey1)
- var rkey4 = SkPrivateKey.init(skey2)
+ rkey1.init(skey1).isOk == true
+ rkey2.init(skey2).isOk == true
+ var rkey3 = SkPrivateKey.init(skey1).expect("private key")
+ var rkey4 = SkPrivateKey.init(skey2).expect("private key")
check:
rkey1 == key
rkey2 == key
@@ -41,14 +41,14 @@ suite "Secp256k1 testing suite":
for i in 0.. 0
- rkey1.init(skey1) == true
- rkey2.init(skey2) == true
- var rkey3 = SkPublicKey.init(skey1)
- var rkey4 = SkPublicKey.init(skey2)
+ pair.pubkey.toBytes(skey2).expect("bytes len") > 0
+ rkey1.init(skey1).isOk == true
+ rkey2.init(skey2).isOk == true
+ var rkey3 = SkPublicKey.init(skey1).expect("public key")
+ var rkey4 = SkPublicKey.init(skey2).expect("public key")
check:
rkey1 == pair.pubkey
rkey2 == pair.pubkey
@@ -59,16 +59,16 @@ suite "Secp256k1 testing suite":
test "Generate/Sign/Serialize/Deserialize/Verify test":
var message = "message to sign"
for i in 0..