Crypto utilities resultification (#150)

This commit is contained in:
Giovanni Petrantoni 2020-05-18 14:25:55 +09:00 committed by GitHub
parent 167f42ed45
commit 7dcb807f64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 1180 additions and 1033 deletions

View File

@ -152,7 +152,7 @@ proc readInput(wfd: AsyncFD) {.thread.} =
proc processInput(rfd: AsyncFD) {.async.} = proc processInput(rfd: AsyncFD) {.async.} =
let transp = fromPipe(rfd) let transp = fromPipe(rfd)
let seckey = PrivateKey.random(RSA) let seckey = PrivateKey.random(RSA).get()
let peerInfo = PeerInfo.init(seckey) let peerInfo = PeerInfo.init(seckey)
var localAddress = DefaultAddr var localAddress = DefaultAddr
while true: while true:

View File

@ -95,7 +95,7 @@ proc decode(data: openarray[byte], cid: var Cid): CidStatus =
if mcodec == InvalidMultiCodec: if mcodec == InvalidMultiCodec:
return CidStatus.Incorrect return CidStatus.Incorrect
if not MultiHash.validate(vb.buffer.toOpenArray(vb.offset, if not MultiHash.validate(vb.buffer.toOpenArray(vb.offset,
len(vb.buffer) - 1)): vb.buffer.high)):
return CidStatus.Incorrect return CidStatus.Incorrect
vb.finish() vb.finish()
cid.cidver = CIDv1 cid.cidver = CIDv1
@ -133,7 +133,7 @@ proc validate*(ctype: typedesc[Cid], data: openarray[byte]): bool =
var res: VarintStatus var res: VarintStatus
if len(data) < 2: if len(data) < 2:
return false return false
let last = len(data) - 1 let last = data.high
if len(data) == 34: if len(data) == 34:
if data[0] == 0x12'u8 and data[1] == 0x20'u8: if data[0] == 0x12'u8 and data[1] == 0x20'u8:
return true return true
@ -161,8 +161,8 @@ proc mhash*(cid: Cid): MultiHash =
## Returns MultiHash part of CID. ## Returns MultiHash part of CID.
if cid.cidver notin {CIDv0, CIDv1}: if cid.cidver notin {CIDv0, CIDv1}:
raise newException(CidError, "Incorrect CID!") raise newException(CidError, "Incorrect CID!")
result = MultiHash.init(cid.data.buffer.toOpenArray(cid.hpos, result = MultiHash.init(
len(cid.data) - 1)) cid.data.buffer.toOpenArray(cid.hpos, cid.data.high)).tryGet()
proc contentType*(cid: Cid): MultiCodec = proc contentType*(cid: Cid): MultiCodec =
## Returns content type part of CID ## Returns content type part of CID
@ -221,11 +221,11 @@ proc `==`*(a: Cid, b: Cid): bool =
## are equal, ``false`` otherwise. ## are equal, ``false`` otherwise.
if a.mcodec == b.mcodec: if a.mcodec == b.mcodec:
var ah, bh: MultiHash var ah, bh: MultiHash
if MultiHash.decode(a.data.buffer.toOpenArray(a.hpos, if MultiHash.decode(
len(a.data) - 1), ah) == -1: a.data.buffer.toOpenArray(a.hpos, a.data.high), ah).isErr:
return false return false
if MultiHash.decode(b.data.buffer.toOpenArray(b.hpos, if MultiHash.decode(
len(b.data) - 1), bh) == -1: b.data.buffer.toOpenArray(b.hpos, b.data.high), bh).isErr:
return false return false
result = (ah == bh) result = (ah == bh)

View File

@ -8,6 +8,9 @@
## those terms. ## those terms.
## This module implements Public Key and Private Key interface for libp2p. ## This module implements Public Key and Private Key interface for libp2p.
{.push raises: [Defect].}
import rsa, ecnist, ed25519/ed25519, secp import rsa, ecnist, ed25519/ed25519, secp
import ../protobuf/minprotobuf, ../vbuffer, ../multihash, ../multicodec import ../protobuf/minprotobuf, ../vbuffer, ../multihash, ../multicodec
import nimcrypto/[rijndael, blowfish, twofish, sha, sha2, hash, hmac, utils] import nimcrypto/[rijndael, blowfish, twofish, sha, sha2, hash, hmac, utils]
@ -79,172 +82,177 @@ type
Signature* = object Signature* = object
data*: seq[byte] data*: seq[byte]
P2pKeyError* = object of CatchableError CryptoError* = enum
P2pSigError* = object of CatchableError KeyError,
SigError,
HashError,
SchemeError
CryptoResult*[T] = Result[T, CryptoError]
const const
SupportedSchemes* = {RSA, Ed25519, Secp256k1, ECDSA} SupportedSchemes* = {RSA, Ed25519, Secp256k1, ECDSA}
SupportedSchemesInt* = {int8(RSA), int8(Ed25519), int8(Secp256k1), SupportedSchemesInt* = {int8(RSA), int8(Ed25519), int8(Secp256k1),
int8(ECDSA)} int8(ECDSA)}
template orError(exp: untyped, err: CryptoError): untyped =
(exp.mapErr do (_: auto) -> auto: err)
proc random*(t: typedesc[PrivateKey], scheme: PKScheme, proc random*(t: typedesc[PrivateKey], scheme: PKScheme,
bits = DefaultKeySize): PrivateKey = bits = DefaultKeySize): CryptoResult[PrivateKey] =
## Generate random private key for scheme ``scheme``. ## Generate random private key for scheme ``scheme``.
## ##
## ``bits`` is number of bits for RSA key, ``bits`` value must be in ## ``bits`` is number of bits for RSA key, ``bits`` value must be in
## [512, 4096], default value is 2048 bits. ## [512, 4096], default value is 2048 bits.
doAssert(scheme in SupportedSchemes) case scheme
result = PrivateKey(scheme: scheme) of RSA:
if scheme == RSA: let rsakey = ? RsaPrivateKey.random(bits).orError(KeyError)
result.rsakey = RsaPrivateKey.random(bits) ok(PrivateKey(scheme: scheme, rsakey: rsakey))
elif scheme == Ed25519: of Ed25519:
result.edkey = EdPrivateKey.random() let edkey = ? EdPrivateKey.random().orError(KeyError)
elif scheme == ECDSA: ok(PrivateKey(scheme: scheme, edkey: edkey))
result.eckey = EcPrivateKey.random(Secp256r1) of ECDSA:
elif scheme == Secp256k1: let eckey = ? EcPrivateKey.random(Secp256r1).orError(KeyError)
result.skkey = SkPrivateKey.random() 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, proc random*(t: typedesc[KeyPair], scheme: PKScheme,
bits = DefaultKeySize): KeyPair = bits = DefaultKeySize): CryptoResult[KeyPair] =
## Generate random key pair for scheme ``scheme``. ## Generate random key pair for scheme ``scheme``.
## ##
## ``bits`` is number of bits for RSA key, ``bits`` value must be in ## ``bits`` is number of bits for RSA key, ``bits`` value must be in
## [512, 4096], default value is 2048 bits. ## [512, 4096], default value is 2048 bits.
doAssert(scheme in SupportedSchemes) case scheme
result.seckey = PrivateKey(scheme: scheme) of RSA:
result.pubkey = PublicKey(scheme: scheme) let pair = ? RsaKeyPair.random(bits).orError(KeyError)
if scheme == RSA: ok(KeyPair(
var pair = RsaKeyPair.random(bits) seckey: PrivateKey(scheme: scheme, rsakey: pair.seckey),
result.seckey.rsakey = pair.seckey pubkey: PublicKey(scheme: scheme, rsakey: pair.pubkey)))
result.pubkey.rsakey = pair.pubkey of Ed25519:
elif scheme == Ed25519: let pair = ? EdKeyPair.random().orError(KeyError)
var pair = EdKeyPair.random() ok(KeyPair(
result.seckey.edkey = pair.seckey seckey: PrivateKey(scheme: scheme, edkey: pair.seckey),
result.pubkey.edkey = pair.pubkey pubkey: PublicKey(scheme: scheme, edkey: pair.pubkey)))
elif scheme == ECDSA: of ECDSA:
var pair = EcKeyPair.random(Secp256r1) let pair = ? EcKeyPair.random(Secp256r1).orError(KeyError)
result.seckey.eckey = pair.seckey ok(KeyPair(
result.pubkey.eckey = pair.pubkey seckey: PrivateKey(scheme: scheme, eckey: pair.seckey),
elif scheme == Secp256k1: pubkey: PublicKey(scheme: scheme, eckey: pair.pubkey)))
var pair = SkKeyPair.random() of Secp256k1:
result.seckey.skkey = pair.seckey let pair = ? SkKeyPair.random().orError(KeyError)
result.pubkey.skkey = pair.pubkey 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``. ## Get public key from corresponding private key ``key``.
result = PublicKey(scheme: key.scheme) case key.scheme
if key.scheme == RSA: of RSA:
result.rsakey = key.rsakey.getKey() let rsakey = key.rsakey.getKey()
elif key.scheme == Ed25519: ok(PublicKey(scheme: RSA, rsakey: rsakey))
result.edkey = key.edkey.getKey() of Ed25519:
elif key.scheme == ECDSA: let edkey = key.edkey.getKey()
result.eckey = key.eckey.getKey() ok(PublicKey(scheme: Ed25519, edkey: edkey))
elif key.scheme == Secp256k1: of ECDSA:
result.skkey = key.skkey.getKey() 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 ## Serialize private key ``key`` (using scheme's own serialization) and store
## it to ``data``. ## it to ``data``.
## ##
## Returns number of bytes (octets) needed to store private key ``key``. ## Returns number of bytes (octets) needed to store private key ``key``.
if key.scheme == RSA: case key.scheme
result = key.rsakey.toBytes(data) of RSA:
elif key.scheme == Ed25519: key.rsakey.toBytes(data).orError(KeyError)
result = key.edkey.toBytes(data) of Ed25519:
elif key.scheme == ECDSA: ok(key.edkey.toBytes(data))
result = key.eckey.toBytes(data) of ECDSA:
elif key.scheme == Secp256k1: key.eckey.toBytes(data).orError(KeyError)
result = key.skkey.toBytes(data) of Secp256k1:
key.skkey.toBytes(data).orError(KeyError)
else:
err(KeyError)
proc toRawBytes*(key: PublicKey, data: var openarray[byte]): int = proc getRawBytes*(key: PrivateKey | PublicKey): CryptoResult[seq[byte]] =
## 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] =
## Return private key ``key`` in binary form (using scheme's own ## Return private key ``key`` in binary form (using scheme's own
## serialization). ## serialization).
if key.scheme == RSA: case key.scheme
result = key.rsakey.getBytes() of RSA:
elif key.scheme == Ed25519: key.rsakey.getBytes().orError(KeyError)
result = key.edkey.getBytes() of Ed25519:
elif key.scheme == ECDSA: ok(key.edkey.getBytes())
result = key.eckey.getBytes() of ECDSA:
elif key.scheme == Secp256k1: key.eckey.getBytes().orError(KeyError)
result = key.skkey.getBytes() of Secp256k1:
ok(key.skkey.getBytes())
else:
err(KeyError)
proc getRawBytes*(key: PublicKey): seq[byte] = proc toBytes*(key: PrivateKey, data: var openarray[byte]): CryptoResult[int] =
## 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 =
## Serialize private key ``key`` (using libp2p protobuf scheme) and store ## Serialize private key ``key`` (using libp2p protobuf scheme) and store
## it to ``data``. ## it to ``data``.
## ##
## Returns number of bytes (octets) needed to store private key ``key``. ## Returns number of bytes (octets) needed to store private key ``key``.
var msg = initProtoBuffer() var msg = initProtoBuffer()
msg.write(initProtoField(1, cast[uint64](key.scheme))) msg.write(initProtoField(1, cast[uint64](key.scheme)))
msg.write(initProtoField(2, key.getRawBytes())) msg.write(initProtoField(2, ? key.getRawBytes()))
msg.finish() msg.finish()
result = len(msg.buffer) var blen = len(msg.buffer)
if len(data) >= result: if len(data) >= blen:
copyMem(addr data[0], addr msg.buffer[0], len(msg.buffer)) 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 ## Serialize public key ``key`` (using libp2p protobuf scheme) and store
## it to ``data``. ## it to ``data``.
## ##
## Returns number of bytes (octets) needed to store public key ``key``. ## Returns number of bytes (octets) needed to store public key ``key``.
var msg = initProtoBuffer() var msg = initProtoBuffer()
msg.write(initProtoField(1, cast[uint64](key.scheme))) msg.write(initProtoField(1, cast[uint64](key.scheme)))
msg.write(initProtoField(2, key.getRawBytes())) msg.write(initProtoField(2, ? key.getRawBytes()))
msg.finish() msg.finish()
result = len(msg.buffer) var blen = len(msg.buffer)
if len(data) >= result: if len(data) >= blen and blen > 0:
copyMem(addr data[0], addr msg.buffer[0], len(msg.buffer)) copyMem(addr data[0], addr msg.buffer[0], blen)
ok(blen)
proc toBytes*(sig: Signature, data: var openarray[byte]): int = proc toBytes*(sig: Signature, data: var openarray[byte]): int =
## Serialize signature ``sig`` and store it to ``data``. ## Serialize signature ``sig`` and store it to ``data``.
## ##
## Returns number of bytes (octets) needed to store signature ``sig``. ## Returns number of bytes (octets) needed to store signature ``sig``.
result = len(sig.data) 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)) 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 ## Return private key ``key`` in binary form (using libp2p's protobuf
## serialization). ## serialization).
var msg = initProtoBuffer() var msg = initProtoBuffer()
msg.write(initProtoField(1, cast[uint64](key.scheme))) msg.write(initProtoField(1, cast[uint64](key.scheme)))
msg.write(initProtoField(2, key.getRawBytes())) msg.write(initProtoField(2, ? key.getRawBytes()))
msg.finish() 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 ## Return public key ``key`` in binary form (using libp2p's protobuf
## serialization). ## serialization).
var msg = initProtoBuffer() var msg = initProtoBuffer()
msg.write(initProtoField(1, cast[uint64](key.scheme))) msg.write(initProtoField(1, cast[uint64](key.scheme)))
msg.write(initProtoField(2, key.getRawBytes())) msg.write(initProtoField(2, ? key.getRawBytes()))
msg.finish() msg.finish()
result = msg.buffer ok(msg.buffer)
proc getBytes*(sig: Signature): seq[byte] = proc getBytes*(sig: Signature): seq[byte] =
## Return signature ``sig`` in binary form. ## Return signature ``sig`` in binary form.
@ -277,7 +285,7 @@ proc init*(key: var PrivateKey, data: openarray[byte]): bool =
key = nkey key = nkey
result = true result = true
elif scheme == Secp256k1: elif scheme == Secp256k1:
if init(nkey.skkey, buffer): if init(nkey.skkey, buffer).isOk:
key = nkey key = nkey
result = true result = true
@ -308,7 +316,7 @@ proc init*(key: var PublicKey, data: openarray[byte]): bool =
key = nkey key = nkey
result = true result = true
elif scheme == Secp256k1: elif scheme == Secp256k1:
if init(nkey.skkey, buffer): if init(nkey.skkey, buffer).isOk:
key = nkey key = nkey
result = true result = true
@ -325,50 +333,77 @@ proc init*(key: var PrivateKey, data: string): bool =
## hexadecimal string representation. ## hexadecimal string representation.
## ##
## Returns ``true`` on success. ## 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 = proc init*(key: var PublicKey, data: string): bool =
## Initialize public key ``key`` from libp2p's protobuf serialized ## Initialize public key ``key`` from libp2p's protobuf serialized
## hexadecimal string representation. ## hexadecimal string representation.
## ##
## Returns ``true`` on success. ## 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 = proc init*(sig: var Signature, data: string): bool =
## Initialize signature ``sig`` from serialized hexadecimal string ## Initialize signature ``sig`` from serialized hexadecimal string
## representation. ## representation.
## ##
## Returns ``true`` on success. ## 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. ## Create new private key from libp2p's protobuf serialized binary form.
if not result.init(data): var res: t
raise newException(P2pKeyError, "Incorrect binary form") 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. ## Create new public key from libp2p's protobuf serialized binary form.
if not result.init(data): var res: t
raise newException(P2pKeyError, "Incorrect binary form") 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. ## Create new public key from libp2p's protobuf serialized binary form.
if not result.init(data): var res: t
raise newException(P2pSigError, "Incorrect binary form") 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 ## Create new private key from libp2p's protobuf serialized hexadecimal string
## form. ## 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 ## Create new public key from libp2p's protobuf serialized hexadecimal string
## form. ## 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. ## 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 = proc `==`*(key1, key2: PublicKey): bool =
## Return ``true`` if two public keys ``key1`` and ``key2`` of the same ## 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``. ## Get string representation of signature ``sig``.
result = toHex(sig.data) 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 ## Sign message ``data`` using private key ``key`` and return generated
## signature in raw binary form. ## signature in raw binary form.
var res: Signature
if key.scheme == RSA: if key.scheme == RSA:
var sig = key.rsakey.sign(data) let sig = ? key.rsakey.sign(data).orError(SigError)
result.data = sig.getBytes() res.data = ? sig.getBytes().orError(SigError)
ok(res)
elif key.scheme == Ed25519: elif key.scheme == Ed25519:
var sig = key.edkey.sign(data) let sig = key.edkey.sign(data)
result.data = sig.getBytes() res.data = sig.getBytes()
ok(res)
elif key.scheme == ECDSA: elif key.scheme == ECDSA:
var sig = key.eckey.sign(data) let sig = ? key.eckey.sign(data).orError(SigError)
result.data = sig.getBytes() res.data = ? sig.getBytes().orError(SigError)
ok(res)
elif key.scheme == Secp256k1: elif key.scheme == Secp256k1:
var sig = key.skkey.sign(data) let sig = ? key.skkey.sign(data).orError(SigError)
result.data = sig.getBytes() res.data = sig.getBytes()
ok(res)
else:
err(SigError)
proc verify*(sig: Signature, message: openarray[byte], proc verify*(sig: Signature, message: openarray[byte], key: PublicKey): bool =
key: PublicKey): bool =
## Verify signature ``sig`` using message ``message`` and public key ``key``. ## Verify signature ``sig`` using message ``message`` and public key ``key``.
## Return ``true`` if message signature is valid. ## Return ``true`` if message signature is valid.
if key.scheme == RSA: if key.scheme == RSA:
@ -498,7 +539,7 @@ proc verify*(sig: Signature, message: openarray[byte],
result = signature.verify(message, key.eckey) result = signature.verify(message, key.eckey)
elif key.scheme == Secp256k1: elif key.scheme == Secp256k1:
var signature: SkSignature var signature: SkSignature
if signature.init(sig.data): if signature.init(sig.data).isOk:
result = signature.verify(message, key.skkey) result = signature.verify(message, key.skkey)
template makeSecret(buffer, hmactype, secret, seed: untyped) {.dirty.}= 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: if secret[i] != 0x00'u8:
break break
inc(offset) inc(offset)
ctx.init(secret.toOpenArray(offset, len(secret) - 1)) ctx.init(secret.toOpenArray(offset, secret.high))
ctx.update(seed) ctx.update(seed)
var a = ctx.finish() var a = ctx.finish()
while j < len(buffer): 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(a.data)
ctx.update(seed) ctx.update(seed)
var b = ctx.finish() var b = ctx.finish()
@ -523,7 +564,7 @@ template makeSecret(buffer, hmactype, secret, seed: untyped) {.dirty.}=
todo = len(buffer) - j todo = len(buffer) - j
copyMem(addr buffer[j], addr b.data[0], todo) copyMem(addr buffer[j], addr b.data[0], todo)
j += todo j += todo
ctx.init(secret.toOpenArray(offset, len(secret) - 1)) ctx.init(secret.toOpenArray(offset, secret.high))
ctx.update(a.data) ctx.update(a.data)
a = ctx.finish() a = ctx.finish()
@ -588,33 +629,32 @@ proc mac*(secret: Secret, id: int): seq[byte] {.inline.} =
offset += secret.ivsize + secret.keysize offset += secret.ivsize + secret.keysize
copyMem(addr result[0], unsafeAddr secret.data[offset], secret.macsize) 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. ## Generate ephemeral keys used to perform ECDHE.
var keypair: EcKeyPair var keypair: EcKeyPair
if scheme == Secp256r1: if scheme == Secp256r1:
keypair = EcKeyPair.random(Secp256r1) keypair = ? EcKeyPair.random(Secp256r1).orError(KeyError)
elif scheme == Secp384r1: elif scheme == Secp384r1:
keypair = EcKeyPair.random(Secp384r1) keypair = ? EcKeyPair.random(Secp384r1).orError(KeyError)
elif scheme == Secp521r1: elif scheme == Secp521r1:
keypair = EcKeyPair.random(Secp521r1) keypair = ? EcKeyPair.random(Secp521r1).orError(KeyError)
result.seckey = PrivateKey(scheme: ECDSA) ok(KeyPair(
result.pubkey = PublicKey(scheme: ECDSA) seckey: PrivateKey(scheme: ECDSA, eckey: keypair.seckey),
result.seckey.eckey = keypair.seckey pubkey: PublicKey(scheme: ECDSA, eckey: keypair.pubkey)))
result.pubkey.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. ## Generate ephemeral keys used to perform ECDHE using string encoding.
## ##
## Currently supported encoding strings are P-256, P-384, P-521, if encoding ## Currently supported encoding strings are P-256, P-384, P-521, if encoding
## string is not supported P-521 key will be generated. ## string is not supported P-521 key will be generated.
if scheme == "P-256": if scheme == "P-256":
result = ephemeral(Secp256r1) ephemeral(Secp256r1)
elif scheme == "P-384": elif scheme == "P-384":
result = ephemeral(Secp384r1) ephemeral(Secp384r1)
elif scheme == "P-521": elif scheme == "P-521":
result = ephemeral(Secp521r1) ephemeral(Secp521r1)
else: else:
result = ephemeral(Secp521r1) ephemeral(Secp521r1)
proc makeSecret*(remoteEPublic: PublicKey, localEPrivate: PrivateKey, proc makeSecret*(remoteEPublic: PublicKey, localEPrivate: PrivateKey,
data: var openarray[byte]): int = data: var openarray[byte]): int =
@ -644,7 +684,7 @@ proc getSecret*(remoteEPublic: PublicKey,
result = getSecret(remoteEPublic.eckey, localEPrivate.eckey) result = getSecret(remoteEPublic.eckey, localEPrivate.eckey)
proc getOrder*(remotePubkey, localNonce: openarray[byte], proc getOrder*(remotePubkey, localNonce: openarray[byte],
localPubkey, remoteNonce: openarray[byte]): int = localPubkey, remoteNonce: openarray[byte]): CryptoResult[int] =
## Compare values and calculate `order` parameter. ## Compare values and calculate `order` parameter.
var ctx: sha256 var ctx: sha256
ctx.init() ctx.init()
@ -655,16 +695,18 @@ proc getOrder*(remotePubkey, localNonce: openarray[byte],
ctx.update(localPubkey) ctx.update(localPubkey)
ctx.update(remoteNonce) ctx.update(remoteNonce)
var digest2 = ctx.finish() var digest2 = ctx.finish()
var mh1 = MultiHash.init(multiCodec("sha2-256"), digest1) var mh1 = ? MultiHash.init(multiCodec("sha2-256"), digest1).orError(HashError)
var mh2 = MultiHash.init(multiCodec("sha2-256"), digest2) var mh2 = ? MultiHash.init(multiCodec("sha2-256"), digest2).orError(HashError)
var res = 0;
for i in 0 ..< len(mh1.data.buffer): for i in 0 ..< len(mh1.data.buffer):
result = int(mh1.data.buffer[i]) - int(mh2.data.buffer[i]) res = int(mh1.data.buffer[i]) - int(mh2.data.buffer[i])
if result != 0: if res != 0:
if result < 0: if res < 0:
result = -1 res = -1
elif result > 0: elif res > 0:
result = 1 res = 1
break break
ok(res)
proc selectBest*(order: int, p1, p2: string): string = proc selectBest*(order: int, p1, p2: string): string =
## Determines which algorithm to use from list `p1` and `p2`. ## Determines which algorithm to use from list `p1` and `p2`.
@ -741,25 +783,25 @@ proc decodeExchange*(message: seq[byte],
## Serialization/Deserialization helpers ## 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``. ## 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``. ## 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``. ## 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``. ## 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``. ## Initialize ProtoField with PrivateKey ``seckey``.
result = initProtoField(index, seckey.getBytes()) result = initProtoField(index, seckey.getBytes().tryGet())
proc initProtoField*(index: int, sig: Signature): ProtoField = proc initProtoField*(index: int, sig: Signature): ProtoField =
## Initialize ProtoField with Signature ``sig``. ## Initialize ProtoField with Signature ``sig``.

View File

@ -14,6 +14,8 @@
## BearSSL library <https://bearssl.org/> ## BearSSL library <https://bearssl.org/>
## Copyright(C) 2018 Thomas Pornin <pornin@bolet.org>. ## Copyright(C) 2018 Thomas Pornin <pornin@bolet.org>.
{.push raises: [Defect].}
import bearssl import bearssl
import nimcrypto/utils import nimcrypto/utils
import minasn1 import minasn1
@ -58,11 +60,14 @@ type
EcPKI* = EcPrivateKey | EcPublicKey | EcSignature EcPKI* = EcPrivateKey | EcPublicKey | EcSignature
EcError* = object of CatchableError EcError* = enum
EcKeyIncorrectError* = object of EcError EcRngError,
EcRngError* = object of EcError EcKeyGenError,
EcPublicKeyError* = object of EcError EcPublicKeyError,
EcSignatureError* = object of EcError EcKeyIncorrectError,
EcSignatureError
EcResult*[T] = Result[T, EcError]
const const
EcSupportedCurvesCint* = {cint(Secp256r1), cint(Secp384r1), cint(Secp521r1)} 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.qlen = 0
pki.pubkey.key.curve = 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 ## Generate new random EC private key using BearSSL's HMAC-SHA256-DRBG
## algorithm. ## algorithm.
## ##
@ -232,37 +237,46 @@ proc random*(t: typedesc[EcPrivateKey], kind: EcCurveKind): EcPrivateKey =
var seeder = brPrngSeederSystem(nil) var seeder = brPrngSeederSystem(nil)
brHmacDrbgInit(addr rng, addr sha256Vtable, nil, 0) brHmacDrbgInit(addr rng, addr sha256Vtable, nil, 0)
if seeder(addr rng.vtable) == 0: if seeder(addr rng.vtable) == 0:
raise newException(ValueError, "Could not seed RNG") return err(EcRngError)
var ecimp = brEcGetDefault() var ecimp = brEcGetDefault()
result = new EcPrivateKey var res = new EcPrivateKey
result.buffer = newSeq[byte](BR_EC_KBUF_PRIV_MAX_SIZE) res.buffer = newSeq[byte](BR_EC_KBUF_PRIV_MAX_SIZE)
if brEcKeygen(addr rng.vtable, ecimp, if brEcKeygen(addr rng.vtable, ecimp,
addr result.key, addr result.buffer[0], addr res.key, addr res.buffer[0],
cast[cint](kind)) == 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``. ## Calculate and return EC public key from private key ``seckey``.
doAssert(not isNil(seckey)) if isNil(seckey):
return err(EcKeyIncorrectError)
var ecimp = brEcGetDefault() var ecimp = brEcGetDefault()
if seckey.key.curve in EcSupportedCurvesCint: if seckey.key.curve in EcSupportedCurvesCint:
var length = getPublicKeyLength(cast[EcCurveKind](seckey.key.curve)) var length = getPublicKeyLength(cast[EcCurveKind](seckey.key.curve))
result = new EcPublicKey var res = new EcPublicKey
result.buffer = newSeq[byte](length) res.buffer = newSeq[byte](length)
if brEcComputePublicKey(ecimp, addr result.key, if brEcComputePublicKey(ecimp, addr res.key,
addr result.buffer[0], unsafeAddr seckey.key) == 0: addr res.buffer[0], unsafeAddr seckey.key) == 0:
raise newException(EcKeyIncorrectError, "Could not calculate public key") err(EcKeyIncorrectError)
else:
ok(res)
else: 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 ## Generate new random EC private and public keypair using BearSSL's
## HMAC-SHA256-DRBG algorithm. ## HMAC-SHA256-DRBG algorithm.
## ##
## ``kind`` elliptic curve kind of your choice (secp256r1, secp384r1 or ## ``kind`` elliptic curve kind of your choice (secp256r1, secp384r1 or
## secp521r1). ## secp521r1).
result.seckey = EcPrivateKey.random(kind) let
result.pubkey = result.seckey.getKey() seckey = ? EcPrivateKey.random(kind)
pubkey = ? seckey.getKey()
key = EcKeyPair(seckey: seckey, pubkey: pubkey)
ok(key)
proc `$`*(seckey: EcPrivateKey): string = proc `$`*(seckey: EcPrivateKey): string =
## Return string representation of EC private key. ## Return string representation of EC private key.
@ -303,29 +317,37 @@ proc `$`*(sig: EcSignature): string =
else: else:
result = toHex(sig.buffer) 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 ## Serialize EC private key ``seckey`` to raw binary form and store it
## to ``data``. ## to ``data``.
## ##
## Returns number of bytes (octets) needed to store EC private key, or `0` ## Returns number of bytes (octets) needed to store EC private key, or `0`
## if private key is not in supported curve. ## if private key is not in supported curve.
doAssert(not isNil(seckey)) if isNil(seckey):
return err(EcKeyIncorrectError)
if seckey.key.curve in EcSupportedCurvesCint: if seckey.key.curve in EcSupportedCurvesCint:
result = getPrivateKeyLength(cast[EcCurveKind](seckey.key.curve)) let klen = getPrivateKeyLength(cast[EcCurveKind](seckey.key.curve))
if len(data) >= result: if len(data) >= klen:
copyMem(addr data[0], unsafeAddr seckey.buffer[0], result) 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 ## Serialize EC public key ``pubkey`` to uncompressed form specified in
## section 4.3.6 of ANSI X9.62. ## section 4.3.6 of ANSI X9.62.
## ##
## Returns number of bytes (octets) needed to store EC public key, or `0` ## Returns number of bytes (octets) needed to store EC public key, or `0`
## if public key is not in supported curve. ## if public key is not in supported curve.
doAssert(not isNil(pubkey)) if isNil(pubkey):
return err(EcKeyIncorrectError)
if pubkey.key.curve in EcSupportedCurvesCint: if pubkey.key.curve in EcSupportedCurvesCint:
result = getPublicKeyLength(cast[EcCurveKind](pubkey.key.curve)) let klen = getPublicKeyLength(cast[EcCurveKind](pubkey.key.curve))
if len(data) >= result: if len(data) >= klen:
copyMem(addr data[0], unsafeAddr pubkey.buffer[0], result) copyMem(addr data[0], unsafeAddr pubkey.buffer[0], klen)
ok(klen)
else:
err(EcKeyIncorrectError)
proc toRawBytes*(sig: EcSignature, data: var openarray[byte]): int = proc toRawBytes*(sig: EcSignature, data: var openarray[byte]): int =
## Serialize EC signature ``sig`` to raw binary form and store it to ``data``. ## 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: if len(sig.buffer) > 0:
copyMem(addr data[0], unsafeAddr sig.buffer[0], len(sig.buffer)) 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 ## Serialize EC private key ``seckey`` to ASN.1 DER binary form and store it
## to ``data``. ## to ``data``.
## ##
## Procedure returns number of bytes (octets) needed to store EC private key, ## Procedure returns number of bytes (octets) needed to store EC private key,
## or `0` if private key is not in supported curve. ## 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: if seckey.key.curve in EcSupportedCurvesCint:
var offset, length: int var offset, length: int
var pubkey = seckey.getKey() var pubkey = ? seckey.getKey()
var b = Asn1Buffer.init() var b = Asn1Buffer.init()
var p = Asn1Composite.init(Asn1Tag.Sequence) var p = Asn1Composite.init(Asn1Tag.Sequence)
var c0 = Asn1Composite.init(0) var c0 = Asn1Composite.init(0)
@ -374,17 +397,23 @@ proc toBytes*(seckey: EcPrivateKey, data: var openarray[byte]): int =
p.finish() p.finish()
b.write(p) b.write(p)
b.finish() b.finish()
result = len(b) var blen = len(b)
if len(data) >= result: if len(data) >= blen:
copyMem(addr data[0], addr b.buffer[0], result) 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 ## Serialize EC public key ``pubkey`` to ASN.1 DER binary form and store it
## to ``data``. ## to ``data``.
## ##
## Procedure returns number of bytes (octets) needed to store EC public key, ## Procedure returns number of bytes (octets) needed to store EC public key,
## or `0` if public key is not in supported curve. ## 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: if pubkey.key.curve in EcSupportedCurvesCint:
var b = Asn1Buffer.init() var b = Asn1Buffer.init()
var p = Asn1Composite.init(Asn1Tag.Sequence) var p = Asn1Composite.init(Asn1Tag.Sequence)
@ -405,80 +434,97 @@ proc toBytes*(pubkey: EcPublicKey, data: var openarray[byte]): int =
p.finish() p.finish()
b.write(p) b.write(p)
b.finish() b.finish()
result = len(b) var blen = len(b)
if len(data) >= result: if len(data) >= blen:
copyMem(addr data[0], addr b.buffer[0], result) 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 ## Serialize EC signature ``sig`` to ASN.1 DER binary form and store it
## to ``data``. ## to ``data``.
## ##
## Procedure returns number of bytes (octets) needed to store EC signature, ## Procedure returns number of bytes (octets) needed to store EC signature,
## or `0` if signature is not in supported curve. ## or `0` if signature is not in supported curve.
doAssert(not isNil(sig)) if isNil(sig):
result = len(sig.buffer) return err(EcSignatureError)
if len(data) >= result: let slen = len(sig.buffer)
copyMem(addr data[0], unsafeAddr sig.buffer[0], result) 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. ## 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: if seckey.key.curve in EcSupportedCurvesCint:
result = newSeq[byte]() var res = newSeq[byte]()
let length = seckey.toBytes(result) let length = ? seckey.toBytes(res)
result.setLen(length) res.setLen(length)
discard seckey.toBytes(result) discard ? seckey.toBytes(res)
ok(res)
else: 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. ## 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: if pubkey.key.curve in EcSupportedCurvesCint:
result = newSeq[byte]() var res = newSeq[byte]()
let length = pubkey.toBytes(result) let length = ? pubkey.toBytes(res)
result.setLen(length) res.setLen(length)
discard pubkey.toBytes(result) discard ? pubkey.toBytes(res)
ok(res)
else: 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. ## Serialize EC signature ``sig`` to ASN.1 DER binary form and return it.
doAssert(not isNil(sig)) if isNil(sig):
result = newSeq[byte]() return err(EcSignatureError)
let length = sig.toBytes(result) var res = newSeq[byte]()
result.setLen(length) let length = ? sig.toBytes(res)
discard sig.toBytes(result) 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. ## 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: if seckey.key.curve in EcSupportedCurvesCint:
result = newSeq[byte]() var res = newSeq[byte]()
let length = seckey.toRawBytes(result) let length = ? seckey.toRawBytes(res)
result.setLen(length) res.setLen(length)
discard seckey.toRawBytes(result) discard ? seckey.toRawBytes(res)
ok(res)
else: 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. ## 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: if pubkey.key.curve in EcSupportedCurvesCint:
result = newSeq[byte]() var res = newSeq[byte]()
let length = pubkey.toRawBytes(result) let length = ? pubkey.toRawBytes(res)
result.setLen(length) res.setLen(length)
discard pubkey.toRawBytes(result) discard ? pubkey.toRawBytes(res)
ok(res)
else: 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. ## Serialize EC signature ``sig`` to raw binary form and return it.
doAssert(not isNil(sig)) if isNil(sig):
result = newSeq[byte]() return err(EcSignatureError)
let length = sig.toBytes(result) var res = newSeq[byte]()
result.setLen(length) let length = ? sig.toBytes(res)
discard sig.toBytes(result) res.setLen(length)
discard ? sig.toBytes(res)
ok(res)
proc `==`*(pubkey1, pubkey2: EcPublicKey): bool = proc `==`*(pubkey1, pubkey2: EcPublicKey): bool =
## Returns ``true`` if both keys ``pubkey1`` and ``pubkey2`` are equal. ## 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``. ## Procedure returns ``Asn1Status``.
sospk.init(fromHex(data)) 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 ## Initialize EC private key from ASN.1 DER binary representation ``data`` and
## return constructed object. ## return constructed object.
let res = result.init(data) var key: EcPrivateKey
let res = key.init(data)
if res.isErr: if res.isErr:
raise newException(EcKeyIncorrectError, err(EcKeyIncorrectError)
"Incorrect private key (" & $res.error & ")") 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 ## Initialize EC public key from ASN.1 DER binary representation ``data`` and
## return constructed object. ## return constructed object.
let res = result.init(data) var key: EcPublicKey
let res = key.init(data)
if res.isErr: if res.isErr:
raise newException(EcKeyIncorrectError, err(EcKeyIncorrectError)
"Incorrect public key (" & $res.error & ")") 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 ## Initialize EC signature from raw binary representation ``data`` and
## return constructed object. ## return constructed object.
let res = result.init(data) var sig: EcSignature
let res = sig.init(data)
if res.isErr: if res.isErr:
raise newException(EcKeyIncorrectError, err(EcSignatureError)
"Incorrect signature (" & $res.error & ")") 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 ## Initialize EC `private key`, `public key` or `signature` from hexadecimal
## string representation ``data`` and return constructed object. ## 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 = proc initRaw*(key: var EcPrivateKey, data: openarray[byte]): bool =
## Initialize EC `private key` or `scalar` ``key`` from raw binary ## 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. ## Procedure returns ``true`` on success, ``false`` otherwise.
result = sospk.initRaw(fromHex(data)) 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 ## Initialize EC private key from raw binary representation ``data`` and
## return constructed object. ## return constructed object.
if not result.initRaw(data): var res: EcPrivateKey
raise newException(EcKeyIncorrectError, "Incorrect private key") 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 ## Initialize EC public key from raw binary representation ``data`` and
## return constructed object. ## return constructed object.
if not result.initRaw(data): var res: EcPublicKey
raise newException(EcKeyIncorrectError, "Incorrect public key") 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 ## Initialize EC signature from raw binary representation ``data`` and
## return constructed object. ## return constructed object.
if not result.initRaw(data): var res: EcSignature
raise newException(EcKeyIncorrectError, "Incorrect signature") if not res.initRaw(data):
err(EcSignatureError)
else:
ok(res)
proc initRaw*[T: EcPKI](t: typedesc[T], data: string): T {.inline.} = proc initRaw*[T: EcPKI](t: typedesc[T], data: string): T {.inline.} =
## Initialize EC `private key`, `public key` or `signature` from raw ## 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) copyMem(addr result[0], addr data[0], res)
proc sign*[T: byte|char](seckey: EcPrivateKey, 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``. ## Get ECDSA signature of data ``message`` using private key ``seckey``.
doAssert(not isNil(seckey)) if isNil(seckey):
return err(EcKeyIncorrectError)
var hc: BrHashCompatContext var hc: BrHashCompatContext
var hash: array[32, byte] var hash: array[32, byte]
var impl = brEcGetDefault() var impl = brEcGetDefault()
if seckey.key.curve in EcSupportedCurvesCint: if seckey.key.curve in EcSupportedCurvesCint:
result = new EcSignature var sig = new EcSignature
result.buffer = newSeq[byte](256) sig.buffer = newSeq[byte](256)
var kv = addr sha256Vtable var kv = addr sha256Vtable
kv.init(addr hc.vtable) kv.init(addr hc.vtable)
if len(message) > 0: if len(message) > 0:
@ -875,15 +940,16 @@ proc sign*[T: byte|char](seckey: EcPrivateKey,
kv.update(addr hc.vtable, nil, 0) kv.update(addr hc.vtable, nil, 0)
kv.output(addr hc.vtable, addr hash[0]) kv.output(addr hc.vtable, addr hash[0])
let res = brEcdsaSignAsn1(impl, kv, addr hash[0], addr seckey.key, let res = brEcdsaSignAsn1(impl, kv, addr hash[0], addr seckey.key,
addr result.buffer[0]) addr sig.buffer[0])
# Clear context with initial value # Clear context with initial value
kv.init(addr hc.vtable) kv.init(addr hc.vtable)
if res != 0: if res != 0:
result.buffer.setLen(res) sig.buffer.setLen(res)
ok(sig)
else: else:
raise newException(EcSignatureError, "Could not make signature") err(EcSignatureError)
else: else:
raise newException(EcKeyIncorrectError, "Incorrect private key") err(EcKeyIncorrectError)
proc verify*[T: byte|char](sig: EcSignature, message: openarray[T], proc verify*[T: byte|char](sig: EcSignature, message: openarray[T],
pubkey: EcPublicKey): bool {.inline.} = pubkey: EcPublicKey): bool {.inline.} =

View File

@ -10,8 +10,13 @@
## This module implements ED25519. ## This module implements ED25519.
## This code is a port of the public domain, "ref10" implementation of ed25519 ## This code is a port of the public domain, "ref10" implementation of ed25519
## from SUPERCOP. ## from SUPERCOP.
{.push raises: Defect.}
import constants import constants
import nimcrypto/[hash, sha2, sysrand, utils] import nimcrypto/[hash, sha2, sysrand, utils]
import stew/results
export results
# This workaround needed because of some bugs in Nim Static[T]. # This workaround needed because of some bugs in Nim Static[T].
export hash, sha2 export hash, sha2
@ -38,9 +43,9 @@ type
seckey*: EdPrivateKey seckey*: EdPrivateKey
pubkey*: EdPublicKey pubkey*: EdPublicKey
EdError* = object of CatchableError EdError* = enum
EdRngError* = object of EdError EdRngError,
EdIncorrectError* = object of EdError EdIncorrectError
proc `-`(x: uint32): uint32 {.inline.} = proc `-`(x: uint32): uint32 {.inline.} =
result = (0xFFFF_FFFF'u32 - x) + 1'u32 result = (0xFFFF_FFFF'u32 - x) + 1'u32
@ -1632,40 +1637,47 @@ proc checkScalar*(scalar: openarray[byte]): uint32 =
for u in scalar: for u in scalar:
z = z or u z = z or u
if len(scalar) == len(CurveOrder): 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])) c = c or (-(cast[int32](EQ0(c))) and CMP(scalar[i], CurveOrder[i]))
else: else:
c = -1 c = -1
result = NEQ(z, 0'u32) and LT0(c) 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. ## Generate new random ED25519 private key using OS specific CSPRNG.
var var
point: GeP3 point: GeP3
pk: array[EdPublicKeySize, byte] pk: array[EdPublicKeySize, byte]
if randomBytes(result.data.toOpenArray(0, 31)) != 32: res: EdPrivateKey
raise newException(EdRngError, "Could not generate random data") if randomBytes(res.data.toOpenArray(0, 31)) != 32:
var hh = sha512.digest(result.data.toOpenArray(0, 31)) err(EdRngError)
hh.data[0] = hh.data[0] and 0xF8'u8 else:
hh.data[31] = hh.data[31] and 0x3F'u8 var hh = sha512.digest(res.data.toOpenArray(0, 31))
hh.data[31] = hh.data[31] or 0x40'u8 hh.data[0] = hh.data[0] and 0xF8'u8
geScalarMultBase(point, hh.data) hh.data[31] = hh.data[31] and 0x3F'u8
geP3ToBytes(pk, point) hh.data[31] = hh.data[31] or 0x40'u8
copyMem(addr result.data[32], addr pk[0], 32) 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 ## Generate new random ED25519 private and public keypair using OS specific
## CSPRNG. ## CSPRNG.
var point: GeP3 var
if randomBytes(result.seckey.data.toOpenArray(0, 31)) != 32: point: GeP3
raise newException(EdRngError, "Could not generate random data") res: EdKeyPair
var hh = sha512.digest(result.seckey.data.toOpenArray(0, 31)) if randomBytes(res.seckey.data.toOpenArray(0, 31)) != 32:
hh.data[0] = hh.data[0] and 0xF8'u8 err(EdRngError)
hh.data[31] = hh.data[31] and 0x3F'u8 else:
hh.data[31] = hh.data[31] or 0x40'u8 var hh = sha512.digest(res.seckey.data.toOpenArray(0, 31))
geScalarMultBase(point, hh.data) hh.data[0] = hh.data[0] and 0xF8'u8
geP3ToBytes(result.pubkey.data, point) hh.data[31] = hh.data[31] and 0x3F'u8
copyMem(addr result.seckey.data[32], addr result.pubkey.data[0], 32) 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 = proc getKey*(key: EdPrivateKey): EdPublicKey =
## Calculate and return ED25519 public key from private key ``key``. ## Calculate and return ED25519 public key from private key ``key``.
@ -1766,57 +1778,84 @@ proc init*(key: var EdPrivateKey, data: string): bool =
## representation ``data``. ## representation ``data``.
## ##
## Procedure returns ``true`` on success. ## 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 = proc init*(key: var EdPublicKey, data: string): bool =
## Initialize ED25519 `public key` ``key`` from hexadecimal string ## Initialize ED25519 `public key` ``key`` from hexadecimal string
## representation ``data``. ## representation ``data``.
## ##
## Procedure returns ``true`` on success. ## 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 = proc init*(sig: var EdSignature, data: string): bool =
## Initialize ED25519 `signature` ``sig`` from hexadecimal string ## Initialize ED25519 `signature` ``sig`` from hexadecimal string
## representation ``data``. ## representation ``data``.
## ##
## Procedure returns ``true`` on success. ## 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`` ## Initialize ED25519 `private key` from raw binary representation ``data``
## and return constructed object. ## and return constructed object.
if not init(result, data): var res: t
raise newException(EdIncorrectError, "Incorrect binary form") 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`` ## Initialize ED25519 `public key` from raw binary representation ``data``
## and return constructed object. ## and return constructed object.
if not init(result, data): var res: t
raise newException(EdIncorrectError, "Incorrect binary form") 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`` ## Initialize ED25519 `signature` from raw binary representation ``data``
## and return constructed object. ## and return constructed object.
if not init(result, data): var res: t
raise newException(EdIncorrectError, "Incorrect binary form") 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 ## Initialize ED25519 `private key` from hexadecimal string representation
## ``data`` and return constructed object. ## ``data`` and return constructed object.
if not init(result, data): var res: t
raise newException(EdIncorrectError, "Incorrect binary form") 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 ## Initialize ED25519 `public key` from hexadecimal string representation
## ``data`` and return constructed object. ## ``data`` and return constructed object.
if not init(result, data): var res: t
raise newException(EdIncorrectError, "Incorrect binary form") 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 ## Initialize ED25519 `signature` from hexadecimal string representation
## ``data`` and return constructed object. ## ``data`` and return constructed object.
if not init(result, data): var res: t
raise newException(EdIncorrectError, "Incorrect binary form") if not init(res, data):
err(EdIncorrectError)
else:
ok(res)
proc clear*(key: var EdPrivateKey) = proc clear*(key: var EdPrivateKey) =
## Wipe and clear memory of ED25519 `private key`. ## Wipe and clear memory of ED25519 `private key`.

View File

@ -106,10 +106,10 @@ const
## Encoded ``NULL`` value. ## Encoded ``NULL`` value.
template toOpenArray*(ab: Asn1Buffer): untyped = 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 = 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 = template toOpenArray*(af: Asn1Field): untyped =
toOpenArray(af.buffer, af.offset, af.offset + af.length - 1) 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 += asn1EncodeLength(buffer, oidlen)
result += oidlen result += oidlen
if len(dest) >= result: if len(dest) >= result:
let last = len(dest) - 1 let last = dest.high
var offset = 1 var offset = 1
dest[0] = Asn1Tag.Oid.code() dest[0] = Asn1Tag.Oid.code()
offset += asn1EncodeLength(dest.toOpenArray(offset, last), oidlen) offset += asn1EncodeLength(dest.toOpenArray(offset, last), oidlen)

View File

@ -12,6 +12,9 @@
## This module uses unmodified parts of code from ## This module uses unmodified parts of code from
## BearSSL library <https://bearssl.org/> ## BearSSL library <https://bearssl.org/>
## Copyright(C) 2018 Thomas Pornin <pornin@bolet.org>. ## Copyright(C) 2018 Thomas Pornin <pornin@bolet.org>.
{.push raises: Defect.}
import nimcrypto/utils import nimcrypto/utils
import bearssl import bearssl
import minasn1 import minasn1
@ -72,11 +75,13 @@ type
RsaPKI* = RsaPrivateKey | RsaPublicKey | RsaSignature RsaPKI* = RsaPrivateKey | RsaPublicKey | RsaSignature
RsaKP* = RsaPrivateKey | RsaKeyPair RsaKP* = RsaPrivateKey | RsaKeyPair
RsaError* = object of CatchableError RsaError* = enum
RsaRngError* = object of RsaError RsaRngError,
RsaGenError* = object of RsaError RsaGenError,
RsaKeyIncorrectError* = object of RsaError RsaKeyIncorrectError,
RsaSignatureError* = object of RsaError RsaSignatureError
RsaResult*[T] = Result[T, RsaError]
template getStart(bs, os, ls: untyped): untyped = template getStart(bs, os, ls: untyped): untyped =
let p = cast[uint](os) let p = cast[uint](os)
@ -108,7 +113,7 @@ template trimZeroes(b: seq[byte], pt, ptlen: untyped) =
ptlen -= 1 ptlen -= 1
proc random*[T: RsaKP](t: typedesc[T], bits = DefaultKeySize, 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 ## Generate new random RSA private key using BearSSL's HMAC-SHA256-DRBG
## algorithm. ## algorithm.
## ##
@ -121,7 +126,8 @@ proc random*[T: RsaKP](t: typedesc[T], bits = DefaultKeySize,
var seeder = brPrngSeederSystem(nil) var seeder = brPrngSeederSystem(nil)
brHmacDrbgInit(addr rng, addr sha256Vtable, nil, 0) brHmacDrbgInit(addr rng, addr sha256Vtable, nil, 0)
if seeder(addr rng.vtable) == 0: if seeder(addr rng.vtable) == 0:
raise newException(RsaRngError, "Could not seed RNG") return err(RsaRngError)
keygen = brRsaKeygenGetDefault() keygen = brRsaKeygenGetDefault()
let length = brRsaPrivateKeyBufferSize(bits) + let length = brRsaPrivateKeyBufferSize(bits) +
@ -131,34 +137,38 @@ proc random*[T: RsaKP](t: typedesc[T], bits = DefaultKeySize,
let pko = brRsaPrivateKeyBufferSize(bits) let pko = brRsaPrivateKeyBufferSize(bits)
let eko = pko + brRsaPublicKeyBufferSize(bits) let eko = pko + brRsaPublicKeyBufferSize(bits)
when T is RsaKeyPair: var res: T
result = new RsaKeyPair
else:
result = new RsaPrivateKey
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, if keygen(addr rng.vtable,
addr result.seck, addr result.buffer[sko], addr res.seck, addr res.buffer[sko],
addr result.pubk, addr result.buffer[pko], addr res.pubk, addr res.buffer[pko],
cuint(bits), pubexp) == 0: cuint(bits), pubexp) == 0:
raise newException(RsaGenError, "Could not create private key") return err(RsaGenError)
let compute = brRsaComputePrivexpGetDefault() let compute = brRsaComputePrivexpGetDefault()
let res = compute(addr result.buffer[eko], addr result.seck, pubexp) let computed = compute(addr res.buffer[eko], addr res.seck, pubexp)
if res == 0: if computed == 0:
raise newException(RsaGenError, "Could not create private key") return err(RsaGenError)
result.pexp = cast[ptr cuchar](addr result.buffer[eko]) res.pexp = cast[ptr cuchar](addr res.buffer[eko])
result.pexplen = res res.pexplen = computed
trimZeroes(result.buffer, result.seck.p, result.seck.plen) trimZeroes(res.buffer, res.seck.p, res.seck.plen)
trimZeroes(result.buffer, result.seck.q, result.seck.qlen) trimZeroes(res.buffer, res.seck.q, res.seck.qlen)
trimZeroes(result.buffer, result.seck.dp, result.seck.dplen) trimZeroes(res.buffer, res.seck.dp, res.seck.dplen)
trimZeroes(result.buffer, result.seck.dq, result.seck.dqlen) trimZeroes(res.buffer, res.seck.dq, res.seck.dqlen)
trimZeroes(result.buffer, result.seck.iq, result.seck.iqlen) trimZeroes(res.buffer, res.seck.iq, res.seck.iqlen)
trimZeroes(result.buffer, result.pubk.n, result.pubk.nlen) trimZeroes(res.buffer, res.pubk.n, res.pubk.nlen)
trimZeroes(result.buffer, result.pubk.e, result.pubk.elen) trimZeroes(res.buffer, res.pubk.e, res.pubk.elen)
trimZeroes(result.buffer, result.pexp, result.pexplen) trimZeroes(res.buffer, res.pexp, res.pexplen)
ok(res)
proc copy*[T: RsaPKI](key: T): T = proc copy*[T: RsaPKI](key: T): T =
## Create copy of RSA private key, public key or signature. ## 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) burnMem(pki.buffer)
pki.buffer.setLen(0) 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 ## Serialize RSA private key ``key`` to ASN.1 DER binary form and store it
## to ``data``. ## to ``data``.
## ##
## Procedure returns number of bytes (octets) needed to store RSA private key, ## Procedure returns number of bytes (octets) needed to store RSA private key,
## or `0` if private key is is incorrect. ## or `0` if private key is is incorrect.
doAssert(not isNil(key)) if isNil(key):
if len(key.buffer) > 0: err(RsaKeyIncorrectError)
elif len(key.buffer) > 0:
var b = Asn1Buffer.init() var b = Asn1Buffer.init()
var p = Asn1Composite.init(Asn1Tag.Sequence) var p = Asn1Composite.init(Asn1Tag.Sequence)
p.write(0'u64) p.write(0'u64)
@ -304,18 +315,22 @@ proc toBytes*(key: RsaPrivateKey, data: var openarray[byte]): int =
p.finish() p.finish()
b.write(p) b.write(p)
b.finish() b.finish()
result = len(b) var blen = len(b)
if len(data) >= result: if len(data) >= blen:
copyMem(addr data[0], addr b.buffer[0], result) 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 ## Serialize RSA public key ``key`` to ASN.1 DER binary form and store it
## to ``data``. ## to ``data``.
## ##
## Procedure returns number of bytes (octets) needed to store RSA public key, ## Procedure returns number of bytes (octets) needed to store RSA public key,
## or `0` if public key is incorrect. ## or `0` if public key is incorrect.
doAssert(not isNil(key)) if isNil(key):
if len(key.buffer) > 0: err(RsaKeyIncorrectError)
elif len(key.buffer) > 0:
var b = Asn1Buffer.init() var b = Asn1Buffer.init()
var p = Asn1Composite.init(Asn1Tag.Sequence) var p = Asn1Composite.init(Asn1Tag.Sequence)
var c0 = 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() p.finish()
b.write(p) b.write(p)
b.finish() b.finish()
result = len(b) var blen = len(b)
if len(data) >= result: if len(data) >= blen:
copyMem(addr data[0], addr b.buffer[0], result) 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 ## Serialize RSA signature ``sig`` to raw binary form and store it
## to ``data``. ## to ``data``.
## ##
## Procedure returns number of bytes (octets) needed to store RSA public key, ## Procedure returns number of bytes (octets) needed to store RSA public key,
## or `0` if public key is incorrect. ## or `0` if public key is incorrect.
doAssert(not isNil(sig)) if isNil(sig):
result = len(sig.buffer) err(RsaSignatureError)
if len(data) >= result: else:
copyMem(addr data[0], addr sig.buffer[0], result) 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 ## Serialize RSA private key ``key`` to ASN.1 DER binary form and
## return it. ## return it.
doAssert(not isNil(key)) if isNil(key):
result = newSeq[byte](4096) return err(RsaKeyIncorrectError)
let length = key.toBytes(result) var res = newSeq[byte](4096)
let length = ? key.toBytes(res)
if length > 0: if length > 0:
result.setLen(length) res.setLen(length)
ok(res)
else: 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 ## Serialize RSA public key ``key`` to ASN.1 DER binary form and
## return it. ## return it.
doAssert(not isNil(key)) if isNil(key):
result = newSeq[byte](4096) return err(RsaKeyIncorrectError)
let length = key.toBytes(result) var res = newSeq[byte](4096)
let length = ? key.toBytes(res)
if length > 0: if length > 0:
result.setLen(length) res.setLen(length)
ok(res)
else: 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. ## Serialize RSA signature ``sig`` to raw binary form and return it.
doAssert(not isNil(sig)) if isNil(sig):
result = newSeq[byte](4096) return err(RsaSignatureError)
let length = sig.toBytes(result) var res = newSeq[byte](4096)
let length = ? sig.toBytes(res)
if length > 0: if length > 0:
result.setLen(length) res.setLen(length)
ok(res)
else: else:
raise newException(RsaSignatureError, "Incorrect signature") err(RsaSignatureError)
proc init*(key: var RsaPrivateKey, data: openarray[byte]): Result[void, Asn1Error] = proc init*(key: var RsaPrivateKey, data: openarray[byte]): Result[void, Asn1Error] =
## Initialize RSA private key ``key`` from ASN.1 DER binary representation ## 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]``. ## Procedure returns ``Result[void, Asn1Status]``.
sospk.init(fromHex(data)) 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`` ## Initialize RSA private key from ASN.1 DER binary representation ``data``
## and return constructed object. ## and return constructed object.
let res = result.init(data) var res: RsaPrivateKey
if res.isErr: if res.init(data).isErr:
raise newException(RsaKeyIncorrectError, err(RsaKeyIncorrectError)
"Incorrect private key (" & $res.error & ")") 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`` ## Initialize RSA public key from ASN.1 DER binary representation ``data``
## and return constructed object. ## and return constructed object.
let res = result.init(data) var res: RsaPublicKey
if res.isErr: if res.init(data).isErr:
raise newException(RsaKeyIncorrectError, err(RsaKeyIncorrectError)
"Incorrect public key (" & $res.error & ")") 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 ## Initialize RSA signature from raw binary representation ``data`` and
## return constructed object. ## return constructed object.
let res = result.init(data) var res: RsaSignature
if res.isErr: if res.init(data).isErr:
raise newException(RsaKeyIncorrectError, err(RsaSignatureError)
"Incorrect signature (" & $res.error & ")") else:
ok(res)
proc init*[T: RsaPKI](t: typedesc[T], data: string): T {.inline.} = proc init*[T: RsaPKI](t: typedesc[T], data: string): T {.inline.} =
## Initialize RSA `private key`, `public key` or `signature` from hexadecimal ## Initialize RSA `private key`, `public key` or `signature` from hexadecimal
@ -714,15 +744,17 @@ proc `==`*(a, b: RsaPublicKey): bool =
result = r1 and r2 result = r1 and r2
proc sign*[T: byte|char](key: RsaPrivateKey, 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 ## Get RSA PKCS1.5 signature of data ``message`` using SHA256 and private
## key ``key``. ## key ``key``.
doAssert(not isNil(key)) if isNil(key):
return err(RsaKeyIncorrectError)
var hc: BrHashCompatContext var hc: BrHashCompatContext
var hash: array[32, byte] var hash: array[32, byte]
let impl = BrRsaPkcs1SignGetDefault() let impl = BrRsaPkcs1SignGetDefault()
result = new RsaSignature var res = new RsaSignature
result.buffer = newSeq[byte]((key.seck.nBitlen + 7) shr 3) res.buffer = newSeq[byte]((key.seck.nBitlen + 7) shr 3)
var kv = addr sha256Vtable var kv = addr sha256Vtable
kv.init(addr hc.vtable) kv.init(addr hc.vtable)
if len(message) > 0: if len(message) > 0:
@ -731,11 +763,13 @@ proc sign*[T: byte|char](key: RsaPrivateKey,
kv.update(addr hc.vtable, nil, 0) kv.update(addr hc.vtable, nil, 0)
kv.output(addr hc.vtable, addr hash[0]) kv.output(addr hc.vtable, addr hash[0])
var oid = RsaOidSha256 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), cast[ptr cuchar](addr hash[0]), len(hash),
addr key.seck, cast[ptr cuchar](addr result.buffer[0])) addr key.seck, cast[ptr cuchar](addr res.buffer[0]))
if res == 0: if implRes == 0:
raise newException(RsaSignatureError, "Signature generation error") err(RsaSignatureError)
else:
ok(res)
proc verify*[T: byte|char](sig: RsaSignature, message: openarray[T], proc verify*[T: byte|char](sig: RsaSignature, message: openarray[T],
pubkey: RsaPublicKey): bool {.inline.} = pubkey: RsaPublicKey): bool {.inline.} =

View File

@ -6,8 +6,15 @@
## at your option. ## at your option.
## This file may not be copied, modified, or distributed except according to ## This file may not be copied, modified, or distributed except according to
## those terms. ## 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 export sha2
import stew/results
export results
export secp256k1
const const
SkRawPrivateKeySize* = 256 div 8 SkRawPrivateKeySize* = 256 div 8
@ -18,169 +25,125 @@ const
## Size of public key in octets (bytes) ## Size of public key in octets (bytes)
type type
SkPublicKey* = distinct s.SkPublicKey SkPrivateKey* = SkSecretKey
SkPrivateKey* = distinct s.SkSecretKey
SkKeyPair* = distinct s.SkKeyPair
SkSignature* = distinct s.SkSignature
Secp256k1Error* = object of CatchableError template pubkey*(v: SkKeyPair): SkPublicKey = SkPublicKey(SkKeyPair(v).pubkey)
## Exceptions generated by `libsecp256k1` template seckey*(v: SkKeyPair): SkPrivateKey = SkPrivateKey(SkKeyPair(v).seckey)
template toException(v: cstring): (ref Secp256k1Error) = proc init*(key: var SkPrivateKey, data: openarray[byte]): SkResult[void] =
(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].} =
## Initialize Secp256k1 `private key` ``key`` from raw binary ## Initialize Secp256k1 `private key` ``key`` from raw binary
## representation ``data``. ## representation ``data``.
## key = ? SkSecretKey.fromRaw(data)
## Procedure returns ``true`` on success. ok()
if (let v = SkSecretKey.fromRaw(data); v.isOk):
key = SkPrivateKey(v[])
return true
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 ## Initialize Secp256k1 `private key` ``key`` from hexadecimal string
## representation ``data``. ## representation ``data``.
## key = ? SkSecretKey.fromHex(data)
## Procedure returns ``true`` on success. ok()
try:
key = SkPrivateKey(SkSecretKey.fromHex(data).tryGet())
return true
except Secp256k1Error:
discard
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 ## Initialize Secp256k1 `public key` ``key`` from raw binary
## representation ``data``. ## representation ``data``.
## key = ? SkPublicKey.fromRaw(data)
## Procedure returns ``true`` on success. ok()
try:
key = SkPublicKey(s.SkPublicKey.fromRaw(data).tryGet())
return true
except Secp256k1Error:
discard
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 ## Initialize Secp256k1 `public key` ``key`` from hexadecimal string
## representation ``data``. ## representation ``data``.
## key = ? SkPublicKey.fromHex(data)
## Procedure returns ``true`` on success. ok()
try:
key = SkPublicKey(s.SkPublicKey.fromHex(data).tryGet())
return true
except Secp256k1Error:
discard
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 ## Initialize Secp256k1 `signature` ``sig`` from raw binary
## representation ``data``. ## representation ``data``.
## sig = ? SkSignature.fromDer(data)
## Procedure returns ``true`` on success. ok()
try:
sig = SkSignature(s.SkSignature.fromDer(data).tryGet())
return true
except Secp256k1Error:
discard
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 ## Initialize Secp256k1 `signature` ``sig`` from hexadecimal string
## representation ``data``. ## representation ``data``.
##
## Procedure returns ``true`` on success.
# TODO DER vs raw here is fishy # TODO DER vs raw here is fishy
var buffer: seq[byte] var buffer: seq[byte]
try: try:
buffer = hexToSeqByte(data) buffer = hexToSeqByte(data)
except ValueError: except ValueError:
return false return err("Hex to bytes failed")
result = init(sig, buffer) init(sig, buffer)
proc init*(t: typedesc[SkPrivateKey], proc init*(t: typedesc[SkPrivateKey], data: openarray[byte]): SkResult[SkPrivateKey] =
data: openarray[byte]): SkPrivateKey {.raises: [Defect, Secp256k1Error].} =
## Initialize Secp256k1 `private key` from raw binary ## Initialize Secp256k1 `private key` from raw binary
## representation ``data``. ## representation ``data``.
## ##
## Procedure returns `private key` on success. ## Procedure returns `private key` on success.
SkPrivateKey(s.SkSecretKey.fromRaw(data).tryGet()) SkSecretKey.fromRaw(data)
proc init*(t: typedesc[SkPrivateKey], proc init*(t: typedesc[SkPrivateKey], data: string): SkResult[SkPrivateKey] =
data: string): SkPrivateKey {.raises: [Defect, Secp256k1Error].} =
## Initialize Secp256k1 `private key` from hexadecimal string ## Initialize Secp256k1 `private key` from hexadecimal string
## representation ``data``. ## representation ``data``.
## ##
## Procedure returns `private key` on success. ## Procedure returns `private key` on success.
s.SkSecretKey.fromHex(data).tryGet() SkSecretKey.fromHex(data)
proc init*(t: typedesc[SkPublicKey], proc init*(t: typedesc[SkPublicKey], data: openarray[byte]): SkResult[SkPublicKey] =
data: openarray[byte]): SkPublicKey {.raises: [Defect, Secp256k1Error].} =
## Initialize Secp256k1 `public key` from raw binary ## Initialize Secp256k1 `public key` from raw binary
## representation ``data``. ## representation ``data``.
## ##
## Procedure returns `public key` on success. ## Procedure returns `public key` on success.
if not init(result, data): var key: SkPublicKey
raise newException(Secp256k1Error, "Incorrect binary form") key.init(data) and ok(key)
proc init*(t: typedesc[SkPublicKey], proc init*(t: typedesc[SkPublicKey], data: string): SkResult[SkPublicKey] =
data: string): SkPublicKey {.raises: [Defect, Secp256k1Error].} =
## Initialize Secp256k1 `public key` from hexadecimal string ## Initialize Secp256k1 `public key` from hexadecimal string
## representation ``data``. ## representation ``data``.
## ##
## Procedure returns `public key` on success. ## Procedure returns `public key` on success.
if not init(result, data): var key: SkPublicKey
raise newException(Secp256k1Error, "Incorrect binary form") key.init(data) and ok(key)
proc init*(t: typedesc[SkSignature], proc init*(t: typedesc[SkSignature], data: openarray[byte]): SkResult[SkSignature] =
data: openarray[byte]): SkSignature {.raises: [Defect, Secp256k1Error].} =
## Initialize Secp256k1 `signature` from raw binary ## Initialize Secp256k1 `signature` from raw binary
## representation ``data``. ## representation ``data``.
## ##
## Procedure returns `signature` on success. ## Procedure returns `signature` on success.
if not init(result, data): var sig: SkSignature
raise newException(Secp256k1Error, "Incorrect binary form") sig.init(data) and ok(sig)
proc init*(t: typedesc[SkSignature], proc init*(t: typedesc[SkSignature], data: string): SkResult[SkSignature] =
data: string): SkSignature {.raises: [Defect, Secp256k1Error].} =
## Initialize Secp256k1 `signature` from hexadecimal string ## Initialize Secp256k1 `signature` from hexadecimal string
## representation ``data``. ## representation ``data``.
## ##
## Procedure returns `signature` on success. ## Procedure returns `signature` on success.
if not init(result, data): var sig: SkSignature
raise newException(Secp256k1Error, "Incorrect binary form") 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``. ## Calculate and return Secp256k1 `public key` from `private key` ``key``.
SkPublicKey(s.SkSecretKey(key).toPublicKey().tryGet()) key.toPublicKey()
proc random*(t: typedesc[SkPrivateKey]): SkPrivateKey = proc toBytes*(key: SkPrivateKey, data: var openarray[byte]): SkResult[int] =
## 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 =
## Serialize Secp256k1 `private key` ``key`` to raw binary form and store it ## Serialize Secp256k1 `private key` ``key`` to raw binary form and store it
## to ``data``. ## to ``data``.
## ##
## Procedure returns number of bytes (octets) needed to store ## Procedure returns number of bytes (octets) needed to store
## Secp256k1 private key. ## Secp256k1 private key.
result = SkRawPrivateKeySize
if len(data) >= SkRawPrivateKeySize: if len(data) >= SkRawPrivateKeySize:
data[0..<SkRawPrivateKeySize] = s.SkSecretKey(key).toRaw() data[0..<SkRawPrivateKeySize] = SkSecretKey(key).toRaw()
ok(SkRawPrivateKeySize)
else:
err("Not enough bytes")
proc toBytes*(key: SkPublicKey, data: var openarray[byte]): int = proc toBytes*(key: SkPublicKey, data: var openarray[byte]): SkResult[int] =
## Serialize Secp256k1 `public key` ``key`` to raw binary form and store it ## Serialize Secp256k1 `public key` ``key`` to raw binary form and store it
## to ``data``. ## to ``data``.
## ##
## Procedure returns number of bytes (octets) needed to store ## Procedure returns number of bytes (octets) needed to store
## Secp256k1 public key. ## Secp256k1 public key.
result = SkRawPublicKeySize
if len(data) >= SkRawPublicKeySize: if len(data) >= SkRawPublicKeySize:
data[0..<SkRawPublicKeySize] = s.SkPublicKey(key).toRawCompressed() data[0..<SkRawPublicKeySize] = key.toRawCompressed()
ok(SkRawPublicKeySize)
else:
err("Not enough bytes")
proc toBytes*(sig: SkSignature, data: var openarray[byte]): int = proc toBytes*(sig: SkSignature, data: var openarray[byte]): int =
## Serialize Secp256k1 `signature` ``sig`` to raw binary form and store it ## Serialize Secp256k1 `signature` ``sig`` to raw binary form and store it
@ -188,15 +151,15 @@ proc toBytes*(sig: SkSignature, data: var openarray[byte]): int =
## ##
## Procedure returns number of bytes (octets) needed to store ## Procedure returns number of bytes (octets) needed to store
## Secp256k1 signature. ## Secp256k1 signature.
s.SkSignature(sig).toDer(data) sig.toDer(data)
proc getBytes*(key: SkPrivateKey): seq[byte] {.inline.} = proc getBytes*(key: SkPrivateKey): seq[byte] {.inline.} =
## Serialize Secp256k1 `private key` and return it. ## Serialize Secp256k1 `private key` and return it.
result = @(s.SkSecretKey(key).toRaw()) result = @(SkSecretKey(key).toRaw())
proc getBytes*(key: SkPublicKey): seq[byte] {.inline.} = proc getBytes*(key: SkPublicKey): seq[byte] {.inline.} =
## Serialize Secp256k1 `public key` and return it. ## Serialize Secp256k1 `public key` and return it.
result = @(s.SkPublicKey(key).toRawCompressed()) result = @(key.toRawCompressed())
proc getBytes*(sig: SkSignature): seq[byte] {.inline.} = proc getBytes*(sig: SkSignature): seq[byte] {.inline.} =
## Serialize Secp256k1 `signature` and return it. ## Serialize Secp256k1 `signature` and return it.
@ -204,49 +167,12 @@ proc getBytes*(sig: SkSignature): seq[byte] {.inline.} =
let length = toBytes(sig, result) let length = toBytes(sig, result)
result.setLen(length) result.setLen(length)
proc `==`*(ska, skb: SkPrivateKey): bool = proc sign*[T: byte|char](key: SkPrivateKey, msg: openarray[T]): SkResult[SkSignature] =
## Compare Secp256k1 `private key` objects for equality.
result = (s.SkSecretKey(ska).toRaw == s.SkSecretKey(skb).toRaw)
proc `==`*(pka, pkb: SkPublicKey): bool =
## Compare Secp256k1 `public key` objects for equality.
result = (s.SkPublicKey(pka).toRaw == s.SkPublicKey(pkb).toRaw)
proc `==`*(sia, sib: SkSignature): bool =
## Compare Secp256k1 `signature` objects for equality.
result = (s.SkSignature(sia).toRaw == s.SkSignature(sib).toRaw)
proc `$`*(key: SkPrivateKey): string = s.SkSecretKey(key).toHex()
## Return string representation of Secp256k1 `private key`.
proc `$`*(key: SkPublicKey): string =
## Return string representation of Secp256k1 `private key`.s
result = toHex(s.SkPublicKey(key).toRawCompressed())
proc `$`*(sig: SkSignature): string =
## Return string representation of Secp256k1 `signature`.s
result = toHex(s.SkSignature(sig).toDer())
proc sign*[T: byte|char](key: SkPrivateKey, msg: openarray[T]): SkSignature =
## Sign message `msg` using private key `key` and return signature object. ## Sign message `msg` using private key `key` and return signature object.
let h = sha256.digest(msg) let h = sha256.digest(msg)
SkSignature(sign(s.SkSecretKey(key), h).tryGet()) sign(key, h)
proc verify*[T: byte|char](sig: SkSignature, msg: openarray[T], proc verify*[T: byte|char](sig: SkSignature, msg: openarray[T],
key: SkPublicKey): bool = key: SkPublicKey): bool =
let h = sha256.digest(msg) let h = sha256.digest(msg)
verify(s.SkSignature(sig), h, s.SkPublicKey(key)) verify(SkSignature(sig), h, SkPublicKey(key))
proc clear*(key: var SkPrivateKey) {.borrow.}
## Wipe and clear memory of Secp256k1 `private key`.
proc clear*(key: var SkPublicKey) {.borrow.}
## Wipe and clear memory of Secp256k1 `public key`.
proc clear*(sig: var SkSignature) {.borrow.}
## Wipe and clear memory of Secp256k1 `signature`.
# Internal memory representation size of signature object is 64 bytes.
proc clear*(pair: var SkKeyPair) {.borrow.}
proc verify*(seckey: SkPrivateKey): bool {.borrow.}

View File

@ -140,7 +140,7 @@ proc p2pStB(s: string, vb: var VBuffer): bool =
try: try:
var data = Base58.decode(s) var data = Base58.decode(s)
var mh: MultiHash var mh: MultiHash
if MultiHash.decode(data, mh) >= 0: if MultiHash.decode(data, mh).isOk:
vb.writeSeq(data) vb.writeSeq(data)
result = true result = true
except: except:
@ -151,7 +151,7 @@ proc p2pBtS(vb: var VBuffer, s: var string): bool =
var address = newSeq[byte]() var address = newSeq[byte]()
if vb.readSeq(address) > 0: if vb.readSeq(address) > 0:
var mh: MultiHash var mh: MultiHash
if MultiHash.decode(address, mh) >= 0: if MultiHash.decode(address, mh).isOk:
s = Base58.encode(address) s = Base58.encode(address)
result = true result = true
@ -160,7 +160,7 @@ proc p2pVB(vb: var VBuffer): bool =
var address = newSeq[byte]() var address = newSeq[byte]()
if vb.readSeq(address) > 0: if vb.readSeq(address) > 0:
var mh: MultiHash var mh: MultiHash
if MultiHash.decode(address, mh) >= 0: if MultiHash.decode(address, mh).isOk:
result = true result = true
proc onionStB(s: string, vb: var VBuffer): bool = proc onionStB(s: string, vb: var VBuffer): bool =
@ -426,12 +426,12 @@ const
proc trimRight(s: string, ch: char): string = proc trimRight(s: string, ch: char): string =
## Consume trailing characters ``ch`` from string ``s`` and return result. ## Consume trailing characters ``ch`` from string ``s`` and return result.
var m = 0 var m = 0
for i in countdown(len(s) - 1, 0): for i in countdown(s.high, 0):
if s[i] == ch: if s[i] == ch:
inc(m) inc(m)
else: else:
break break
result = s[0..(len(s) - 1 - m)] result = s[0..(s.high - m)]
proc shcopy*(m1: var MultiAddress, m2: MultiAddress) = proc shcopy*(m1: var MultiAddress, m2: MultiAddress) =
shallowCopy(m1.data.buffer, m2.data.buffer) shallowCopy(m1.data.buffer, m2.data.buffer)

View File

@ -392,7 +392,7 @@ proc encode*(mbtype: typedesc[MultiBase], encoding: string,
if isNil(mb.encr) or isNil(mb.encl): if isNil(mb.encr) or isNil(mb.encl):
return MultibaseStatus.NotSupported return MultibaseStatus.NotSupported
if len(outbytes) > 1: if len(outbytes) > 1:
result = mb.encr(inbytes, outbytes.toOpenArray(1, len(outbytes) - 1), result = mb.encr(inbytes, outbytes.toOpenArray(1, outbytes.high),
outlen) outlen)
if result == MultiBaseStatus.Overrun: if result == MultiBaseStatus.Overrun:
outlen += 1 outlen += 1
@ -452,7 +452,7 @@ proc encode*(mbtype: typedesc[MultiBase], encoding: string,
if length > 0: if length > 0:
buffer = newString(mb.encl(length) + 1) buffer = newString(mb.encl(length) + 1)
var outlen = 0 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: if res != MultiBaseStatus.Success:
raise newException(MultiBaseError, "Encoding error [" & $res & "]") raise newException(MultiBaseError, "Encoding error [" & $res & "]")
buffer.setLen(outlen + 1) buffer.setLen(outlen + 1)

View File

@ -8,8 +8,13 @@
## those terms. ## those terms.
## This module implements MultiCodec. ## This module implements MultiCodec.
{.push raises: [Defect].}
import tables, hashes import tables, hashes
import varint, vbuffer import varint, vbuffer
import stew/results
export results
{.deadCodeElim: on.} {.deadCodeElim: on.}
@ -230,7 +235,8 @@ const MultiCodecList = [
type type
MultiCodec* = distinct int MultiCodec* = distinct int
MultiCodecError* = object of CatchableError MultiCodecError* = enum
MultiCodecNotSupported
const const
InvalidMultiCodec* = MultiCodec(-1) InvalidMultiCodec* = MultiCodec(-1)
@ -251,37 +257,32 @@ const
proc multiCodec*(name: string): MultiCodec {.compileTime.} = proc multiCodec*(name: string): MultiCodec {.compileTime.} =
## Generate MultiCodec from string ``name`` at compile time. ## Generate MultiCodec from string ``name`` at compile time.
var code = NameCodecs.getOrDefault(name, -1) let code = NameCodecs.getOrDefault(name, -1)
if code == -1: doAssert(code != -1)
raise newException(MultiCodecError, MultiCodec(code)
"MultiCodec `" & name & "` not supported!")
result = MultiCodec(code)
proc multiCodec*(code: int): MultiCodec {.compileTime.} = proc multiCodec*(code: int): MultiCodec {.compileTime.} =
## Generate MultiCodec from integer ``code`` at compile time. ## Generate MultiCodec from integer ``code`` at compile time.
var name = CodeCodecs.getOrDefault(code, "") let name = CodeCodecs.getOrDefault(code, "")
if name == "": doAssert(name != "")
raise newException(MultiCodecError, MultiCodec(code)
"MultiCodec with code " & $code & " not supported!")
result = MultiCodec(code)
proc `$`*(mc: MultiCodec): string = proc `$`*(mc: MultiCodec): string =
## Returns string representation of MultiCodec ``mc``. ## Returns string representation of MultiCodec ``mc``.
result = CodeCodecs.getOrDefault(int(mc), "") let name = CodeCodecs.getOrDefault(int(mc), "")
if result == "": doAssert(name != "")
raise newException(MultiCodecError, name
"MultiCodec with code " & $int(mc) & " not supported!")
proc `==`*(mc: MultiCodec, name: string): bool {.inline.} = proc `==`*(mc: MultiCodec, name: string): bool {.inline.} =
## Compares MultiCodec ``mc`` with string ``name``. ## Compares MultiCodec ``mc`` with string ``name``.
var mcname = CodeCodecs.getOrDefault(int(mc), "") let mcname = CodeCodecs.getOrDefault(int(mc), "")
if mcname == "": if mcname == "":
return false return false
result = (mcname == name) result = (mcname == name)
proc `==`*(mc: MultiCodec, code: int): bool {.inline.} = proc `==`*(mc: MultiCodec, code: int): bool {.inline.} =
## Compares MultiCodec ``mc`` with integer ``code``. ## Compares MultiCodec ``mc`` with integer ``code``.
result = (int(mc) == code) (int(mc) == code)
proc `==`*(a, b: MultiCodec): bool = proc `==`*(a, b: MultiCodec): bool =
## Returns ``true`` if MultiCodecs ``a`` and ``b`` are equal. ## Returns ``true`` if MultiCodecs ``a`` and ``b`` are equal.
@ -293,13 +294,13 @@ proc `!=`*(a, b: MultiCodec): bool =
proc hash*(m: MultiCodec): Hash {.inline.} = proc hash*(m: MultiCodec): Hash {.inline.} =
## Hash procedure for tables. ## Hash procedure for tables.
result = hash(int(m)) hash(int(m))
proc codec*(mt: typedesc[MultiCodec], name: string): MultiCodec {.inline.} = proc codec*(mt: typedesc[MultiCodec], name: string): MultiCodec {.inline.} =
## Return MultiCodec from string representation ``name``. ## Return MultiCodec from string representation ``name``.
## If ``name`` is not valid multicodec name, then ``InvalidMultiCodec`` will ## If ``name`` is not valid multicodec name, then ``InvalidMultiCodec`` will
## be returned. ## be returned.
result = MultiCodec(NameCodecs.getOrDefault(name, -1)) MultiCodec(NameCodecs.getOrDefault(name, -1))
proc codec*(mt: typedesc[MultiCodec], code: int): MultiCodec {.inline.} = proc codec*(mt: typedesc[MultiCodec], code: int): MultiCodec {.inline.} =
## Return MultiCodec from integer representation ``code``. ## Return MultiCodec from integer representation ``code``.
@ -307,9 +308,9 @@ proc codec*(mt: typedesc[MultiCodec], code: int): MultiCodec {.inline.} =
## be returned. ## be returned.
let res = CodeCodecs.getOrDefault(code, "") let res = CodeCodecs.getOrDefault(code, "")
if res == "": if res == "":
result = InvalidMultiCodec InvalidMultiCodec
else: else:
result = MultiCodec(code) MultiCodec(code)
proc write*(vb: var VBuffer, mc: MultiCodec) {.inline.} = proc write*(vb: var VBuffer, mc: MultiCodec) {.inline.} =
## Write MultiCodec to buffer ``vb``. ## Write MultiCodec to buffer ``vb``.

View File

@ -20,19 +20,29 @@
## Hashes which are not yet supported ## Hashes which are not yet supported
## 1. SKEIN ## 1. SKEIN
## 2. MURMUR ## 2. MURMUR
{.push raises: [Defect].}
import tables import tables
import nimcrypto/[sha, sha2, keccak, blake2, hash, utils] import nimcrypto/[sha, sha2, keccak, blake2, hash, utils]
import varint, vbuffer, multicodec, multibase import varint, vbuffer, multicodec, multibase
import stew/base58 import stew/base58
import stew/results
export results
# This is workaround for Nim `import` bug. # This is workaround for Nim `import` bug.
export sha, sha2, keccak, blake2, hash, utils export sha, sha2, keccak, blake2, hash, utils
const const
MaxHashSize* = 128 MaxHashSize* = 128
ErrIncorrectName = "Incorrect hash name"
ErrNotSupported = "Hash not supported"
ErrWrongDigestSize = "Incorrect digest size"
ErrDecodeError = "Decoding error from bytes"
ErrParseError = "Parse error fromHex"
type type
MHashCoderProc* = proc(data: openarray[byte], MHashCoderProc* = proc(data: openarray[byte],
output: var openarray[byte]) {.nimcall, gcsafe.} output: var openarray[byte]) {.nimcall, gcsafe, raises: [Defect].}
MHash* = object MHash* = object
mcodec*: MultiCodec mcodec*: MultiCodec
size*: int size*: int
@ -44,7 +54,7 @@ type
size*: int size*: int
dpos*: int dpos*: int
MultiHashError* = object of CatchableError MhResult*[T] = Result[T, cstring]
proc identhash(data: openarray[byte], output: var openarray[byte]) = proc identhash(data: openarray[byte], output: var openarray[byte]) =
if len(output) > 0: if len(output) > 0:
@ -345,78 +355,87 @@ proc digestImplWithoutHash(hash: MHash, data: openarray[byte]): MultiHash =
result.data.finish() result.data.finish()
proc digest*(mhtype: typedesc[MultiHash], hashname: string, 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 ## Perform digest calculation using hash algorithm with name ``hashname`` on
## data array ``data``. ## data array ``data``.
let mc = MultiCodec.codec(hashname) let mc = MultiCodec.codec(hashname)
if mc == InvalidMultiCodec: if mc == InvalidMultiCodec:
raise newException(MultihashError, "Incorrect hash name") err(ErrIncorrectName)
let hash = CodeHashes.getOrDefault(mc) else:
if isNil(hash.coder): let hash = CodeHashes.getOrDefault(mc)
raise newException(MultihashError, "Hash not supported") if isNil(hash.coder):
result = digestImplWithHash(hash, data) err(ErrNotSupported)
else:
ok(digestImplWithHash(hash, data))
proc digest*(mhtype: typedesc[MultiHash], hashcode: int, 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 ## Perform digest calculation using hash algorithm with code ``hashcode`` on
## data array ``data``. ## data array ``data``.
let hash = CodeHashes.getOrDefault(hashcode) let hash = CodeHashes.getOrDefault(hashcode)
if isNil(hash.coder): if isNil(hash.coder):
raise newException(MultihashError, "Hash not supported") err(ErrNotSupported)
result = digestImplWithHash(hash, data) else:
ok(digestImplWithHash(hash, data))
proc init*[T](mhtype: typedesc[MultiHash], hashname: string, 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 ## Create MultiHash from nimcrypto's `MDigest` object and hash algorithm name
## ``hashname``. ## ``hashname``.
let mc = MultiCodec.codec(hashname) let mc = MultiCodec.codec(hashname)
if mc == InvalidMultiCodec: if mc == InvalidMultiCodec:
raise newException(MultihashError, "Incorrect hash name") err(ErrIncorrectName)
let hash = CodeHashes.getOrDefault(mc) else:
if isNil(hash.coder): let hash = CodeHashes.getOrDefault(mc)
raise newException(MultihashError, "Hash not supported") if isNil(hash.coder):
if hash.size != len(mdigest.data): err(ErrNotSupported)
raise newException(MultiHashError, "Incorrect MDigest[T] size") elif hash.size != len(mdigest.data):
result = digestImplWithoutHash(hash, mdigest.data) err(ErrWrongDigestSize)
else:
ok(digestImplWithoutHash(hash, mdigest.data))
proc init*[T](mhtype: typedesc[MultiHash], hashcode: MultiCodec, 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 ## Create MultiHash from nimcrypto's `MDigest` and hash algorithm code
## ``hashcode``. ## ``hashcode``.
let hash = CodeHashes.getOrDefault(hashcode) let hash = CodeHashes.getOrDefault(hashcode)
if isNil(hash.coder): if isNil(hash.coder):
raise newException(MultihashError, "Hash not supported") err(ErrNotSupported)
if (hash.size != 0) and (hash.size != len(mdigest.data)): elif (hash.size != 0) and (hash.size != len(mdigest.data)):
raise newException(MultiHashError, "Incorrect MDigest[T] size") err(ErrWrongDigestSize)
result = digestImplWithoutHash(hash, mdigest.data) else:
ok(digestImplWithoutHash(hash, mdigest.data))
proc init*(mhtype: typedesc[MultiHash], hashname: string, 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 ## Create MultiHash from array of bytes ``bdigest`` and hash algorithm code
## ``hashcode``. ## ``hashcode``.
let mc = MultiCodec.codec(hashname) let mc = MultiCodec.codec(hashname)
if mc == InvalidMultiCodec: if mc == InvalidMultiCodec:
raise newException(MultihashError, "Incorrect hash name") err(ErrIncorrectName)
let hash = CodeHashes.getOrDefault(mc) else:
if isNil(hash.coder): let hash = CodeHashes.getOrDefault(mc)
raise newException(MultihashError, "Hash not supported") if isNil(hash.coder):
if (hash.size != 0) and (hash.size != len(bdigest)): err(ErrNotSupported)
raise newException(MultiHashError, "Incorrect bdigest size") elif (hash.size != 0) and (hash.size != len(bdigest)):
result = digestImplWithoutHash(hash, bdigest) err(ErrWrongDigestSize)
else:
ok(digestImplWithoutHash(hash, bdigest))
proc init*(mhtype: typedesc[MultiHash], hashcode: MultiCodec, 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 ## Create MultiHash from array of bytes ``bdigest`` and hash algorithm code
## ``hashcode``. ## ``hashcode``.
let hash = CodeHashes.getOrDefault(hashcode) let hash = CodeHashes.getOrDefault(hashcode)
if isNil(hash.coder): if isNil(hash.coder):
raise newException(MultihashError, "Hash not supported") err(ErrNotSupported)
if (hash.size != 0) and (hash.size != len(bdigest)): elif (hash.size != 0) and (hash.size != len(bdigest)):
raise newException(MultiHashError, "Incorrect bdigest size") err(ErrWrongDigestSize)
result = digestImplWithoutHash(hash, bdigest) else:
ok(digestImplWithoutHash(hash, bdigest))
proc decode*(mhtype: typedesc[MultiHash], data: openarray[byte], 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``. ## Decode MultiHash value from array of bytes ``data``.
## ##
## On success decoded MultiHash will be stored into ``mhash`` and number of ## 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 code, size: uint64
var res, dpos: int var res, dpos: int
if len(data) < 2: if len(data) < 2:
return -1 return err(ErrDecodeError)
var vb = initVBuffer(data) var vb = initVBuffer(data)
if vb.isEmpty(): if vb.isEmpty():
return -1 return err(ErrDecodeError)
res = vb.readVarint(code) res = vb.readVarint(code)
if res == -1: if res == -1:
return -1 return err(ErrDecodeError)
dpos += res dpos += res
res = vb.readVarint(size) res = vb.readVarint(size)
if res == -1: if res == -1:
return -1 return err(ErrDecodeError)
dpos += res dpos += res
if size > 0x7FFF_FFFF'u64: if size > 0x7FFF_FFFF'u64:
return -1 return err(ErrDecodeError)
let hash = CodeHashes.getOrDefault(MultiCodec(code)) let hash = CodeHashes.getOrDefault(MultiCodec(code))
if isNil(hash.coder): if isNil(hash.coder):
return -1 return err(ErrDecodeError)
if (hash.size != 0) and (hash.size != int(size)): if (hash.size != 0) and (hash.size != int(size)):
return -1 return err(ErrDecodeError)
if not vb.isEnough(int(size)): if not vb.isEnough(int(size)):
return -1 return err(ErrDecodeError)
mhash = MultiHash.init(MultiCodec(code),
mhash = ? MultiHash.init(MultiCodec(code),
vb.buffer.toOpenArray(vb.offset, vb.buffer.toOpenArray(vb.offset,
vb.offset + int(size) - 1)) vb.offset + int(size) - 1))
result = vb.offset + int(size) ok(vb.offset + int(size))
proc validate*(mhtype: typedesc[MultiHash], data: openarray[byte]): bool = proc validate*(mhtype: typedesc[MultiHash], data: openarray[byte]): bool =
## Returns ``true`` if array of bytes ``data`` has correct MultiHash inside. ## 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 var res: VarintStatus
if len(data) < 2: if len(data) < 2:
return false return false
let last = len(data) - 1 let last = data.high
var offset = 0 var offset = 0
var length = 0 var length = 0
res = LP.getUVarint(data.toOpenArray(offset, last), length, code) res = LP.getUVarint(data.toOpenArray(offset, last), length, code)
@ -483,15 +510,20 @@ proc validate*(mhtype: typedesc[MultiHash], data: openarray[byte]): bool =
result = true result = true
proc init*(mhtype: typedesc[MultiHash], proc init*(mhtype: typedesc[MultiHash],
data: openarray[byte]): MultiHash {.inline.} = data: openarray[byte]): MhResult[MultiHash] {.inline.} =
## Create MultiHash from bytes array ``data``. ## Create MultiHash from bytes array ``data``.
if MultiHash.decode(data, result) == -1: var hash: MultiHash
raise newException(MultihashError, "Incorrect MultiHash binary format") 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``. ## Create MultiHash from hexadecimal string representation ``data``.
if MultiHash.decode(fromHex(data), result) == -1: var hash: MultiHash
raise newException(MultihashError, "Incorrect MultiHash binary format") try:
discard ? MultiHash.decode(fromHex(data), hash)
ok(hash)
except ValueError:
err(ErrParseError)
proc init58*(mhtype: typedesc[MultiHash], proc init58*(mhtype: typedesc[MultiHash],
data: string): MultiHash {.inline.} = data: string): MultiHash {.inline.} =
@ -518,7 +550,7 @@ proc `==`*[T](mh: MultiHash, mdigest: MDigest[T]): bool =
if len(mdigest.data) != mh.size: if len(mdigest.data) != mh.size:
return false return false
result = cmp(mh.data.buffer.toOpenArray(mh.dpos, mh.dpos + mh.size - 1), 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.} = proc `==`*[T](mdigest: MDigest[T], mh: MultiHash): bool {.inline.} =
## Compares MultiHash with nimcrypto's MDigest[T], returns ``true`` if ## Compares MultiHash with nimcrypto's MDigest[T], returns ``true`` if

View File

@ -91,7 +91,7 @@ proc hasPublicKey*(pid: PeerID): bool =
## Returns ``true`` if ``pid`` is small enough to hold public key inside. ## Returns ``true`` if ``pid`` is small enough to hold public key inside.
if len(pid.data) > 0: if len(pid.data) > 0:
var mh: MultiHash var mh: MultiHash
if MultiHash.decode(pid.data, mh) > 0: if MultiHash.decode(pid.data, mh).isOk:
if mh.mcodec == multiCodec("identity"): if mh.mcodec == multiCodec("identity"):
result = true result = true
@ -102,7 +102,7 @@ proc extractPublicKey*(pid: PeerID, pubkey: var PublicKey): bool =
## Returns ``false`` otherwise. ## Returns ``false`` otherwise.
var mh: MultiHash var mh: MultiHash
if len(pid.data) > 0: if len(pid.data) > 0:
if MultiHash.decode(pid.data, mh) > 0: if MultiHash.decode(pid.data, mh).isOk:
if mh.mcodec == multiCodec("identity"): if mh.mcodec == multiCodec("identity"):
let length = len(mh.data.buffer) let length = len(mh.data.buffer)
result = pubkey.init(mh.data.buffer.toOpenArray(mh.dpos, length - 1)) result = pubkey.init(mh.data.buffer.toOpenArray(mh.dpos, length - 1))
@ -117,7 +117,7 @@ proc `$`*(pid: PeerID): string =
for i in 0..<2: for i in 0..<2:
result.add(spid[i]) result.add(spid[i])
result.add("*") result.add("*")
for i in (len(spid) - 6)..(len(spid) - 1): for i in (len(spid) - 6)..spid.high:
result.add(spid[i]) result.add(spid[i])
proc init*(pid: var PeerID, data: openarray[byte]): bool = 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 = proc init*(t: typedesc[PeerID], pubkey: PublicKey): PeerID =
## Create new peer id from public key ``pubkey``. ## Create new peer id from public key ``pubkey``.
var pubraw = pubkey.getBytes() var pubraw = pubkey.getBytes().tryGet()
var mh: MultiHash var mh: MultiHash
if len(pubraw) <= maxInlineKeyLength: if len(pubraw) <= maxInlineKeyLength:
mh = MultiHash.digest("identity", pubraw) mh = MultiHash.digest("identity", pubraw).tryGet()
else: else:
mh = MultiHash.digest("sha2-256", pubraw) mh = MultiHash.digest("sha2-256", pubraw).tryGet()
result.data = mh.data.buffer result.data = mh.data.buffer
proc init*(t: typedesc[PeerID], seckey: PrivateKey): PeerID {.inline.} = proc init*(t: typedesc[PeerID], seckey: PrivateKey): PeerID {.inline.} =
## Create new peer id from private key ``seckey``. ## 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.} = proc match*(pid: PeerID, pubkey: PublicKey): bool {.inline.} =
## Returns ``true`` if ``pid`` matches public key ``pubkey``. ## Returns ``true`` if ``pid`` matches public key ``pubkey``.

View File

@ -118,4 +118,4 @@ proc publicKey*(p: PeerInfo): Option[PublicKey] {.inline.} =
elif p.key.isSome: elif p.key.isSome:
result = p.key result = p.key
else: else:
result = some(p.privateKey.getKey()) result = some(p.privateKey.getKey().tryGet())

View File

@ -47,7 +47,7 @@ type
proc encodeMsg*(peerInfo: PeerInfo, observedAddrs: Multiaddress): ProtoBuffer = proc encodeMsg*(peerInfo: PeerInfo, observedAddrs: Multiaddress): ProtoBuffer =
result = initProtoBuffer() result = initProtoBuffer()
result.write(initProtoField(1, peerInfo.publicKey.get().getBytes())) result.write(initProtoField(1, peerInfo.publicKey.get().getBytes().tryGet()))
for ma in peerInfo.addrs: for ma in peerInfo.addrs:
result.write(initProtoField(2, ma.data.buffer)) result.write(initProtoField(2, ma.data.buffer))

View File

@ -33,7 +33,7 @@ proc sign*(msg: Message, p: PeerInfo): Message {.gcsafe.} =
if buff.buffer.len > 0: if buff.buffer.len > 0:
result = msg result = msg
result.signature = p.privateKey. result.signature = p.privateKey.
sign(cast[seq[byte]](PubSubPrefix) & buff.buffer). sign(cast[seq[byte]](PubSubPrefix) & buff.buffer).tryGet().
getBytes() getBytes()
proc verify*(m: Message, p: PeerInfo): bool = proc verify*(m: Message, p: PeerInfo): bool =
@ -57,7 +57,7 @@ proc newMessage*(p: PeerInfo,
sign: bool = true): Message {.gcsafe.} = sign: bool = true): Message {.gcsafe.} =
var seqno: seq[byte] = newSeq[byte](20) var seqno: seq[byte] = newSeq[byte](20)
if p.publicKey.isSome and randomBytes(addr seqno[0], 20) > 0: 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(), result = Message(fromPeer: p.peerId.getBytes(),
data: data, data: data,

View File

@ -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 # https://github.com/libp2p/specs/tree/master/noise#libp2p-data-in-handshake-messages
let let
signedPayload = p.localPrivateKey.sign(PayloadString.toBytes & p.noisePublicKey.getBytes) signedPayload = p.localPrivateKey.sign(
PayloadString.toBytes & p.noisePublicKey.getBytes).tryGet()
var var
libp2pProof = initProtoBuffer() libp2pProof = initProtoBuffer()
@ -532,7 +533,7 @@ proc newNoise*(privateKey: PrivateKey; outgoing: bool = true; commonPrologue: se
new result new result
result.outgoing = outgoing result.outgoing = outgoing
result.localPrivateKey = privateKey result.localPrivateKey = privateKey
result.localPublicKey = privateKey.getKey() result.localPublicKey = privateKey.getKey().tryGet()
discard randomBytes(result.noisePrivateKey) discard randomBytes(result.noisePrivateKey)
result.noisePublicKey = result.noisePrivateKey.public() result.noisePublicKey = result.noisePrivateKey.public()
result.commonPrologue = commonPrologue result.commonPrologue = commonPrologue

View File

@ -166,7 +166,7 @@ proc macCheckAndDecode(sconn: SecioConn, data: var seq[byte]): bool =
if not equalMem(addr data[mark], addr macData[0], macsize): if not equalMem(addr data[mark], addr macData[0], macsize):
trace "Invalid MAC", trace "Invalid MAC",
calculated = toHex(macData.toOpenArray(0, macsize - 1)), calculated = toHex(macData.toOpenArray(0, macsize - 1)),
stored = toHex(data.toOpenArray(mark, len(data) - 1)) stored = toHex(data.toOpenArray(mark, data.high))
return false return false
sconn.readerCoder.decrypt(data.toOpenArray(0, mark - 1), 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 remoteHashes: string
remotePeerId: PeerID remotePeerId: PeerID
localPeerId: PeerID localPeerId: PeerID
localBytesPubkey = s.localPublicKey.getBytes() localBytesPubkey = s.localPublicKey.getBytes().tryGet()
if randomBytes(localNonce) != SecioNonceSize: if randomBytes(localNonce) != SecioNonceSize:
raise (ref SecioError)(msg: "Could not generate random data") 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 # TODO: PeerID check against supplied PeerID
let order = getOrder(remoteBytesPubkey, localNonce, localBytesPubkey, let order = getOrder(remoteBytesPubkey, localNonce, localBytesPubkey,
remoteNonce) remoteNonce).tryGet()
trace "Remote proposal", schemes = remoteExchanges, ciphers = remoteCiphers, trace "Remote proposal", schemes = remoteExchanges, ciphers = remoteCiphers,
hashes = remoteHashes, hashes = remoteHashes,
pubkey = remoteBytesPubkey.shortLog, order = order, 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, trace "Encryption scheme selected", scheme = scheme, cipher = cipher,
hash = hash hash = hash
var ekeypair = ephemeral(scheme) var ekeypair = ephemeral(scheme).tryGet()
# We need EC public key in raw binary form # 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 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 localExchange = createExchange(epubkey, signature.getBytes())
var remoteExchange = await transactMessage(conn, localExchange) var remoteExchange = await transactMessage(conn, localExchange)
@ -430,5 +430,5 @@ method init(s: Secio) {.gcsafe.} =
proc newSecio*(localPrivateKey: PrivateKey): Secio = proc newSecio*(localPrivateKey: PrivateKey): Secio =
new result new result
result.localPrivateKey = localPrivateKey result.localPrivateKey = localPrivateKey
result.localPublicKey = localPrivateKey.getKey() result.localPublicKey = localPrivateKey.getKey().tryGet()
result.init() result.init()

View File

@ -31,7 +31,7 @@ proc newStandardSwitch*(privKey = none(PrivateKey),
result = newMplex(conn) result = newMplex(conn)
let let
seckey = privKey.get(otherwise = PrivateKey.random(ECDSA)) seckey = privKey.get(otherwise = PrivateKey.random(ECDSA).tryGet())
peerInfo = PeerInfo.init(seckey, [address]) peerInfo = PeerInfo.init(seckey, [address])
mplexProvider = newMuxerProvider(createMplex, MplexCodec) mplexProvider = newMuxerProvider(createMplex, MplexCodec)
transports = @[Transport(newTransport(TcpTransport, transportFlags))] transports = @[Transport(newTransport(TcpTransport, transportFlags))]

View File

@ -24,9 +24,15 @@ template isEnough*(vb: VBuffer, length: int): bool =
## Returns ``true`` if buffer ``vb`` holds at least ``length`` bytes. ## Returns ``true`` if buffer ``vb`` holds at least ``length`` bytes.
len(vb.buffer) - vb.offset - length >= 0 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 = proc len*(vb: VBuffer): int =
## Returns number of bytes left in buffer ``vb``. ## Returns number of bytes left in buffer ``vb``.
result = len(vb.buffer) - vb.offset result = len(vb.buffer) - vb.offset
doAssert(result >= 0)
proc isLiteral[T](s: seq[T]): bool {.inline.} = proc isLiteral[T](s: seq[T]): bool {.inline.} =
type type
@ -58,7 +64,7 @@ proc writePBVarint*(vb: var VBuffer, value: PBSomeUVarint) =
var length = 0 var length = 0
var v = value and cast[type(value)](0xFFFF_FFFF_FFFF_FFFF) var v = value and cast[type(value)](0xFFFF_FFFF_FFFF_FFFF)
vb.buffer.setLen(len(vb.buffer) + vsizeof(v)) 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) length, v)
doAssert(res == VarintStatus.Success) doAssert(res == VarintStatus.Success)
vb.offset += length vb.offset += length
@ -69,7 +75,7 @@ proc writeLPVarint*(vb: var VBuffer, value: LPSomeUVarint) =
# LibP2P varint supports only 63 bits. # LibP2P varint supports only 63 bits.
var v = value and cast[type(value)](0x7FFF_FFFF_FFFF_FFFF) var v = value and cast[type(value)](0x7FFF_FFFF_FFFF_FFFF)
vb.buffer.setLen(len(vb.buffer) + vsizeof(v)) 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) length, v)
doAssert(res == VarintStatus.Success) doAssert(res == VarintStatus.Success)
vb.offset += length vb.offset += length
@ -82,7 +88,7 @@ proc writeSeq*[T: byte|char](vb: var VBuffer, value: openarray[T]) =
## varint length of the array. ## varint length of the array.
var length = 0 var length = 0
vb.buffer.setLen(len(vb.buffer) + vsizeof(uint(len(value))) + len(value)) 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))) length, uint(len(value)))
doAssert(res == VarintStatus.Success) doAssert(res == VarintStatus.Success)
vb.offset += length vb.offset += length
@ -113,7 +119,7 @@ proc peekVarint*(vb: var VBuffer, value: var LPSomeUVarint): int =
var length = 0 var length = 0
if not vb.isEmpty(): if not vb.isEmpty():
let res = LP.getUVarint( 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: if res == VarintStatus.Success:
result = length result = length
@ -129,7 +135,7 @@ proc peekSeq*[T: string|seq[byte]](vb: var VBuffer, value: var T): int =
var length = 0 var length = 0
var size = 0'u64 var size = 0'u64
if not vb.isEmpty() and 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: length, size) == VarintStatus.Success:
vb.offset += length vb.offset += length
result = length result = length

View File

@ -19,7 +19,7 @@ suite "GossipSub internal":
test "`rebalanceMesh` Degree Lo": test "`rebalanceMesh` Degree Lo":
proc testRun(): Future[bool] {.async.} = proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub, let gossipSub = newPubSub(TestGossipSub,
PeerInfo.init(PrivateKey.random(RSA))) PeerInfo.init(PrivateKey.random(RSA).get()))
let topic = "foobar" let topic = "foobar"
gossipSub.mesh[topic] = initHashSet[string]() gossipSub.mesh[topic] = initHashSet[string]()
@ -28,7 +28,7 @@ suite "GossipSub internal":
for i in 0..<15: for i in 0..<15:
let conn = newConnection(newBufferStream()) let conn = newConnection(newBufferStream())
conns &= conn conns &= conn
let peerInfo = PeerInfo.init(PrivateKey.random(RSA)) let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec) gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].conn = conn gossipSub.peers[peerInfo.id].conn = conn
@ -48,7 +48,7 @@ suite "GossipSub internal":
test "`rebalanceMesh` Degree Hi": test "`rebalanceMesh` Degree Hi":
proc testRun(): Future[bool] {.async.} = proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub, let gossipSub = newPubSub(TestGossipSub,
PeerInfo.init(PrivateKey.random(RSA))) PeerInfo.init(PrivateKey.random(RSA).get()))
let topic = "foobar" let topic = "foobar"
gossipSub.gossipsub[topic] = initHashSet[string]() gossipSub.gossipsub[topic] = initHashSet[string]()
@ -57,7 +57,7 @@ suite "GossipSub internal":
for i in 0..<15: for i in 0..<15:
let conn = newConnection(newBufferStream()) let conn = newConnection(newBufferStream())
conns &= conn conns &= conn
let peerInfo = PeerInfo.init(PrivateKey.random(RSA)) let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec) gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].conn = conn gossipSub.peers[peerInfo.id].conn = conn
@ -77,7 +77,7 @@ suite "GossipSub internal":
test "`replenishFanout` Degree Lo": test "`replenishFanout` Degree Lo":
proc testRun(): Future[bool] {.async.} = proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub, let gossipSub = newPubSub(TestGossipSub,
PeerInfo.init(PrivateKey.random(RSA))) PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} = proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard discard
@ -89,7 +89,7 @@ suite "GossipSub internal":
for i in 0..<15: for i in 0..<15:
let conn = newConnection(newBufferStream()) let conn = newConnection(newBufferStream())
conns &= conn conns &= conn
var peerInfo = PeerInfo.init(PrivateKey.random(RSA)) var peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec) gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler gossipSub.peers[peerInfo.id].handler = handler
@ -109,7 +109,7 @@ suite "GossipSub internal":
test "`dropFanoutPeers` drop expired fanout topics": test "`dropFanoutPeers` drop expired fanout topics":
proc testRun(): Future[bool] {.async.} = proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub, let gossipSub = newPubSub(TestGossipSub,
PeerInfo.init(PrivateKey.random(RSA))) PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} = proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard discard
@ -122,7 +122,7 @@ suite "GossipSub internal":
for i in 0..<6: for i in 0..<6:
let conn = newConnection(newBufferStream()) let conn = newConnection(newBufferStream())
conns &= conn conns &= conn
let peerInfo = PeerInfo.init(PrivateKey.random(RSA)) let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec) gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler gossipSub.peers[peerInfo.id].handler = handler
@ -143,7 +143,7 @@ suite "GossipSub internal":
test "`dropFanoutPeers` leave unexpired fanout topics": test "`dropFanoutPeers` leave unexpired fanout topics":
proc testRun(): Future[bool] {.async.} = proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub, let gossipSub = newPubSub(TestGossipSub,
PeerInfo.init(PrivateKey.random(RSA))) PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} = proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard discard
@ -159,7 +159,7 @@ suite "GossipSub internal":
for i in 0..<6: for i in 0..<6:
let conn = newConnection(newBufferStream()) let conn = newConnection(newBufferStream())
conns &= conn conns &= conn
let peerInfo = PeerInfo.init(PrivateKey.random(RSA)) let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec) gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler gossipSub.peers[peerInfo.id].handler = handler
@ -183,7 +183,7 @@ suite "GossipSub internal":
test "`getGossipPeers` - should gather up to degree D non intersecting peers": test "`getGossipPeers` - should gather up to degree D non intersecting peers":
proc testRun(): Future[bool] {.async.} = proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub, let gossipSub = newPubSub(TestGossipSub,
PeerInfo.init(PrivateKey.random(RSA))) PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} = proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard discard
@ -196,7 +196,7 @@ suite "GossipSub internal":
for i in 0..<30: for i in 0..<30:
let conn = newConnection(newBufferStream()) let conn = newConnection(newBufferStream())
conns &= conn conns &= conn
let peerInfo = PeerInfo.init(PrivateKey.random(RSA)) let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec) gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler gossipSub.peers[peerInfo.id].handler = handler
@ -208,7 +208,7 @@ suite "GossipSub internal":
for i in 0..<15: for i in 0..<15:
let conn = newConnection(newBufferStream()) let conn = newConnection(newBufferStream())
conns &= conn conns &= conn
let peerInfo = PeerInfo.init(PrivateKey.random(RSA)) let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec) gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler gossipSub.peers[peerInfo.id].handler = handler
@ -234,7 +234,7 @@ suite "GossipSub internal":
test "`getGossipPeers` - should not crash on missing topics in mesh": test "`getGossipPeers` - should not crash on missing topics in mesh":
proc testRun(): Future[bool] {.async.} = proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub, let gossipSub = newPubSub(TestGossipSub,
PeerInfo.init(PrivateKey.random(RSA))) PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} = proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard discard
@ -246,7 +246,7 @@ suite "GossipSub internal":
for i in 0..<30: for i in 0..<30:
let conn = newConnection(newBufferStream()) let conn = newConnection(newBufferStream())
conns &= conn conns &= conn
let peerInfo = PeerInfo.init(PrivateKey.random(RSA)) let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec) gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler gossipSub.peers[peerInfo.id].handler = handler
@ -268,7 +268,7 @@ suite "GossipSub internal":
test "`getGossipPeers` - should not crash on missing topics in gossip": test "`getGossipPeers` - should not crash on missing topics in gossip":
proc testRun(): Future[bool] {.async.} = proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub, let gossipSub = newPubSub(TestGossipSub,
PeerInfo.init(PrivateKey.random(RSA))) PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} = proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard discard
@ -280,7 +280,7 @@ suite "GossipSub internal":
for i in 0..<30: for i in 0..<30:
let conn = newConnection(newBufferStream()) let conn = newConnection(newBufferStream())
conns &= conn conns &= conn
let peerInfo = PeerInfo.init(PrivateKey.random(RSA)) let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec) gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler gossipSub.peers[peerInfo.id].handler = handler
@ -302,7 +302,7 @@ suite "GossipSub internal":
test "`getGossipPeers` - should not crash on missing topics in gossip": test "`getGossipPeers` - should not crash on missing topics in gossip":
proc testRun(): Future[bool] {.async.} = proc testRun(): Future[bool] {.async.} =
let gossipSub = newPubSub(TestGossipSub, let gossipSub = newPubSub(TestGossipSub,
PeerInfo.init(PrivateKey.random(RSA))) PeerInfo.init(PrivateKey.random(RSA).get()))
proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} = proc handler(peer: PubSubPeer, msg: seq[RPCMsg]) {.async.} =
discard discard
@ -314,7 +314,7 @@ suite "GossipSub internal":
for i in 0..<30: for i in 0..<30:
let conn = newConnection(newBufferStream()) let conn = newConnection(newBufferStream())
conns &= conn conns &= conn
let peerInfo = PeerInfo.init(PrivateKey.random(RSA)) let peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
conn.peerInfo = peerInfo conn.peerInfo = peerInfo
gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec) gossipSub.peers[peerInfo.id] = newPubSubPeer(peerInfo, GossipSubCodec)
gossipSub.peers[peerInfo.id].handler = handler gossipSub.peers[peerInfo.id].handler = handler

