2019-09-02 18:55:42 +00:00
|
|
|
## Nim-Libp2p
|
|
|
|
## Copyright (c) 2018 Status Research & Development GmbH
|
|
|
|
## Licensed under either of
|
|
|
|
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
|
|
|
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
|
|
|
## at your option.
|
|
|
|
## This file may not be copied, modified, or distributed except according to
|
|
|
|
## those terms.
|
2020-05-18 05:25:55 +00:00
|
|
|
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
|
|
|
|
import secp256k1, stew/byteutils, nimcrypto/hash, nimcrypto/sha2
|
2019-09-02 18:55:42 +00:00
|
|
|
export sha2
|
2020-05-18 05:25:55 +00:00
|
|
|
import stew/results
|
|
|
|
|
|
|
|
export results
|
|
|
|
export secp256k1
|
2019-09-02 18:55:42 +00:00
|
|
|
|
|
|
|
const
|
|
|
|
SkRawPrivateKeySize* = 256 div 8
|
|
|
|
## Size of private key in octets (bytes)
|
|
|
|
SkRawSignatureSize* = SkRawPrivateKeySize * 2 + 1
|
|
|
|
## Size of signature in octets (bytes)
|
|
|
|
SkRawPublicKeySize* = SkRawPrivateKeySize + 1
|
|
|
|
## Size of public key in octets (bytes)
|
|
|
|
|
|
|
|
type
|
2020-05-18 05:25:55 +00:00
|
|
|
SkPrivateKey* = SkSecretKey
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
template pubkey*(v: SkKeyPair): SkPublicKey = SkPublicKey(SkKeyPair(v).pubkey)
|
|
|
|
template seckey*(v: SkKeyPair): SkPrivateKey = SkPrivateKey(SkKeyPair(v).seckey)
|
2020-04-17 10:51:13 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc init*(key: var SkPrivateKey, data: openarray[byte]): SkResult[void] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Initialize Secp256k1 `private key` ``key`` from raw binary
|
|
|
|
## representation ``data``.
|
2020-05-18 05:25:55 +00:00
|
|
|
key = ? SkSecretKey.fromRaw(data)
|
|
|
|
ok()
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc init*(key: var SkPrivateKey, data: string): SkResult[void] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Initialize Secp256k1 `private key` ``key`` from hexadecimal string
|
|
|
|
## representation ``data``.
|
2020-05-18 05:25:55 +00:00
|
|
|
key = ? SkSecretKey.fromHex(data)
|
|
|
|
ok()
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc init*(key: var SkPublicKey, data: openarray[byte]): SkResult[void] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Initialize Secp256k1 `public key` ``key`` from raw binary
|
|
|
|
## representation ``data``.
|
2020-05-18 05:25:55 +00:00
|
|
|
key = ? SkPublicKey.fromRaw(data)
|
|
|
|
ok()
|
2020-04-17 10:51:13 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc init*(key: var SkPublicKey, data: string): SkResult[void] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Initialize Secp256k1 `public key` ``key`` from hexadecimal string
|
|
|
|
## representation ``data``.
|
2020-05-18 05:25:55 +00:00
|
|
|
key = ? SkPublicKey.fromHex(data)
|
|
|
|
ok()
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc init*(sig: var SkSignature, data: openarray[byte]): SkResult[void] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Initialize Secp256k1 `signature` ``sig`` from raw binary
|
|
|
|
## representation ``data``.
|
2020-05-18 05:25:55 +00:00
|
|
|
sig = ? SkSignature.fromDer(data)
|
|
|
|
ok()
|
2020-04-17 10:51:13 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc init*(sig: var SkSignature, data: string): SkResult[void] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Initialize Secp256k1 `signature` ``sig`` from hexadecimal string
|
|
|
|
## representation ``data``.
|
2020-04-17 10:51:13 +00:00
|
|
|
# TODO DER vs raw here is fishy
|
2019-09-02 18:55:42 +00:00
|
|
|
var buffer: seq[byte]
|
|
|
|
try:
|
2020-04-17 10:51:13 +00:00
|
|
|
buffer = hexToSeqByte(data)
|
|
|
|
except ValueError:
|
2020-05-18 05:25:55 +00:00
|
|
|
return err("Hex to bytes failed")
|
|
|
|
init(sig, buffer)
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc init*(t: typedesc[SkPrivateKey], data: openarray[byte]): SkResult[SkPrivateKey] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Initialize Secp256k1 `private key` from raw binary
|
|
|
|
## representation ``data``.
|
|
|
|
##
|
|
|
|
## Procedure returns `private key` on success.
|
2020-05-18 05:25:55 +00:00
|
|
|
SkSecretKey.fromRaw(data)
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc init*(t: typedesc[SkPrivateKey], data: string): SkResult[SkPrivateKey] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Initialize Secp256k1 `private key` from hexadecimal string
|
|
|
|
## representation ``data``.
|
|
|
|
##
|
|
|
|
## Procedure returns `private key` on success.
|
2020-05-18 05:25:55 +00:00
|
|
|
SkSecretKey.fromHex(data)
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc init*(t: typedesc[SkPublicKey], data: openarray[byte]): SkResult[SkPublicKey] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Initialize Secp256k1 `public key` from raw binary
|
|
|
|
## representation ``data``.
|
|
|
|
##
|
|
|
|
## Procedure returns `public key` on success.
|
2020-05-18 05:25:55 +00:00
|
|
|
var key: SkPublicKey
|
|
|
|
key.init(data) and ok(key)
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc init*(t: typedesc[SkPublicKey], data: string): SkResult[SkPublicKey] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Initialize Secp256k1 `public key` from hexadecimal string
|
|
|
|
## representation ``data``.
|
|
|
|
##
|
|
|
|
## Procedure returns `public key` on success.
|
2020-05-18 05:25:55 +00:00
|
|
|
var key: SkPublicKey
|
|
|
|
key.init(data) and ok(key)
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc init*(t: typedesc[SkSignature], data: openarray[byte]): SkResult[SkSignature] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Initialize Secp256k1 `signature` from raw binary
|
|
|
|
## representation ``data``.
|
|
|
|
##
|
|
|
|
## Procedure returns `signature` on success.
|
2020-05-18 05:25:55 +00:00
|
|
|
var sig: SkSignature
|
|
|
|
sig.init(data) and ok(sig)
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc init*(t: typedesc[SkSignature], data: string): SkResult[SkSignature] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Initialize Secp256k1 `signature` from hexadecimal string
|
|
|
|
## representation ``data``.
|
|
|
|
##
|
|
|
|
## Procedure returns `signature` on success.
|
2020-05-18 05:25:55 +00:00
|
|
|
var sig: SkSignature
|
|
|
|
sig.init(data) and ok(sig)
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc getKey*(key: SkPrivateKey): SkResult[SkPublicKey] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Calculate and return Secp256k1 `public key` from `private key` ``key``.
|
2020-05-18 05:25:55 +00:00
|
|
|
key.toPublicKey()
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc toBytes*(key: SkPrivateKey, data: var openarray[byte]): SkResult[int] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Serialize Secp256k1 `private key` ``key`` to raw binary form and store it
|
|
|
|
## to ``data``.
|
|
|
|
##
|
|
|
|
## Procedure returns number of bytes (octets) needed to store
|
|
|
|
## Secp256k1 private key.
|
|
|
|
if len(data) >= SkRawPrivateKeySize:
|
2020-05-18 05:25:55 +00:00
|
|
|
data[0..<SkRawPrivateKeySize] = SkSecretKey(key).toRaw()
|
|
|
|
ok(SkRawPrivateKeySize)
|
|
|
|
else:
|
|
|
|
err("Not enough bytes")
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc toBytes*(key: SkPublicKey, data: var openarray[byte]): SkResult[int] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Serialize Secp256k1 `public key` ``key`` to raw binary form and store it
|
|
|
|
## to ``data``.
|
|
|
|
##
|
|
|
|
## Procedure returns number of bytes (octets) needed to store
|
|
|
|
## Secp256k1 public key.
|
|
|
|
if len(data) >= SkRawPublicKeySize:
|
2020-05-18 05:25:55 +00:00
|
|
|
data[0..<SkRawPublicKeySize] = key.toRawCompressed()
|
|
|
|
ok(SkRawPublicKeySize)
|
|
|
|
else:
|
|
|
|
err("Not enough bytes")
|
2019-09-02 18:55:42 +00:00
|
|
|
|
|
|
|
proc toBytes*(sig: SkSignature, data: var openarray[byte]): int =
|
|
|
|
## Serialize Secp256k1 `signature` ``sig`` to raw binary form and store it
|
|
|
|
## to ``data``.
|
|
|
|
##
|
|
|
|
## Procedure returns number of bytes (octets) needed to store
|
|
|
|
## Secp256k1 signature.
|
2020-05-18 05:25:55 +00:00
|
|
|
sig.toDer(data)
|
2019-09-02 18:55:42 +00:00
|
|
|
|
|
|
|
proc getBytes*(key: SkPrivateKey): seq[byte] {.inline.} =
|
|
|
|
## Serialize Secp256k1 `private key` and return it.
|
2020-05-18 05:25:55 +00:00
|
|
|
result = @(SkSecretKey(key).toRaw())
|
2019-09-02 18:55:42 +00:00
|
|
|
|
|
|
|
proc getBytes*(key: SkPublicKey): seq[byte] {.inline.} =
|
|
|
|
## Serialize Secp256k1 `public key` and return it.
|
2020-05-18 05:25:55 +00:00
|
|
|
result = @(key.toRawCompressed())
|
2019-09-02 18:55:42 +00:00
|
|
|
|
|
|
|
proc getBytes*(sig: SkSignature): seq[byte] {.inline.} =
|
|
|
|
## Serialize Secp256k1 `signature` and return it.
|
2020-01-09 08:33:57 +00:00
|
|
|
result = newSeq[byte](72)
|
|
|
|
let length = toBytes(sig, result)
|
|
|
|
result.setLen(length)
|
2019-09-02 18:55:42 +00:00
|
|
|
|
2020-05-18 05:25:55 +00:00
|
|
|
proc sign*[T: byte|char](key: SkPrivateKey, msg: openarray[T]): SkResult[SkSignature] =
|
2019-09-02 18:55:42 +00:00
|
|
|
## Sign message `msg` using private key `key` and return signature object.
|
2020-04-17 10:51:13 +00:00
|
|
|
let h = sha256.digest(msg)
|
2020-05-18 05:25:55 +00:00
|
|
|
sign(key, h)
|
2019-09-02 18:55:42 +00:00
|
|
|
|
|
|
|
proc verify*[T: byte|char](sig: SkSignature, msg: openarray[T],
|
|
|
|
key: SkPublicKey): bool =
|
2020-04-17 10:51:13 +00:00
|
|
|
let h = sha256.digest(msg)
|
2020-05-18 05:25:55 +00:00
|
|
|
verify(SkSignature(sig), h, SkPublicKey(key))
|