View File

@ -25,7 +25,7 @@ import utils, ../../libp2p/[errors,
import ../helpers import ../helpers
proc createGossipSub(): GossipSub = proc createGossipSub(): GossipSub =
var peerInfo = PeerInfo.init(PrivateKey.random(RSA)) var peerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
result = newPubSub(GossipSub, peerInfo) result = newPubSub(GossipSub, peerInfo)
proc waitSub(sender, receiver: auto; key: string) {.async, gcsafe.} = proc waitSub(sender, receiver: auto; key: string) {.async, gcsafe.} =

View File

@ -11,7 +11,7 @@ import ../../libp2p/[peer,
suite "MCache": suite "MCache":
test "put/get": test "put/get":
var mCache = newMCache(3, 5) 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")) seqno: cast[seq[byte]]("12345"))
mCache.put(msg) mCache.put(msg)
check mCache.get(msg.msgId).isSome and mCache.get(msg.msgId).get() == 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) var mCache = newMCache(3, 5)
for i in 0..<3: 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"), seqno: cast[seq[byte]]("12345"),
topicIDs: @["foo"]) topicIDs: @["foo"])
mCache.put(msg) mCache.put(msg)
for i in 0..<5: 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"), seqno: cast[seq[byte]]("12345"),
topicIDs: @["bar"]) topicIDs: @["bar"])
mCache.put(msg) mCache.put(msg)
@ -41,7 +41,7 @@ suite "MCache":
var mCache = newMCache(1, 5) var mCache = newMCache(1, 5)
for i in 0..<3: 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"), seqno: cast[seq[byte]]("12345"),
topicIDs: @["foo"]) topicIDs: @["foo"])
mCache.put(msg) mCache.put(msg)
@ -50,7 +50,7 @@ suite "MCache":
check mCache.window("foo").len == 0 check mCache.window("foo").len == 0
for i in 0..<3: 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"), seqno: cast[seq[byte]]("12345"),
topicIDs: @["bar"]) topicIDs: @["bar"])
mCache.put(msg) mCache.put(msg)
@ -59,7 +59,7 @@ suite "MCache":
check mCache.window("bar").len == 0 check mCache.window("bar").len == 0
for i in 0..<3: 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"), seqno: cast[seq[byte]]("12345"),
topicIDs: @["baz"]) topicIDs: @["baz"])
mCache.put(msg) mCache.put(msg)
@ -71,19 +71,19 @@ suite "MCache":
var mCache = newMCache(1, 5) var mCache = newMCache(1, 5)
for i in 0..<3: 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"), seqno: cast[seq[byte]]("12345"),
topicIDs: @["foo"]) topicIDs: @["foo"])
mCache.put(msg) mCache.put(msg)
for i in 0..<3: 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"), seqno: cast[seq[byte]]("12345"),
topicIDs: @["bar"]) topicIDs: @["bar"])
mCache.put(msg) mCache.put(msg)
for i in 0..<3: 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"), seqno: cast[seq[byte]]("12345"),
topicIDs: @["baz"]) topicIDs: @["baz"])
mCache.put(msg) mCache.put(msg)

View File

@ -38,17 +38,17 @@ suite "Content identifier CID test suite":
var bmsg = cast[seq[byte]](msg) var bmsg = cast[seq[byte]](msg)
var bmmsg = cast[seq[byte]](mmsg) var bmmsg = cast[seq[byte]](mmsg)
var cid0 = Cid.init(CIDv0, multiCodec("dag-pb"), 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"), var cid1 = Cid.init(CIDv1, multiCodec("dag-pb"),
MultiHash.digest("sha2-256", bmsg)) MultiHash.digest("sha2-256", bmsg).get())
var cid2 = cid1 var cid2 = cid1
var cid3 = cid0 var cid3 = cid0
var cid4 = Cid.init(CIDv1, multiCodec("dag-cbor"), 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"), 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"), var cid6 = Cid.init(CIDv1, multiCodec("dag-pb"),
MultiHash.digest("keccak-256", bmsg)) MultiHash.digest("keccak-256", bmsg).get())
check: check:
cid0 == cid1 cid0 == cid1
cid1 == cid2 cid1 == cid2

View File

@ -378,13 +378,13 @@ suite "Key interface test suite":
test "Go test vectors": test "Go test vectors":
for i in 0..<len(PrivateKeys): for i in 0..<len(PrivateKeys):
var seckey = PrivateKey.init(fromHex(stripSpaces(PrivateKeys[i]))) var seckey = PrivateKey.init(fromHex(stripSpaces(PrivateKeys[i]))).expect("private key")
var pubkey = PublicKey.init(fromHex(stripSpaces(PublicKeys[i]))) var pubkey = PublicKey.init(fromHex(stripSpaces(PublicKeys[i]))).expect("public key")
var calckey = seckey.getKey() var calckey = seckey.getKey().expect("public key")
check: check:
pubkey == calckey pubkey == calckey
var checkseckey = seckey.getBytes() var checkseckey = seckey.getBytes().expect("private key")
var checkpubkey = pubkey.getBytes() var checkpubkey = pubkey.getBytes().expect("public key")
check: check:
toHex(checkseckey) == stripSpaces(PrivateKeys[i]) toHex(checkseckey) == stripSpaces(PrivateKeys[i])
toHex(checkpubkey) == stripSpaces(PublicKeys[i]) toHex(checkpubkey) == stripSpaces(PublicKeys[i])
@ -394,19 +394,19 @@ suite "Key interface test suite":
var bmsg = cast[seq[byte]](msg) var bmsg = cast[seq[byte]](msg)
for i in 0..<5: for i in 0..<5:
var seckey = PrivateKey.random(ECDSA) var seckey = PrivateKey.random(ECDSA).get()
var pubkey = seckey.getKey() var pubkey = seckey.getKey().get()
var pair = KeyPair.random(ECDSA) var pair = KeyPair.random(ECDSA).get()
var sig1 = pair.seckey.sign(bmsg) var sig1 = pair.seckey.sign(bmsg).get()
var sig2 = seckey.sign(bmsg) var sig2 = seckey.sign(bmsg).get()
var sersig1 = sig1.getBytes() var sersig1 = sig1.getBytes()
var sersig2 = sig2.getBytes() var sersig2 = sig2.getBytes()
var serpub1 = pair.pubkey.getBytes() var serpub1 = pair.pubkey.getBytes().get()
var serpub2 = pubkey.getBytes() var serpub2 = pubkey.getBytes().get()
var recsig1 = Signature.init(sersig1) var recsig1 = Signature.init(sersig1).get()
var recsig2 = Signature.init(sersig2) var recsig2 = Signature.init(sersig2).get()
var recpub1 = PublicKey.init(serpub1) var recpub1 = PublicKey.init(serpub1).get()
var recpub2 = PublicKey.init(serpub2) var recpub2 = PublicKey.init(serpub2).get()
check: check:
sig1.verify(bmsg, pair.pubkey) == true sig1.verify(bmsg, pair.pubkey) == true
recsig1.verify(bmsg, recpub1) == true recsig1.verify(bmsg, recpub1) == true
@ -414,19 +414,19 @@ suite "Key interface test suite":
recsig2.verify(bmsg, recpub2) == true recsig2.verify(bmsg, recpub2) == true
for i in 0..<5: for i in 0..<5:
var seckey = PrivateKey.random(Ed25519) var seckey = PrivateKey.random(Ed25519).get()
var pubkey = seckey.getKey() var pubkey = seckey.getKey().get()
var pair = KeyPair.random(Ed25519) var pair = KeyPair.random(Ed25519).get()
var sig1 = pair.seckey.sign(bmsg) var sig1 = pair.seckey.sign(bmsg).get()
var sig2 = seckey.sign(bmsg) var sig2 = seckey.sign(bmsg).get()
var sersig1 = sig1.getBytes() var sersig1 = sig1.getBytes()
var sersig2 = sig2.getBytes() var sersig2 = sig2.getBytes()
var serpub1 = pair.pubkey.getBytes() var serpub1 = pair.pubkey.getBytes().get()
var serpub2 = pubkey.getBytes() var serpub2 = pubkey.getBytes().get()
var recsig1 = Signature.init(sersig1) var recsig1 = Signature.init(sersig1).get()
var recsig2 = Signature.init(sersig2) var recsig2 = Signature.init(sersig2).get()
var recpub1 = PublicKey.init(serpub1) var recpub1 = PublicKey.init(serpub1).get()
var recpub2 = PublicKey.init(serpub2) var recpub2 = PublicKey.init(serpub2).get()
check: check:
sig1.verify(bmsg, pair.pubkey) == true sig1.verify(bmsg, pair.pubkey) == true
recsig1.verify(bmsg, recpub1) == true recsig1.verify(bmsg, recpub1) == true
@ -434,19 +434,19 @@ suite "Key interface test suite":
recsig2.verify(bmsg, recpub2) == true recsig2.verify(bmsg, recpub2) == true
for i in 0..<5: for i in 0..<5:
var seckey = PrivateKey.random(RSA, 512) var seckey = PrivateKey.random(RSA, 512).get()
var pubkey = seckey.getKey() var pubkey = seckey.getKey().get()
var pair = KeyPair.random(RSA, 512) var pair = KeyPair.random(RSA, 512).get()
var sig1 = pair.seckey.sign(bmsg) var sig1 = pair.seckey.sign(bmsg).get()
var sig2 = seckey.sign(bmsg) var sig2 = seckey.sign(bmsg).get()
var sersig1 = sig1.getBytes() var sersig1 = sig1.getBytes()
var sersig2 = sig2.getBytes() var sersig2 = sig2.getBytes()
var serpub1 = pair.pubkey.getBytes() var serpub1 = pair.pubkey.getBytes().get()
var serpub2 = pubkey.getBytes() var serpub2 = pubkey.getBytes().get()
var recsig1 = Signature.init(sersig1) var recsig1 = Signature.init(sersig1).get()
var recsig2 = Signature.init(sersig2) var recsig2 = Signature.init(sersig2).get()
var recpub1 = PublicKey.init(serpub1) var recpub1 = PublicKey.init(serpub1).get()
var recpub2 = PublicKey.init(serpub2) var recpub2 = PublicKey.init(serpub2).get()
check: check:
sig1.verify(bmsg, pair.pubkey) == true sig1.verify(bmsg, pair.pubkey) == true
recsig1.verify(bmsg, recpub1) == true recsig1.verify(bmsg, recpub1) == true

View File

@ -300,15 +300,15 @@ suite "EC NIST-P256/384/521 test suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: EcPrivateKey var rkey1, rkey2: EcPrivateKey
var skey2 = newSeq[byte](256) var skey2 = newSeq[byte](256)
var key = EcPrivateKey.random(Secp256r1) var key = EcPrivateKey.random(Secp256r1).expect("random key")
var skey1 = key.getBytes() var skey1 = key.getBytes().expect("bytes")
check: check:
key.toBytes(skey2) > 0 key.toBytes(skey2).expect("bytes") > 0
check: check:
rkey1.init(skey1).isOk rkey1.init(skey1).isOk
rkey2.init(skey2).isOk rkey2.init(skey2).isOk
var rkey3 = EcPrivateKey.init(skey1) var rkey3 = EcPrivateKey.init(skey1).expect("private key")
var rkey4 = EcPrivateKey.init(skey2) var rkey4 = EcPrivateKey.init(skey2).expect("private key")
check: check:
rkey1 == key rkey1 == key
rkey2 == key rkey2 == key
@ -319,14 +319,14 @@ suite "EC NIST-P256/384/521 test suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: EcPublicKey var rkey1, rkey2: EcPublicKey
var skey2 = newSeq[byte](256) var skey2 = newSeq[byte](256)
var pair = EcKeyPair.random(Secp256r1) var pair = EcKeyPair.random(Secp256r1).expect("random key")
var skey1 = pair.pubkey.getBytes() var skey1 = pair.pubkey.getBytes().expect("bytes")
check: check:
pair.pubkey.toBytes(skey2) > 0 pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk rkey1.init(skey1).isOk
rkey2.init(skey2).isOk rkey2.init(skey2).isOk
var rkey3 = EcPublicKey.init(skey1) var rkey3 = EcPublicKey.init(skey1).expect("public key")
var rkey4 = EcPublicKey.init(skey2) var rkey4 = EcPublicKey.init(skey2).expect("public key")
check: check:
rkey1 == pair.pubkey rkey1 == pair.pubkey
rkey2 == pair.pubkey rkey2 == pair.pubkey
@ -335,8 +335,8 @@ suite "EC NIST-P256/384/521 test suite":
test "[secp256r1] ECDHE test": test "[secp256r1] ECDHE test":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var kp1 = EcKeyPair.random(Secp256r1) var kp1 = EcKeyPair.random(Secp256r1).expect("random key")
var kp2 = EcKeyPair.random(Secp256r1) var kp2 = EcKeyPair.random(Secp256r1).expect("random key")
var shared1 = kp2.pubkey.scalarMul(kp1.seckey) var shared1 = kp2.pubkey.scalarMul(kp1.seckey)
var shared2 = kp1.pubkey.scalarMul(kp2.seckey) var shared2 = kp1.pubkey.scalarMul(kp2.seckey)
check: check:
@ -348,10 +348,10 @@ suite "EC NIST-P256/384/521 test suite":
for i in 0..<3: for i in 0..<3:
var key1 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2])) var key1 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2]))
var key2 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2 + 1])) var key2 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2 + 1]))
var seckey1 = EcPrivateKey.initRaw(key1) var seckey1 = EcPrivateKey.initRaw(key1).expect("initRaw key")
var seckey2 = EcPrivateKey.initRaw(key2) var seckey2 = EcPrivateKey.initRaw(key2).expect("initRaw key")
var pubkey1 = seckey1.getKey() var pubkey1 = seckey1.getKey().expect("public key")
var pubkey2 = seckey2.getKey() var pubkey2 = seckey2.getKey().expect("public key")
var secret1 = getSecret(pubkey2, seckey1) var secret1 = getSecret(pubkey2, seckey1)
var secret2 = getSecret(pubkey1, seckey2) var secret2 = getSecret(pubkey1, seckey2)
var expsecret = fromHex(stripSpaces(ECDHESecrets[i])) var expsecret = fromHex(stripSpaces(ECDHESecrets[i]))
@ -361,45 +361,45 @@ suite "EC NIST-P256/384/521 test suite":
test "[secp256r1] ECDSA test vectors": test "[secp256r1] ECDSA test vectors":
for i in 0..<2: for i in 0..<2:
var sk = EcPrivateKey.init(stripSpaces(SignatureSecKeys[i])) var sk = EcPrivateKey.init(stripSpaces(SignatureSecKeys[i])).expect("private key")
var expectpk = EcPublicKey.init(stripSpaces(SignaturePubKeys[i])) var expectpk = EcPublicKey.init(stripSpaces(SignaturePubKeys[i])).expect("private key")
var checkpk = sk.getKey() var checkpk = sk.getKey().expect("public key")
check expectpk == checkpk check expectpk == checkpk
var checksig = sk.sign(SignatureMessages[i]) var checksig = sk.sign(SignatureMessages[i]).expect("signature")
var expectsig = EcSignature.init(stripSpaces(SignatureVectors[i])) var expectsig = EcSignature.init(stripSpaces(SignatureVectors[i])).expect("signature")
check: check:
checksig == expectsig checksig == expectsig
checksig.verify(SignatureMessages[i], checkpk) == true checksig.verify(SignatureMessages[i], checkpk) == true
let error = len(checksig.buffer) - 1 let error = checksig.buffer.high
checksig.buffer[error] = not(checksig.buffer[error]) checksig.buffer[error] = not(checksig.buffer[error])
check checksig.verify(SignatureMessages[i], checkpk) == false check checksig.verify(SignatureMessages[i], checkpk) == false
test "[secp256r1] ECDSA non-deterministic test vectors": test "[secp256r1] ECDSA non-deterministic test vectors":
var sk = EcPrivateKey.init(stripSpaces(NDPrivateKeys[0])) var sk = EcPrivateKey.init(stripSpaces(NDPrivateKeys[0])).expect("private key")
var pk = EcPublicKey.init(stripSpaces(NDPublicKeys[0])) var pk = EcPublicKey.init(stripSpaces(NDPublicKeys[0])).expect("public key")
var checkpk = sk.getKey() var checkpk = sk.getKey().expect("public key")
check pk == checkpk check pk == checkpk
for i in 0..<6: for i in 0..<6:
var message = NDMessages[i] var message = NDMessages[i]
var checksig = EcSignature.init(stripSpaces(NDSignatures[i])) var checksig = EcSignature.init(stripSpaces(NDSignatures[i])).expect("signature")
check checksig.verify(message, pk) == true check checksig.verify(message, pk) == true
let error = len(checksig.buffer) - 1 let error = checksig.buffer.high
checksig.buffer[error] = not(checksig.buffer[error]) checksig.buffer[error] = not(checksig.buffer[error])
check checksig.verify(message, pk) == false check checksig.verify(message, pk) == false
test "[secp256r1] Generate/Sign/Serialize/Deserialize/Verify test": test "[secp256r1] Generate/Sign/Serialize/Deserialize/Verify test":
var message = "message to sign" var message = "message to sign"
for i in 0..<TestsCount: for i in 0..<TestsCount:
var kp = EcKeyPair.random(Secp256r1) var kp = EcKeyPair.random(Secp256r1).expect("random key")
var sig = kp.seckey.sign(message) var sig = kp.seckey.sign(message).expect("signature")
var sersk = kp.seckey.getBytes() var sersk = kp.seckey.getBytes().expect("bytes")
var serpk = kp.pubkey.getBytes() var serpk = kp.pubkey.getBytes().expect("bytes")
var sersig = sig.getBytes() var sersig = sig.getBytes().expect("bytes")
discard EcPrivateKey.init(sersk) discard EcPrivateKey.init(sersk)
var pubkey = EcPublicKey.init(serpk) var pubkey = EcPublicKey.init(serpk).expect("public key")
var csig = EcSignature.init(sersig) var csig = EcSignature.init(sersig).expect("signature")
check csig.verify(message, pubkey) == true check csig.verify(message, pubkey) == true
let error = len(csig.buffer) - 1 let error = csig.buffer.high
csig.buffer[error] = not(csig.buffer[error]) csig.buffer[error] = not(csig.buffer[error])
check csig.verify(message, pubkey) == false check csig.verify(message, pubkey) == false
@ -407,15 +407,15 @@ suite "EC NIST-P256/384/521 test suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: EcPrivateKey var rkey1, rkey2: EcPrivateKey
var skey2 = newSeq[byte](256) var skey2 = newSeq[byte](256)
var key = EcPrivateKey.random(Secp384r1) var key = EcPrivateKey.random(Secp384r1).expect("random key")
var skey1 = key.getBytes() var skey1 = key.getBytes().expect("bytes")
check: check:
key.toBytes(skey2) > 0 key.toBytes(skey2).expect("bytes") > 0
check: check:
rkey1.init(skey1).isOk rkey1.init(skey1).isOk
rkey2.init(skey2).isOk rkey2.init(skey2).isOk
var rkey3 = EcPrivateKey.init(skey1) var rkey3 = EcPrivateKey.init(skey1).expect("private key")
var rkey4 = EcPrivateKey.init(skey2) var rkey4 = EcPrivateKey.init(skey2).expect("private key")
check: check:
rkey1 == key rkey1 == key
rkey2 == key rkey2 == key
@ -426,14 +426,14 @@ suite "EC NIST-P256/384/521 test suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: EcPublicKey var rkey1, rkey2: EcPublicKey
var skey2 = newSeq[byte](256) var skey2 = newSeq[byte](256)
var pair = EcKeyPair.random(Secp384r1) var pair = EcKeyPair.random(Secp384r1).expect("random key")
var skey1 = pair.pubkey.getBytes() var skey1 = pair.pubkey.getBytes().expect("bytes")
check: check:
pair.pubkey.toBytes(skey2) > 0 pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk rkey1.init(skey1).isOk
rkey2.init(skey2).isOk rkey2.init(skey2).isOk
var rkey3 = EcPublicKey.init(skey1) var rkey3 = EcPublicKey.init(skey1).expect("public key")
var rkey4 = EcPublicKey.init(skey2) var rkey4 = EcPublicKey.init(skey2).expect("public key")
check: check:
rkey1 == pair.pubkey rkey1 == pair.pubkey
rkey2 == pair.pubkey rkey2 == pair.pubkey
@ -442,8 +442,8 @@ suite "EC NIST-P256/384/521 test suite":
test "[secp384r1] ECDHE test": test "[secp384r1] ECDHE test":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var kp1 = EcKeyPair.random(Secp384r1) var kp1 = EcKeyPair.random(Secp384r1).expect("random key")
var kp2 = EcKeyPair.random(Secp384r1) var kp2 = EcKeyPair.random(Secp384r1).expect("random key")
var shared1 = kp2.pubkey.scalarMul(kp1.seckey) var shared1 = kp2.pubkey.scalarMul(kp1.seckey)
var shared2 = kp1.pubkey.scalarMul(kp2.seckey) var shared2 = kp1.pubkey.scalarMul(kp2.seckey)
check: check:
@ -455,10 +455,10 @@ suite "EC NIST-P256/384/521 test suite":
for i in 3..<6: for i in 3..<6:
var key1 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2])) var key1 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2]))
var key2 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2 + 1])) var key2 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2 + 1]))
var seckey1 = EcPrivateKey.initRaw(key1) var seckey1 = EcPrivateKey.initRaw(key1).expect("private key")
var seckey2 = EcPrivateKey.initRaw(key2) var seckey2 = EcPrivateKey.initRaw(key2).expect("private key")
var pubkey1 = seckey1.getKey() var pubkey1 = seckey1.getKey().expect("public key")
var pubkey2 = seckey2.getKey() var pubkey2 = seckey2.getKey().expect("public key")
var secret1 = getSecret(pubkey2, seckey1) var secret1 = getSecret(pubkey2, seckey1)
var secret2 = getSecret(pubkey1, seckey2) var secret2 = getSecret(pubkey1, seckey2)
var expsecret = fromHex(stripSpaces(ECDHESecrets[i])) var expsecret = fromHex(stripSpaces(ECDHESecrets[i]))
@ -468,45 +468,45 @@ suite "EC NIST-P256/384/521 test suite":
test "[secp384r1] ECDSA test vectors": test "[secp384r1] ECDSA test vectors":
for i in 2..<4: for i in 2..<4:
var sk = EcPrivateKey.init(stripSpaces(SignatureSecKeys[i])) var sk = EcPrivateKey.init(stripSpaces(SignatureSecKeys[i])).expect("private key")
var expectpk = EcPublicKey.init(stripSpaces(SignaturePubKeys[i])) var expectpk = EcPublicKey.init(stripSpaces(SignaturePubKeys[i])).expect("public key")
var checkpk = sk.getKey() var checkpk = sk.getKey().expect("public key")
check expectpk == checkpk check expectpk == checkpk
var checksig = sk.sign(SignatureMessages[i]) var checksig = sk.sign(SignatureMessages[i]).expect("signature")
var expectsig = EcSignature.init(stripSpaces(SignatureVectors[i])) var expectsig = EcSignature.init(stripSpaces(SignatureVectors[i])).expect("signature")
check: check:
checksig == expectsig checksig == expectsig
checksig.verify(SignatureMessages[i], checkpk) == true checksig.verify(SignatureMessages[i], checkpk) == true
let error = len(checksig.buffer) - 1 let error = checksig.buffer.high
checksig.buffer[error] = not(checksig.buffer[error]) checksig.buffer[error] = not(checksig.buffer[error])
check checksig.verify(SignatureMessages[i], checkpk) == false check checksig.verify(SignatureMessages[i], checkpk) == false
test "[secp384r1] ECDSA non-deterministic test vectors": test "[secp384r1] ECDSA non-deterministic test vectors":
var sk = EcPrivateKey.init(stripSpaces(NDPrivateKeys[1])) var sk = EcPrivateKey.init(stripSpaces(NDPrivateKeys[1])).expect("private key")
var pk = EcPublicKey.init(stripSpaces(NDPublicKeys[1])) var pk = EcPublicKey.init(stripSpaces(NDPublicKeys[1])).expect("public key")
var checkpk = sk.getKey() var checkpk = sk.getKey().expect("public key")
check pk == checkpk check pk == checkpk
for i in 6..<12: for i in 6..<12:
var message = NDMessages[i] var message = NDMessages[i]
var checksig = EcSignature.init(stripSpaces(NDSignatures[i])) var checksig = EcSignature.init(stripSpaces(NDSignatures[i])).expect("signature")
check checksig.verify(message, pk) == true check checksig.verify(message, pk) == true
let error = len(checksig.buffer) - 1 let error = checksig.buffer.high
checksig.buffer[error] = not(checksig.buffer[error]) checksig.buffer[error] = not(checksig.buffer[error])
check checksig.verify(message, pk) == false check checksig.verify(message, pk) == false
test "[secp384r1] Generate/Sign/Serialize/Deserialize/Verify test": test "[secp384r1] Generate/Sign/Serialize/Deserialize/Verify test":
var message = "message to sign" var message = "message to sign"
for i in 0..<TestsCount: for i in 0..<TestsCount:
var kp = EcKeyPair.random(Secp384r1) var kp = EcKeyPair.random(Secp384r1).expect("random key")
var sig = kp.seckey.sign(message) var sig = kp.seckey.sign(message).expect("signature")
var sersk = kp.seckey.getBytes() var sersk = kp.seckey.getBytes().expect("bytes")
var serpk = kp.pubkey.getBytes() var serpk = kp.pubkey.getBytes().expect("bytes")
var sersig = sig.getBytes() var sersig = sig.getBytes().expect("bytes")
discard EcPrivateKey.init(sersk) discard EcPrivateKey.init(sersk).expect("private key")
var pubkey = EcPublicKey.init(serpk) var pubkey = EcPublicKey.init(serpk).expect("public key")
var csig = EcSignature.init(sersig) var csig = EcSignature.init(sersig).expect("signature")
check csig.verify(message, pubkey) == true check csig.verify(message, pubkey) == true
let error = len(csig.buffer) - 1 let error = csig.buffer.high
csig.buffer[error] = not(csig.buffer[error]) csig.buffer[error] = not(csig.buffer[error])
check csig.verify(message, pubkey) == false check csig.verify(message, pubkey) == false
@ -514,15 +514,15 @@ suite "EC NIST-P256/384/521 test suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: EcPrivateKey var rkey1, rkey2: EcPrivateKey
var skey2 = newSeq[byte](256) var skey2 = newSeq[byte](256)
var key = EcPrivateKey.random(Secp521r1) var key = EcPrivateKey.random(Secp521r1).expect("random key")
var skey1 = key.getBytes() var skey1 = key.getBytes().expect("bytes")
check: check:
key.toBytes(skey2) > 0 key.toBytes(skey2).expect("bytes") > 0
check: check:
rkey1.init(skey1).isOk rkey1.init(skey1).isOk
rkey2.init(skey2).isOk rkey2.init(skey2).isOk
var rkey3 = EcPrivateKey.init(skey1) var rkey3 = EcPrivateKey.init(skey1).expect("private key")
var rkey4 = EcPrivateKey.init(skey2) var rkey4 = EcPrivateKey.init(skey2).expect("private key")
check: check:
rkey1 == key rkey1 == key
rkey2 == key rkey2 == key
@ -533,14 +533,14 @@ suite "EC NIST-P256/384/521 test suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: EcPublicKey var rkey1, rkey2: EcPublicKey
var skey2 = newSeq[byte](256) var skey2 = newSeq[byte](256)
var pair = EcKeyPair.random(Secp521r1) var pair = EcKeyPair.random(Secp521r1).expect("random key")
var skey1 = pair.pubkey.getBytes() var skey1 = pair.pubkey.getBytes().expect("bytes")
check: check:
pair.pubkey.toBytes(skey2) > 0 pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk rkey1.init(skey1).isOk
rkey2.init(skey2).isOk rkey2.init(skey2).isOk
var rkey3 = EcPublicKey.init(skey1) var rkey3 = EcPublicKey.init(skey1).expect("public key")
var rkey4 = EcPublicKey.init(skey2) var rkey4 = EcPublicKey.init(skey2).expect("public key")
check: check:
rkey1 == pair.pubkey rkey1 == pair.pubkey
rkey2 == pair.pubkey rkey2 == pair.pubkey
@ -549,8 +549,8 @@ suite "EC NIST-P256/384/521 test suite":
test "[secp521r1] ECDHE test": test "[secp521r1] ECDHE test":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var kp1 = EcKeyPair.random(Secp521r1) var kp1 = EcKeyPair.random(Secp521r1).expect("random key")
var kp2 = EcKeyPair.random(Secp521r1) var kp2 = EcKeyPair.random(Secp521r1).expect("random key")
var shared1 = kp2.pubkey.scalarMul(kp1.seckey) var shared1 = kp2.pubkey.scalarMul(kp1.seckey)
var shared2 = kp1.pubkey.scalarMul(kp2.seckey) var shared2 = kp1.pubkey.scalarMul(kp2.seckey)
check: check:
@ -562,10 +562,10 @@ suite "EC NIST-P256/384/521 test suite":
for i in 6..<9: for i in 6..<9:
var key1 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2])) var key1 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2]))
var key2 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2 + 1])) var key2 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2 + 1]))
var seckey1 = EcPrivateKey.initRaw(key1) var seckey1 = EcPrivateKey.initRaw(key1).expect("private key")
var seckey2 = EcPrivateKey.initRaw(key2) var seckey2 = EcPrivateKey.initRaw(key2).expect("private key")
var pubkey1 = seckey1.getKey() var pubkey1 = seckey1.getKey().expect("public key")
var pubkey2 = seckey2.getKey() var pubkey2 = seckey2.getKey().expect("public key")
var secret1 = getSecret(pubkey2, seckey1) var secret1 = getSecret(pubkey2, seckey1)
var secret2 = getSecret(pubkey1, seckey2) var secret2 = getSecret(pubkey1, seckey2)
var expsecret = fromHex(stripSpaces(ECDHESecrets[i])) var expsecret = fromHex(stripSpaces(ECDHESecrets[i]))
@ -575,44 +575,44 @@ suite "EC NIST-P256/384/521 test suite":
test "[secp521r1] ECDSA test vectors": test "[secp521r1] ECDSA test vectors":
for i in 4..<6: for i in 4..<6:
var sk = EcPrivateKey.init(stripSpaces(SignatureSecKeys[i])) var sk = EcPrivateKey.init(stripSpaces(SignatureSecKeys[i])).expect("private key")
var expectpk = EcPublicKey.init(stripSpaces(SignaturePubKeys[i])) var expectpk = EcPublicKey.init(stripSpaces(SignaturePubKeys[i])).expect("public key")
var checkpk = sk.getKey() var checkpk = sk.getKey().expect("public key")
check expectpk == checkpk check expectpk == checkpk
var checksig = sk.sign(SignatureMessages[i]) var checksig = sk.sign(SignatureMessages[i]).expect("signature")
var expectsig = EcSignature.init(stripSpaces(SignatureVectors[i])) var expectsig = EcSignature.init(stripSpaces(SignatureVectors[i])).expect("signature")
check: check:
checksig == expectsig checksig == expectsig
checksig.verify(SignatureMessages[i], checkpk) == true checksig.verify(SignatureMessages[i], checkpk) == true
let error = len(checksig.buffer) - 1 let error = checksig.buffer.high
checksig.buffer[error] = not(checksig.buffer[error]) checksig.buffer[error] = not(checksig.buffer[error])
check checksig.verify(SignatureMessages[i], checkpk) == false check checksig.verify(SignatureMessages[i], checkpk) == false
test "[secp521r1] ECDSA non-deterministic test vectors": test "[secp521r1] ECDSA non-deterministic test vectors":
var sk = EcPrivateKey.init(stripSpaces(NDPrivateKeys[2])) var sk = EcPrivateKey.init(stripSpaces(NDPrivateKeys[2])).expect("private key")
var pk = EcPublicKey.init(stripSpaces(NDPublicKeys[2])) var pk = EcPublicKey.init(stripSpaces(NDPublicKeys[2])).expect("public key")
var checkpk = sk.getKey() var checkpk = sk.getKey().expect("public key")
check pk == checkpk check pk == checkpk
for i in 12..<18: for i in 12..<18:
var message = NDMessages[i] var message = NDMessages[i]
var checksig = EcSignature.init(stripSpaces(NDSignatures[i])) var checksig = EcSignature.init(stripSpaces(NDSignatures[i])).expect("signature")
check checksig.verify(message, pk) == true check checksig.verify(message, pk) == true
let error = len(checksig.buffer) - 1 let error = checksig.buffer.high
checksig.buffer[error] = not(checksig.buffer[error]) checksig.buffer[error] = not(checksig.buffer[error])
check checksig.verify(message, pk) == false check checksig.verify(message, pk) == false
test "[secp521r1] Generate/Sign/Serialize/Deserialize/Verify test": test "[secp521r1] Generate/Sign/Serialize/Deserialize/Verify test":
var message = "message to sign" var message = "message to sign"
for i in 0..<TestsCount: for i in 0..<TestsCount:
var kp = EcKeyPair.random(Secp521r1) var kp = EcKeyPair.random(Secp521r1).expect("random key")
var sig = kp.seckey.sign(message) var sig = kp.seckey.sign(message).expect("signature")
var sersk = kp.seckey.getBytes() var sersk = kp.seckey.getBytes().expect("bytes")
var serpk = kp.pubkey.getBytes() var serpk = kp.pubkey.getBytes().expect("bytes")
var sersig = sig.getBytes() var sersig = sig.getBytes().expect("bytes")
discard EcPrivateKey.init(sersk) discard EcPrivateKey.init(sersk).expect("private key")
var pubkey = EcPublicKey.init(serpk) var pubkey = EcPublicKey.init(serpk).expect("public key")
var csig = EcSignature.init(sersig) var csig = EcSignature.init(sersig).expect("signature")
check csig.verify(message, pubkey) == true check csig.verify(message, pubkey) == true
let error = len(csig.buffer) - 1 let error = csig.buffer.high
csig.buffer[error] = not(csig.buffer[error]) csig.buffer[error] = not(csig.buffer[error])
check csig.verify(message, pubkey) == false check csig.verify(message, pubkey) == false

View File

@ -111,15 +111,15 @@ suite "Ed25519 test suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: EdPrivateKey var rkey1, rkey2: EdPrivateKey
var skey2 = newSeq[byte](256) var skey2 = newSeq[byte](256)
var key = EdPrivateKey.random() var key = EdPrivateKey.random().expect("private key")
var skey1 = key.getBytes() var skey1 = key.getBytes()
check: check:
key.toBytes(skey2) > 0 key.toBytes(skey2) > 0
check: check:
rkey1.init(skey1) == true rkey1.init(skey1) == true
rkey2.init(skey2) == true rkey2.init(skey2) == true
var rkey3 = EdPrivateKey.init(skey1) var rkey3 = EdPrivateKey.init(skey1).expect("key/sig")
var rkey4 = EdPrivateKey.init(skey2) var rkey4 = EdPrivateKey.init(skey2).expect("key/sig")
check: check:
rkey1 == key rkey1 == key
rkey2 == key rkey2 == key
@ -135,14 +135,14 @@ suite "Ed25519 test suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: EdPublicKey var rkey1, rkey2: EdPublicKey
var skey2 = newSeq[byte](256) var skey2 = newSeq[byte](256)
var pair = EdKeyPair.random() var pair = EdKeyPair.random().expect("random key pair")
var skey1 = pair.pubkey.getBytes() var skey1 = pair.pubkey.getBytes()
check: check:
pair.pubkey.toBytes(skey2) > 0 pair.pubkey.toBytes(skey2) > 0
rkey1.init(skey1) == true rkey1.init(skey1) == true
rkey2.init(skey2) == true rkey2.init(skey2) == true
var rkey3 = EdPublicKey.init(skey1) var rkey3 = EdPublicKey.init(skey1).expect("key/sig")
var rkey4 = EdPublicKey.init(skey2) var rkey4 = EdPublicKey.init(skey2).expect("key/sig")
check: check:
rkey1 == pair.pubkey rkey1 == pair.pubkey
rkey2 == pair.pubkey rkey2 == pair.pubkey
@ -156,13 +156,13 @@ suite "Ed25519 test suite":
test "RFC8032 test vectors": test "RFC8032 test vectors":
for i in 0..<5: for i in 0..<5:
var key = EdPrivateKey.init(stripSpaces(SecretKeys[i])) var key = EdPrivateKey.init(stripSpaces(SecretKeys[i])).expect("key/sig")
var exppub = EdPublicKey.init(stripSpaces(PublicKeys[i])) var exppub = EdPublicKey.init(stripSpaces(PublicKeys[i])).expect("key/sig")
var pubkey = key.getKey() var pubkey = key.getKey()
check pubkey == exppub check pubkey == exppub
var msg = fromHex(stripSpaces(Messages[i])) var msg = fromHex(stripSpaces(Messages[i]))
var sig = key.sign(msg) 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 == expsig
check sig.verify(msg, pubkey) == true check sig.verify(msg, pubkey) == true
sig.data[32] = not(sig.data[32]) sig.data[32] = not(sig.data[32])
@ -171,15 +171,15 @@ suite "Ed25519 test suite":
test "Generate/Sign/Serialize/Deserialize/Verify test": test "Generate/Sign/Serialize/Deserialize/Verify test":
var message = "message to sign" var message = "message to sign"
for i in 0..<TestsCount: for i in 0..<TestsCount:
var kp = EdKeyPair.random() var kp = EdKeyPair.random().expect("random key pair")
var sig = kp.seckey.sign(message) var sig = kp.seckey.sign(message)
var sersk = kp.seckey.getBytes() var sersk = kp.seckey.getBytes()
var serpk = kp.pubkey.getBytes() var serpk = kp.pubkey.getBytes()
var sersig = sig.getBytes() var sersig = sig.getBytes()
discard EdPrivateKey.init(sersk) discard EdPrivateKey.init(sersk)
var pubkey = EdPublicKey.init(serpk) var pubkey = EdPublicKey.init(serpk).expect("key/sig")
var csig = EdSignature.init(sersig) var csig = EdSignature.init(sersig).expect("key/sig")
check csig.verify(message, pubkey) == true check csig.verify(message, pubkey) == true
let error = len(csig.data) - 1 let error = csig.data.high
csig.data[error] = not(csig.data[error]) csig.data[error] = not(csig.data[error])
check csig.verify(message, pubkey) == false check csig.verify(message, pubkey) == false

View File

@ -21,7 +21,7 @@ suite "Identify":
test "handle identify message": test "handle identify message":
proc testHandle(): Future[bool] {.async.} = proc testHandle(): Future[bool] {.async.} =
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0") let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
let remoteSecKey = PrivateKey.random(RSA) let remoteSecKey = PrivateKey.random(RSA).get()
let remotePeerInfo = PeerInfo.init(remoteSecKey, let remotePeerInfo = PeerInfo.init(remoteSecKey,
[ma], [ma],
["/test/proto1/1.0.0", ["/test/proto1/1.0.0",
@ -41,12 +41,12 @@ suite "Identify":
let transport2: TcpTransport = newTransport(TcpTransport) let transport2: TcpTransport = newTransport(TcpTransport)
let conn = await transport2.dial(transport1.ma) let conn = await transport2.dial(transport1.ma)
var peerInfo = PeerInfo.init(PrivateKey.random(RSA), [ma]) var peerInfo = PeerInfo.init(PrivateKey.random(RSA).get(), [ma])
let identifyProto2 = newIdentify(peerInfo) let identifyProto2 = newIdentify(peerInfo)
discard await msDial.select(conn, IdentifyCodec) discard await msDial.select(conn, IdentifyCodec)
let id = await identifyProto2.identify(conn, remotePeerInfo) let id = await identifyProto2.identify(conn, remotePeerInfo)
check id.pubKey.get() == remoteSecKey.getKey() check id.pubKey.get() == remoteSecKey.getKey().get()
check id.addrs[0] == ma check id.addrs[0] == ma
check id.protoVersion.get() == ProtoVersion check id.protoVersion.get() == ProtoVersion
# check id.agentVersion.get() == AgentVersion # check id.agentVersion.get() == AgentVersion
@ -66,7 +66,7 @@ suite "Identify":
test "handle failed identify": test "handle failed identify":
proc testHandleError() {.async.} = proc testHandleError() {.async.} =
let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0") let ma: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
var remotePeerInfo = PeerInfo.init(PrivateKey.random(RSA), [ma]) var remotePeerInfo = PeerInfo.init(PrivateKey.random(RSA).get(), [ma])
let identifyProto1 = newIdentify(remotePeerInfo) let identifyProto1 = newIdentify(remotePeerInfo)
let msListen = newMultistream() let msListen = newMultistream()
@ -85,12 +85,12 @@ suite "Identify":
let transport2: TcpTransport = newTransport(TcpTransport) let transport2: TcpTransport = newTransport(TcpTransport)
let conn = await transport2.dial(transport1.ma) let conn = await transport2.dial(transport1.ma)
var localPeerInfo = PeerInfo.init(PrivateKey.random(RSA), [ma]) var localPeerInfo = PeerInfo.init(PrivateKey.random(RSA).get(), [ma])
let identifyProto2 = newIdentify(localPeerInfo) let identifyProto2 = newIdentify(localPeerInfo)
try: try:
discard await msDial.select(conn, IdentifyCodec) discard await msDial.select(conn, IdentifyCodec)
discard await identifyProto2.identify(conn, PeerInfo.init(PrivateKey.random(RSA))) discard await identifyProto2.identify(conn, PeerInfo.init(PrivateKey.random(RSA).get()))
finally: finally:
await done.wait(5000.millis) # when no issues will not wait that long! await done.wait(5000.millis) # when no issues will not wait that long!
await conn.close() await conn.close()

View File

@ -66,7 +66,7 @@ proc createNode*(privKey: Option[PrivateKey] = none(PrivateKey),
gossip: bool = false): Switch = gossip: bool = false): Switch =
var seckey = privKey var seckey = privKey
if privKey.isNone: if privKey.isNone:
seckey = some(PrivateKey.random(RSA)) seckey = some(PrivateKey.random(RSA).get())
var peerInfo = NativePeerInfo.init(seckey.get(), [Multiaddress.init(address)]) var peerInfo = NativePeerInfo.init(seckey.get(), [Multiaddress.init(address)])
proc createMplex(conn: Connection): Muxer = newMplex(conn) proc createMplex(conn: Connection): Muxer = newMplex(conn)

View File

@ -82,8 +82,8 @@ suite "MultiHash test suite":
for item in RustTestVectors: for item in RustTestVectors:
var msg = item[1] var msg = item[1]
var bmsg = cast[seq[byte]](msg) var bmsg = cast[seq[byte]](msg)
var mh1 = MultiHash.digest(item[0], bmsg) var mh1 = MultiHash.digest(item[0], bmsg).get()
var mh2 = MultiHash.init(stripSpaces(item[2])) var mh2 = MultiHash.init(stripSpaces(item[2])).get()
check: check:
hex(mh1) == stripSpaces(item[2]) hex(mh1) == stripSpaces(item[2])
hex(mh1) == hex(mh2) hex(mh1) == hex(mh2)

View File

@ -50,7 +50,7 @@ method init(p: TestProto) {.gcsafe.} =
p.handler = handle p.handler = handle
proc createSwitch(ma: MultiAddress; outgoing: bool): (Switch, PeerInfo) = proc createSwitch(ma: MultiAddress; outgoing: bool): (Switch, PeerInfo) =
var peerInfo: PeerInfo = PeerInfo.init(PrivateKey.random(RSA)) var peerInfo: PeerInfo = PeerInfo.init(PrivateKey.random(RSA).get())
peerInfo.addrs.add(ma) peerInfo.addrs.add(ma)
let identify = newIdentify(peerInfo) let identify = newIdentify(peerInfo)
@ -77,7 +77,7 @@ suite "Noise":
proc testListenerDialer(): Future[bool] {.async.} = proc testListenerDialer(): Future[bool] {.async.} =
let let
server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0") server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
serverInfo = PeerInfo.init(PrivateKey.random(RSA), [server]) serverInfo = PeerInfo.init(PrivateKey.random(RSA).get(), [server])
serverNoise = newNoise(serverInfo.privateKey, outgoing = false) serverNoise = newNoise(serverInfo.privateKey, outgoing = false)
proc connHandler(conn: Connection) {.async, gcsafe.} = proc connHandler(conn: Connection) {.async, gcsafe.} =
@ -93,7 +93,7 @@ suite "Noise":
let let
transport2: TcpTransport = newTransport(TcpTransport) transport2: TcpTransport = newTransport(TcpTransport)
clientInfo = PeerInfo.init(PrivateKey.random(RSA), [transport1.ma]) clientInfo = PeerInfo.init(PrivateKey.random(RSA).get(), [transport1.ma])
clientNoise = newNoise(clientInfo.privateKey, outgoing = true) clientNoise = newNoise(clientInfo.privateKey, outgoing = true)
conn = await transport2.dial(transport1.ma) conn = await transport2.dial(transport1.ma)
sconn = await clientNoise.secure(conn, true) sconn = await clientNoise.secure(conn, true)
@ -115,7 +115,7 @@ suite "Noise":
proc testListenerDialer(): Future[bool] {.async.} = proc testListenerDialer(): Future[bool] {.async.} =
let let
server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0") server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
serverInfo = PeerInfo.init(PrivateKey.random(RSA), [server]) serverInfo = PeerInfo.init(PrivateKey.random(RSA).get(), [server])
serverNoise = newNoise(serverInfo.privateKey, outgoing = false) serverNoise = newNoise(serverInfo.privateKey, outgoing = false)
readTask = newFuture[void]() readTask = newFuture[void]()
@ -135,7 +135,7 @@ suite "Noise":
let let
transport2: TcpTransport = newTransport(TcpTransport) transport2: TcpTransport = newTransport(TcpTransport)
clientInfo = PeerInfo.init(PrivateKey.random(RSA), [transport1.ma]) clientInfo = PeerInfo.init(PrivateKey.random(RSA).get(), [transport1.ma])
clientNoise = newNoise(clientInfo.privateKey, outgoing = true) clientNoise = newNoise(clientInfo.privateKey, outgoing = true)
conn = await transport2.dial(transport1.ma) conn = await transport2.dial(transport1.ma)
sconn = await clientNoise.secure(conn, true) sconn = await clientNoise.secure(conn, true)
@ -156,7 +156,7 @@ suite "Noise":
proc testListenerDialer(): Future[bool] {.async.} = proc testListenerDialer(): Future[bool] {.async.} =
let let
server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0") server: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
serverInfo = PeerInfo.init(PrivateKey.random(RSA), [server]) serverInfo = PeerInfo.init(PrivateKey.random(RSA).get(), [server])
serverNoise = newNoise(serverInfo.privateKey, outgoing = false) serverNoise = newNoise(serverInfo.privateKey, outgoing = false)
readTask = newFuture[void]() readTask = newFuture[void]()
@ -178,7 +178,7 @@ suite "Noise":
let let
transport2: TcpTransport = newTransport(TcpTransport) transport2: TcpTransport = newTransport(TcpTransport)
clientInfo = PeerInfo.init(PrivateKey.random(RSA), [transport1.ma]) clientInfo = PeerInfo.init(PrivateKey.random(RSA).get(), [transport1.ma])
clientNoise = newNoise(clientInfo.privateKey, outgoing = true) clientNoise = newNoise(clientInfo.privateKey, outgoing = true)
conn = await transport2.dial(transport1.ma) conn = await transport2.dial(transport1.ma)
sconn = await clientNoise.secure(conn, true) sconn = await clientNoise.secure(conn, true)

View File

@ -101,8 +101,8 @@ const
suite "Peer testing suite": suite "Peer testing suite":
test "Go PeerID test vectors": test "Go PeerID test vectors":
for i in 0..<len(PrivateKeys): for i in 0..<len(PrivateKeys):
var seckey = PrivateKey.init(stripSpaces(PrivateKeys[i])) var seckey = PrivateKey.init(stripSpaces(PrivateKeys[i])).get()
var pubkey = seckey.getKey() var pubkey = seckey.getKey().get()
var p1 = PeerID.init(seckey) var p1 = PeerID.init(seckey)
var p2 = PeerID.init(pubkey) var p2 = PeerID.init(pubkey)
var p3 = PeerID.init(PeerIDs[i]) var p3 = PeerID.init(PeerIDs[i])

View File

@ -13,29 +13,29 @@ suite "PeerInfo":
check tracker.isLeaked() == false check tracker.isLeaked() == false
test "Should init with private key": test "Should init with private key":
let seckey = PrivateKey.random(RSA) let seckey = PrivateKey.random(RSA).get()
var peerInfo = PeerInfo.init(seckey) var peerInfo = PeerInfo.init(seckey)
var peerId = PeerID.init(seckey) var peerId = PeerID.init(seckey)
check peerId == peerInfo.peerId check peerId == peerInfo.peerId
check seckey == peerInfo.privateKey check seckey == peerInfo.privateKey
check seckey.getKey == peerInfo.publicKey.get() check seckey.getKey().get() == peerInfo.publicKey.get()
test "Should init with public key": test "Should init with public key":
let seckey = PrivateKey.random(RSA) let seckey = PrivateKey.random(RSA).get()
var peerInfo = PeerInfo.init(seckey.getKey()) var peerInfo = PeerInfo.init(seckey.getKey().get())
var peerId = PeerID.init(seckey.getKey()) var peerId = PeerID.init(seckey.getKey().get())
check peerId == peerInfo.peerId check peerId == peerInfo.peerId
check seckey.getKey == peerInfo.publicKey.get() check seckey.getKey.get() == peerInfo.publicKey.get()
test "Should init from PeerId with public key": test "Should init from PeerId with public key":
let seckey = PrivateKey.random(Ed25519) let seckey = PrivateKey.random(Ed25519).get()
var peerInfo = PeerInfo.init(PeerID.init(seckey.getKey())) var peerInfo = PeerInfo.init(PeerID.init(seckey.getKey.get()))
var peerId = PeerID.init(seckey.getKey()) var peerId = PeerID.init(seckey.getKey.get())
check peerId == peerInfo.peerId check peerId == peerInfo.peerId
check seckey.getKey == peerInfo.publicKey.get() check seckey.getKey.get() == peerInfo.publicKey.get()
test "Should init from CIDv0 string": test "Should init from CIDv0 string":
var peerInfo = PeerInfo.init("QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N") var peerInfo = PeerInfo.init("QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N")
@ -52,16 +52,16 @@ suite "PeerInfo":
# PeerID.init("bafzbeie5745rpv2m6tjyuugywy4d5ewrqgqqhfnf445he3omzpjbx5xqxe") == peerInfo.peerId # PeerID.init("bafzbeie5745rpv2m6tjyuugywy4d5ewrqgqqhfnf445he3omzpjbx5xqxe") == peerInfo.peerId
test "Should return none if pubkey is missing from id": test "Should return none if pubkey is missing from id":
let peerInfo = PeerInfo.init(PeerID.init(PrivateKey.random(RSA))) let peerInfo = PeerInfo.init(PeerID.init(PrivateKey.random(RSA).get()))
check peerInfo.publicKey.isNone check peerInfo.publicKey.isNone
test "Should return some if pubkey is present in id": test "Should return some if pubkey is present in id":
let peerInfo = PeerInfo.init(PeerID.init(PrivateKey.random(Ed25519))) let peerInfo = PeerInfo.init(PeerID.init(PrivateKey.random(Ed25519).get()))
check peerInfo.publicKey.isSome check peerInfo.publicKey.isSome
test "join() and isClosed() test": test "join() and isClosed() test":
proc testJoin(): Future[bool] {.async, gcsafe.} = proc testJoin(): Future[bool] {.async, gcsafe.} =
let peerInfo = PeerInfo.init(PeerID.init(PrivateKey.random(Ed25519))) let peerInfo = PeerInfo.init(PeerID.init(PrivateKey.random(Ed25519).get()))
check peerInfo.isClosed() == false check peerInfo.isClosed() == false
var joinFut = peerInfo.join() var joinFut = peerInfo.join()
check joinFut.finished() == false check joinFut.finished() == false

View File

@ -273,14 +273,14 @@ suite "RSA 512/1024/2048/4096 test suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: RsaPrivateKey var rkey1, rkey2: RsaPrivateKey
var skey2 = newSeq[byte](4096) var skey2 = newSeq[byte](4096)
var key = RsaPrivateKey.random(512) var key = RsaPrivateKey.random(512).expect("random key")
var skey1 = key.getBytes() var skey1 = key.getBytes().expect("bytes")
check key.toBytes(skey2) > 0 check key.toBytes(skey2).expect("bytes") > 0
check: check:
rkey1.init(skey1).isOk() rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk() rkey2.init(skey2).isOk()
var rkey3 = RsaPrivateKey.init(skey1) var rkey3 = RsaPrivateKey.init(skey1).expect("key initialization")
var rkey4 = RsaPrivateKey.init(skey2) var rkey4 = RsaPrivateKey.init(skey2).expect("key initialization")
check: check:
rkey1 == key rkey1 == key
rkey2 == key rkey2 == key
@ -291,14 +291,14 @@ suite "RSA 512/1024/2048/4096 test suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: RsaPrivateKey var rkey1, rkey2: RsaPrivateKey
var skey2 = newSeq[byte](4096) var skey2 = newSeq[byte](4096)
var key = RsaPrivateKey.random(1024) var key = RsaPrivateKey.random(1024).expect("random failed")
var skey1 = key.getBytes() var skey1 = key.getBytes().expect("bytes")
check key.toBytes(skey2) > 0 check key.toBytes(skey2).expect("bytes") > 0
check: check:
rkey1.init(skey1).isOk() rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk() rkey2.init(skey2).isOk()
var rkey3 = RsaPrivateKey.init(skey1) var rkey3 = RsaPrivateKey.init(skey1).expect("key initialization")
var rkey4 = RsaPrivateKey.init(skey2) var rkey4 = RsaPrivateKey.init(skey2).expect("key initialization")
check: check:
rkey1 == key rkey1 == key
rkey2 == key rkey2 == key
@ -308,14 +308,14 @@ suite "RSA 512/1024/2048/4096 test suite":
test "[rsa2048] Private key serialize/deserialize test": test "[rsa2048] Private key serialize/deserialize test":
var rkey1, rkey2: RsaPrivateKey var rkey1, rkey2: RsaPrivateKey
var skey2 = newSeq[byte](4096) var skey2 = newSeq[byte](4096)
var key = RsaPrivateKey.random(2048) var key = RsaPrivateKey.random(2048).expect("random failed")
var skey1 = key.getBytes() var skey1 = key.getBytes().expect("bytes")
check key.toBytes(skey2) > 0 check key.toBytes(skey2).expect("bytes") > 0
check: check:
rkey1.init(skey1).isOk() rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk() rkey2.init(skey2).isOk()
var rkey3 = RsaPrivateKey.init(skey1) var rkey3 = RsaPrivateKey.init(skey1).expect("key initialization")
var rkey4 = RsaPrivateKey.init(skey2) var rkey4 = RsaPrivateKey.init(skey2).expect("key initialization")
check: check:
rkey1 == key rkey1 == key
rkey2 == key rkey2 == key
@ -327,14 +327,14 @@ suite "RSA 512/1024/2048/4096 test suite":
when defined(release): when defined(release):
var rkey1, rkey2: RsaPrivateKey var rkey1, rkey2: RsaPrivateKey
var skey2 = newSeq[byte](4096) var skey2 = newSeq[byte](4096)
var key = RsaPrivateKey.random(4096) var key = RsaPrivateKey.random(4096).expect("random failed")
var skey1 = key.getBytes() var skey1 = key.getBytes().expect("bytes")
check key.toBytes(skey2) > 0 check key.toBytes(skey2).expect("bytes") > 0
check: check:
rkey1.init(skey1).isOk() rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk() rkey2.init(skey2).isOk()
var rkey3 = RsaPrivateKey.init(skey1) var rkey3 = RsaPrivateKey.init(skey1).expect("key initialization")
var rkey4 = RsaPrivateKey.init(skey2) var rkey4 = RsaPrivateKey.init(skey2).expect("key initialization")
check: check:
rkey1 == key rkey1 == key
rkey2 == key rkey2 == key
@ -345,14 +345,14 @@ suite "RSA 512/1024/2048/4096 test suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: RsaPublicKey var rkey1, rkey2: RsaPublicKey
var skey2 = newSeq[byte](4096) var skey2 = newSeq[byte](4096)
var pair = RsaKeyPair.random(512) var pair = RsaKeyPair.random(512).expect("random failed")
var skey1 = pair.pubkey().getBytes() var skey1 = pair.pubkey().getBytes().expect("bytes")
check: check:
pair.pubkey.toBytes(skey2) > 0 pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk() rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk() rkey2.init(skey2).isOk()
var rkey3 = RsaPublicKey.init(skey1) var rkey3 = RsaPublicKey.init(skey1).expect("key initialization")
var rkey4 = RsaPublicKey.init(skey2) var rkey4 = RsaPublicKey.init(skey2).expect("key initialization")
check: check:
rkey1 == pair.pubkey rkey1 == pair.pubkey
rkey2 == pair.pubkey rkey2 == pair.pubkey
@ -363,14 +363,14 @@ suite "RSA 512/1024/2048/4096 test suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: RsaPublicKey var rkey1, rkey2: RsaPublicKey
var skey2 = newSeq[byte](4096) var skey2 = newSeq[byte](4096)
var pair = RsaKeyPair.random(1024) var pair = RsaKeyPair.random(1024).expect("random failed")
var skey1 = pair.pubkey.getBytes() var skey1 = pair.pubkey.getBytes().expect("bytes")
check: check:
pair.pubkey.toBytes(skey2) > 0 pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk() rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk() rkey2.init(skey2).isOk()
var rkey3 = RsaPublicKey.init(skey1) var rkey3 = RsaPublicKey.init(skey1).expect("key initialization")
var rkey4 = RsaPublicKey.init(skey2) var rkey4 = RsaPublicKey.init(skey2).expect("key initialization")
check: check:
rkey1 == pair.pubkey rkey1 == pair.pubkey
rkey2 == pair.pubkey rkey2 == pair.pubkey
@ -380,14 +380,14 @@ suite "RSA 512/1024/2048/4096 test suite":
test "[rsa2048] Public key serialize/deserialize test": test "[rsa2048] Public key serialize/deserialize test":
var rkey1, rkey2: RsaPublicKey var rkey1, rkey2: RsaPublicKey
var skey2 = newSeq[byte](4096) var skey2 = newSeq[byte](4096)
var pair = RsaKeyPair.random(2048) var pair = RsaKeyPair.random(2048).expect("random failed")
var skey1 = pair.pubkey.getBytes() var skey1 = pair.pubkey.getBytes().expect("bytes")
check: check:
pair.pubkey.toBytes(skey2) > 0 pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk() rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk() rkey2.init(skey2).isOk()
var rkey3 = RsaPublicKey.init(skey1) var rkey3 = RsaPublicKey.init(skey1).expect("key initialization")
var rkey4 = RsaPublicKey.init(skey2) var rkey4 = RsaPublicKey.init(skey2).expect("key initialization")
check: check:
rkey1 == pair.pubkey rkey1 == pair.pubkey
rkey2 == pair.pubkey rkey2 == pair.pubkey
@ -398,14 +398,14 @@ suite "RSA 512/1024/2048/4096 test suite":
when defined(release): when defined(release):
var rkey1, rkey2: RsaPublicKey var rkey1, rkey2: RsaPublicKey
var skey2 = newSeq[byte](4096) var skey2 = newSeq[byte](4096)
var pair = RsaKeyPair.random(4096) var pair = RsaKeyPair.random(4096).expect("random failed")
var skey1 = pair.pubkey.getBytes() var skey1 = pair.pubkey.getBytes().expect("bytes")
check: check:
pair.pubkey.toBytes(skey2) > 0 pair.pubkey.toBytes(skey2).expect("bytes") > 0
rkey1.init(skey1).isOk() rkey1.init(skey1).isOk()
rkey2.init(skey2).isOk() rkey2.init(skey2).isOk()
var rkey3 = RsaPublicKey.init(skey1) var rkey3 = RsaPublicKey.init(skey1).expect("key initialization")
var rkey4 = RsaPublicKey.init(skey2) var rkey4 = RsaPublicKey.init(skey2).expect("key initialization")
check: check:
rkey1 == pair.pubkey rkey1 == pair.pubkey
rkey2 == 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": test "[rsa512] Generate/Sign/Serialize/Deserialize/Verify test":
var message = "message to sign" var message = "message to sign"
for i in 0..<TestsCount: for i in 0..<TestsCount:
var kp = RsaKeyPair.random(512) var kp = RsaKeyPair.random(512).expect("RsaKeyPair.random failed")
var sig = kp.seckey.sign(message) var sig = kp.seckey.sign(message).expect("signature")
var sersk = kp.seckey.getBytes() var sersk = kp.seckey.getBytes().expect("bytes")
var serpk = kp.pubkey.getBytes() var serpk = kp.pubkey.getBytes().expect("bytes")
var sersig = sig.getBytes() var sersig = sig.getBytes().expect("bytes")
discard RsaPrivateKey.init(sersk) discard RsaPrivateKey.init(sersk).expect("RsaPrivateKey.key initialization")
var pubkey = RsaPublicKey.init(serpk) var pubkey = RsaPublicKey.init(serpk).expect("RsaPublicKey.key initialization")
var csig = RsaSignature.init(sersig) var csig = RsaSignature.init(sersig).expect("RsaSignature.key initialization")
check csig.verify(message, pubkey) == true check csig.verify(message, pubkey) == true
let error = len(csig.buffer) - 1 let error = csig.buffer.high
csig.buffer[error] = not(csig.buffer[error]) csig.buffer[error] = not(csig.buffer[error])
check csig.verify(message, pubkey) == false check csig.verify(message, pubkey) == false
test "[rsa1024] Generate/Sign/Serialize/Deserialize/Verify test": test "[rsa1024] Generate/Sign/Serialize/Deserialize/Verify test":
var message = "message to sign" var message = "message to sign"
for i in 0..<TestsCount: for i in 0..<TestsCount:
var kp = RsaKeyPair.random(1024) var kp = RsaKeyPair.random(1024).expect("RsaPrivateKey.random failed")
var sig = kp.seckey.sign(message) var sig = kp.seckey.sign(message).expect("signature")
var sersk = kp.seckey.getBytes() var sersk = kp.seckey.getBytes().expect("bytes")
var serpk = kp.pubkey.getBytes() var serpk = kp.pubkey.getBytes().expect("bytes")
var sersig = sig.getBytes() var sersig = sig.getBytes().expect("bytes")
discard RsaPrivateKey.init(sersk) discard RsaPrivateKey.init(sersk).expect("key initialization")
var pubkey = RsaPublicKey.init(serpk) var pubkey = RsaPublicKey.init(serpk).expect("key initialization")
var csig = RsaSignature.init(sersig) var csig = RsaSignature.init(sersig).expect("key initialization")
check csig.verify(message, pubkey) == true check csig.verify(message, pubkey) == true
let error = len(csig.buffer) - 1 let error = csig.buffer.high
csig.buffer[error] = not(csig.buffer[error]) csig.buffer[error] = not(csig.buffer[error])
check csig.verify(message, pubkey) == false check csig.verify(message, pubkey) == false
test "[rsa2048] Generate/Sign/Serialize/Deserialize/Verify test": test "[rsa2048] Generate/Sign/Serialize/Deserialize/Verify test":
var message = "message to sign" var message = "message to sign"
var kp = RsaKeyPair.random(2048) var kp = RsaKeyPair.random(2048).expect("RsaPrivateKey.random failed")
var sig = kp.seckey.sign(message) var sig = kp.seckey.sign(message).expect("signature")
var sersk = kp.seckey.getBytes() var sersk = kp.seckey.getBytes().expect("bytes")
var serpk = kp.pubkey.getBytes() var serpk = kp.pubkey.getBytes().expect("bytes")
var sersig = sig.getBytes() var sersig = sig.getBytes().expect("bytes")
discard RsaPrivateKey.init(sersk) discard RsaPrivateKey.init(sersk).expect("key initialization")
var pubkey = RsaPublicKey.init(serpk) var pubkey = RsaPublicKey.init(serpk).expect("key initialization")
var csig = RsaSignature.init(sersig) var csig = RsaSignature.init(sersig).expect("key initialization")
check csig.verify(message, pubkey) == true check csig.verify(message, pubkey) == true
let error = len(csig.buffer) - 1 let error = csig.buffer.high
csig.buffer[error] = not(csig.buffer[error]) csig.buffer[error] = not(csig.buffer[error])
check csig.verify(message, pubkey) == false check csig.verify(message, pubkey) == false
test "[rsa4096] Generate/Sign/Serialize/Deserialize/Verify test": test "[rsa4096] Generate/Sign/Serialize/Deserialize/Verify test":
when defined(release): when defined(release):
var message = "message to sign" var message = "message to sign"
var kp = RsaKeyPair.random(2048) var kp = RsaKeyPair.random(2048).expect("RsaPrivateKey.random failed")
var sig = kp.seckey.sign(message) var sig = kp.seckey.sign(message).expect("signature")
var sersk = kp.seckey.getBytes() var sersk = kp.seckey.getBytes().expect("bytes")
var serpk = kp.pubkey.getBytes() var serpk = kp.pubkey.getBytes().expect("bytes")
var sersig = sig.getBytes() var sersig = sig.getBytes().expect("bytes")
discard RsaPrivateKey.init(sersk) discard RsaPrivateKey.init(sersk).expect("key initialization")
var pubkey = RsaPublicKey.init(serpk) var pubkey = RsaPublicKey.init(serpk).expect("key initialization")
var csig = RsaSignature.init(sersig) var csig = RsaSignature.init(sersig).expect("key initialization")
check csig.verify(message, pubkey) == true check csig.verify(message, pubkey) == true
let error = len(csig.buffer) - 1 let error = csig.buffer.high
csig.buffer[error] = not(csig.buffer[error]) csig.buffer[error] = not(csig.buffer[error])
check csig.verify(message, pubkey) == false check csig.verify(message, pubkey) == false
test "[rsa512] Test vectors": test "[rsa512] Test vectors":
var prvser = fromHex(stripSpaces(PrivateKeys[0])) var prvser = fromHex(stripSpaces(PrivateKeys[0]))
var pubser = fromHex(stripSpaces(PublicKeys[0])) var pubser = fromHex(stripSpaces(PublicKeys[0]))
var seckey = RsaPrivateKey.init(prvser) var seckey = RsaPrivateKey.init(prvser).expect("key initialization")
var pubkey = RsaPublicKey.init(pubser) var pubkey = RsaPublicKey.init(pubser).expect("key initialization")
check: check:
seckey.getBytes() == prvser seckey.getBytes().expect("bytes") == prvser
var cpubkey = seckey.getKey() var cpubkey = seckey.getKey()
check: check:
pubkey == cpubkey pubkey == cpubkey
pubkey.getBytes() == cpubkey.getBytes() pubkey.getBytes().expect("bytes") == cpubkey.getBytes().expect("bytes")
pubkey.getBytes() == pubser pubkey.getBytes().expect("bytes") == pubser
for i in 0..1: for i in 0..1:
var sigser = fromHex(stripSpaces(Signatures[i])) var sigser = fromHex(stripSpaces(Signatures[i]))
var sig = RsaSignature.init(sigser) var sig = RsaSignature.init(sigser).expect("key initialization")
var csig = seckey.sign(Messages[i]) var csig = seckey.sign(Messages[i]).expect("signature")
check: check:
sig == csig sig == csig
sig.getBytes() == csig.getBytes() sig.getBytes().expect("bytes") == csig.getBytes().expect("bytes")
csig.verify(Messages[i], pubkey) == true csig.verify(Messages[i], pubkey) == true
csig.verify(Messages[(i + 1) mod 2], pubkey) == false csig.verify(Messages[(i + 1) mod 2], pubkey) == false
test "[rsa1024] Test vectors": test "[rsa1024] Test vectors":
var prvser = fromHex(stripSpaces(PrivateKeys[1])) var prvser = fromHex(stripSpaces(PrivateKeys[1]))
var pubser = fromHex(stripSpaces(PublicKeys[1])) var pubser = fromHex(stripSpaces(PublicKeys[1]))
var seckey = RsaPrivateKey.init(prvser) var seckey = RsaPrivateKey.init(prvser).expect("key initialization")
var pubkey = RsaPublicKey.init(pubser) var pubkey = RsaPublicKey.init(pubser).expect("key initialization")
check: check:
seckey.getBytes() == prvser seckey.getBytes().expect("bytes") == prvser
var cpubkey = seckey.getKey() var cpubkey = seckey.getKey()
check: check:
pubkey == cpubkey pubkey == cpubkey
pubkey.getBytes() == cpubkey.getBytes() pubkey.getBytes().expect("bytes") == cpubkey.getBytes().expect("bytes")
pubkey.getBytes() == pubser pubkey.getBytes().expect("bytes") == pubser
for i in 0..1: for i in 0..1:
var sigser = fromHex(stripSpaces(Signatures[2 + i])) var sigser = fromHex(stripSpaces(Signatures[2 + i]))
var sig = RsaSignature.init(sigser) var sig = RsaSignature.init(sigser).expect("key initialization")
var csig = seckey.sign(Messages[2 + i]) var csig = seckey.sign(Messages[2 + i]).expect("signature")
check: check:
sig == csig sig == csig
sig.getBytes() == csig.getBytes() sig.getBytes().expect("bytes") == csig.getBytes().expect("bytes")
csig.verify(Messages[2 + i], pubkey) == true csig.verify(Messages[2 + i], pubkey) == true
csig.verify(Messages[2 + (i + 1) mod 2], pubkey) == false csig.verify(Messages[2 + (i + 1) mod 2], pubkey) == false
test "[rsa2048] Test vectors": test "[rsa2048] Test vectors":
var prvser = fromHex(stripSpaces(PrivateKeys[2])) var prvser = fromHex(stripSpaces(PrivateKeys[2]))
var pubser = fromHex(stripSpaces(PublicKeys[2])) var pubser = fromHex(stripSpaces(PublicKeys[2]))
var seckey = RsaPrivateKey.init(prvser) var seckey = RsaPrivateKey.init(prvser).expect("key initialization")
var pubkey = RsaPublicKey.init(pubser) var pubkey = RsaPublicKey.init(pubser).expect("key initialization")
check: check:
seckey.getBytes() == prvser seckey.getBytes().expect("bytes") == prvser
var cpubkey = seckey.getKey() var cpubkey = seckey.getKey()
check: check:
pubkey == cpubkey pubkey == cpubkey
pubkey.getBytes() == cpubkey.getBytes() pubkey.getBytes().expect("bytes") == cpubkey.getBytes().expect("bytes")
pubkey.getBytes() == pubser pubkey.getBytes().expect("bytes") == pubser
for i in 0..1: for i in 0..1:
var sigser = fromHex(stripSpaces(Signatures[4 + i])) var sigser = fromHex(stripSpaces(Signatures[4 + i]))
var sig = RsaSignature.init(sigser) var sig = RsaSignature.init(sigser).expect("key initialization")
var csig = seckey.sign(Messages[4 + i]) var csig = seckey.sign(Messages[4 + i]).expect("signature")
check: check:
sig == csig sig == csig
sig.getBytes() == csig.getBytes() sig.getBytes().expect("bytes") == csig.getBytes().expect("bytes")
csig.verify(Messages[4 + i], pubkey) == true csig.verify(Messages[4 + i], pubkey) == true
csig.verify(Messages[4 + (i + 1) mod 2], pubkey) == false csig.verify(Messages[4 + (i + 1) mod 2], pubkey) == false
test "[rsa4096] Test vectors": test "[rsa4096] Test vectors":
var prvser = fromHex(stripSpaces(PrivateKeys[3])) var prvser = fromHex(stripSpaces(PrivateKeys[3]))
var pubser = fromHex(stripSpaces(PublicKeys[3])) var pubser = fromHex(stripSpaces(PublicKeys[3]))
var seckey = RsaPrivateKey.init(prvser) var seckey = RsaPrivateKey.init(prvser).expect("key initialization")
var pubkey = RsaPublicKey.init(pubser) var pubkey = RsaPublicKey.init(pubser).expect("key initialization")
check: check:
seckey.getBytes() == prvser seckey.getBytes().expect("bytes") == prvser
var cpubkey = seckey.getKey() var cpubkey = seckey.getKey()
check: check:
pubkey == cpubkey pubkey == cpubkey
pubkey.getBytes() == cpubkey.getBytes() pubkey.getBytes().expect("bytes") == cpubkey.getBytes().expect("bytes")
pubkey.getBytes() == pubser pubkey.getBytes().expect("bytes") == pubser
for i in 0..1: for i in 0..1:
var sigser = fromHex(stripSpaces(Signatures[6 + i])) var sigser = fromHex(stripSpaces(Signatures[6 + i]))
var sig = RsaSignature.init(sigser) var sig = RsaSignature.init(sigser).expect("key initialization")
var csig = seckey.sign(Messages[6 + i]) var csig = seckey.sign(Messages[6 + i]).expect("signature")
check: check:
sig == csig sig == csig
sig.getBytes() == csig.getBytes() sig.getBytes().expect("bytes") == csig.getBytes().expect("bytes")
csig.verify(Messages[6 + i], pubkey) == true csig.verify(Messages[6 + i], pubkey) == true
csig.verify(Messages[6 + (i + 1) mod 2], pubkey) == false csig.verify(Messages[6 + (i + 1) mod 2], pubkey) == false

View File

@ -18,15 +18,15 @@ suite "Secp256k1 testing suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: SkPrivateKey var rkey1, rkey2: SkPrivateKey
var skey2 = newSeq[byte](256) var skey2 = newSeq[byte](256)
var key = SkPrivateKey.random() var key = SkPrivateKey.random().expect("random key")
var skey1 = key.getBytes() var skey1 = key.getBytes()
check: check:
key.toBytes(skey2) > 0 key.toBytes(skey2).expect("bytes len") > 0
check: check:
rkey1.init(skey1) == true rkey1.init(skey1).isOk == true
rkey2.init(skey2) == true rkey2.init(skey2).isOk == true
var rkey3 = SkPrivateKey.init(skey1) var rkey3 = SkPrivateKey.init(skey1).expect("private key")
var rkey4 = SkPrivateKey.init(skey2) var rkey4 = SkPrivateKey.init(skey2).expect("private key")
check: check:
rkey1 == key rkey1 == key
rkey2 == key rkey2 == key
@ -41,14 +41,14 @@ suite "Secp256k1 testing suite":
for i in 0..<TestsCount: for i in 0..<TestsCount:
var rkey1, rkey2: SkPublicKey var rkey1, rkey2: SkPublicKey
var skey2 = newSeq[byte](256) var skey2 = newSeq[byte](256)
var pair = SkKeyPair.random() var pair = SkKeyPair.random().expect("random key pair")
var skey1 = pair.pubkey.getBytes() var skey1 = pair.pubkey.getBytes()
check: check:
pair.pubkey.toBytes(skey2) > 0 pair.pubkey.toBytes(skey2).expect("bytes len") > 0
rkey1.init(skey1) == true rkey1.init(skey1).isOk == true
rkey2.init(skey2) == true rkey2.init(skey2).isOk == true
var rkey3 = SkPublicKey.init(skey1) var rkey3 = SkPublicKey.init(skey1).expect("public key")
var rkey4 = SkPublicKey.init(skey2) var rkey4 = SkPublicKey.init(skey2).expect("public key")
check: check:
rkey1 == pair.pubkey rkey1 == pair.pubkey
rkey2 == pair.pubkey rkey2 == pair.pubkey
@ -59,16 +59,16 @@ suite "Secp256k1 testing suite":
test "Generate/Sign/Serialize/Deserialize/Verify test": test "Generate/Sign/Serialize/Deserialize/Verify test":
var message = "message to sign" var message = "message to sign"
for i in 0..<TestsCount: for i in 0..<TestsCount:
var kp = SkKeyPair.random() var kp = SkKeyPair.random().expect("random key pair")
var sig = kp.seckey.sign(message) var sig = kp.seckey.sign(message).expect("signature")
var sersk = kp.seckey.getBytes() var sersk = kp.seckey.getBytes()
var serpk = kp.pubkey.getBytes() var serpk = kp.pubkey.getBytes()
var sersig = sig.getBytes() var sersig = sig.getBytes()
discard SkPrivateKey.init(sersk) discard SkPrivateKey.init(sersk).expect("private key")
var pubkey = SkPublicKey.init(serpk) var pubkey = SkPublicKey.init(serpk).expect("public key")
var csig = SkSignature.init(sersig) var csig = SkSignature.init(sersig).expect("signature")
check csig.verify(message, pubkey) == true check csig.verify(message, pubkey) == true
var error = csig.getBytes() var error = csig.getBytes()
error[^1] = not error[^1] error[^1] = not error[^1]
csig = SkSignature.init(error) csig = SkSignature.init(error).expect("signature")
check csig.verify(message, pubkey) == false check csig.verify(message, pubkey) == false

View File

@ -31,7 +31,7 @@ type
TestProto = ref object of LPProtocol TestProto = ref object of LPProtocol
proc createSwitch(ma: MultiAddress): (Switch, PeerInfo) = proc createSwitch(ma: MultiAddress): (Switch, PeerInfo) =
var peerInfo: PeerInfo = PeerInfo.init(PrivateKey.random(RSA)) var peerInfo: PeerInfo = PeerInfo.init(PrivateKey.random(RSA).tryGet())
peerInfo.addrs.add(ma) peerInfo.addrs.add(ma)
let identify = newIdentify(peerInfo) let identify = newIdentify(peerInfo)

View File

@ -263,7 +263,7 @@ suite "Variable integer test suite":
buffer.setLen(PBedgeSizes[i]) buffer.setLen(PBedgeSizes[i])
check: check:
PB.putUVarint(buffer, length, PBedgeValues[i]) == VarintStatus.Success PB.putUVarint(buffer, length, PBedgeValues[i]) == VarintStatus.Success
buffer.setLen(len(buffer) - 1) buffer.setlen(buffer.high)
check: check:
PB.getUVarint(buffer, length, value) == VarintStatus.Incomplete PB.getUVarint(buffer, length, value) == VarintStatus.Incomplete
@ -339,7 +339,7 @@ suite "Variable integer test suite":
buffer.setLen(LPedgeSizes[i]) buffer.setLen(LPedgeSizes[i])
check: check:
LP.putUVarint(buffer, length, LPedgeValues[i]) == VarintStatus.Success LP.putUVarint(buffer, length, LPedgeValues[i]) == VarintStatus.Success
buffer.setLen(len(buffer) - 1) buffer.setlen(buffer.high)
check: check:
LP.getUVarint(buffer, length, value) == VarintStatus.Incomplete LP.getUVarint(buffer, length, value) == VarintStatus.Incomplete