## 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. import secp256k1 as s, stew/byteutils, nimcrypto/hash, nimcrypto/sha2 export sha2 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 SkPublicKey* = distinct s.SkPublicKey SkPrivateKey* = distinct s.SkSecretKey SkKeyPair* = distinct s.SkKeyPair SkSignature* = distinct s.SkSignature Secp256k1Error* = object of CatchableError ## Exceptions generated by `libsecp256k1` template toException(v: cstring): (ref Secp256k1Error) = (ref Secp256k1Error)(msg: $v) template pubkey*(v: SkKeyPair): SkPublicKey = SkPublicKey(s.SkKeyPair(v).pubkey) template seckey*(v: SkKeyPair): SkPrivateKey = SkPrivateKey(s.SkKeyPair(v).seckey) proc init*(key: var SkPrivateKey, data: openarray[byte]): bool {.raises: [Defect].} = ## Initialize Secp256k1 `private key` ``key`` from raw binary ## representation ``data``. ## ## Procedure returns ``true`` on success. if (let v = SkSecretKey.fromRaw(data); v.isOk): key = SkPrivateKey(v[]) return true proc init*(key: var SkPrivateKey, data: string): bool {.raises: [Defect].} = ## Initialize Secp256k1 `private key` ``key`` from hexadecimal string ## representation ``data``. ## ## Procedure returns ``true`` on success. try: key = SkPrivateKey(SkSecretKey.fromHex(data).tryGet()) return true except Secp256k1Error: discard proc init*(key: var SkPublicKey, data: openarray[byte]): bool {.raises: [Defect].} = ## Initialize Secp256k1 `public key` ``key`` from raw binary ## representation ``data``. ## ## Procedure returns ``true`` on success. try: key = SkPublicKey(s.SkPublicKey.fromRaw(data).tryGet()) return true except Secp256k1Error: discard proc init*(key: var SkPublicKey, data: string): bool {.raises: [Defect].} = ## Initialize Secp256k1 `public key` ``key`` from hexadecimal string ## representation ``data``. ## ## Procedure returns ``true`` on success. try: key = SkPublicKey(s.SkPublicKey.fromHex(data).tryGet()) return true except Secp256k1Error: discard proc init*(sig: var SkSignature, data: openarray[byte]): bool {.raises: [Defect].} = ## Initialize Secp256k1 `signature` ``sig`` from raw binary ## representation ``data``. ## ## Procedure returns ``true`` on success. try: sig = SkSignature(s.SkSignature.fromDer(data).tryGet()) return true except Secp256k1Error: discard proc init*(sig: var SkSignature, data: string): bool {.raises: [Defect].} = ## Initialize Secp256k1 `signature` ``sig`` from hexadecimal string ## representation ``data``. ## ## Procedure returns ``true`` on success. # TODO DER vs raw here is fishy var buffer: seq[byte] try: buffer = hexToSeqByte(data) except ValueError: return false result = init(sig, buffer) proc init*(t: typedesc[SkPrivateKey], data: openarray[byte]): SkPrivateKey {.raises: [Defect, Secp256k1Error].} = ## Initialize Secp256k1 `private key` from raw binary ## representation ``data``. ## ## Procedure returns `private key` on success. SkPrivateKey(s.SkSecretKey.fromRaw(data).tryGet()) proc init*(t: typedesc[SkPrivateKey], data: string): SkPrivateKey {.raises: [Defect, Secp256k1Error].} = ## Initialize Secp256k1 `private key` from hexadecimal string ## representation ``data``. ## ## Procedure returns `private key` on success. s.SkSecretKey.fromHex(data).tryGet() proc init*(t: typedesc[SkPublicKey], data: openarray[byte]): SkPublicKey {.raises: [Defect, Secp256k1Error].} = ## Initialize Secp256k1 `public key` from raw binary ## representation ``data``. ## ## Procedure returns `public key` on success. if not init(result, data): raise newException(Secp256k1Error, "Incorrect binary form") proc init*(t: typedesc[SkPublicKey], data: string): SkPublicKey {.raises: [Defect, Secp256k1Error].} = ## Initialize Secp256k1 `public key` from hexadecimal string ## representation ``data``. ## ## Procedure returns `public key` on success. if not init(result, data): raise newException(Secp256k1Error, "Incorrect binary form") proc init*(t: typedesc[SkSignature], data: openarray[byte]): SkSignature {.raises: [Defect, Secp256k1Error].} = ## Initialize Secp256k1 `signature` from raw binary ## representation ``data``. ## ## Procedure returns `signature` on success. if not init(result, data): raise newException(Secp256k1Error, "Incorrect binary form") proc init*(t: typedesc[SkSignature], data: string): SkSignature {.raises: [Defect, Secp256k1Error].} = ## Initialize Secp256k1 `signature` from hexadecimal string ## representation ``data``. ## ## Procedure returns `signature` on success. if not init(result, data): raise newException(Secp256k1Error, "Incorrect binary form") proc getKey*(key: SkPrivateKey): SkPublicKey {.raises: [Defect, Secp256k1Error].} = ## Calculate and return Secp256k1 `public key` from `private key` ``key``. SkPublicKey(s.SkSecretKey(key).toPublicKey().tryGet()) proc random*(t: typedesc[SkPrivateKey]): SkPrivateKey = ## Generates new random private key. SkPrivateKey(s.SkSecretKey.random().tryGet()) proc random*(t: typedesc[SkKeyPair]): SkKeyPair {.inline.} = ## Generates new random key pair. SkKeyPair(s.SkKeyPair.random().tryGet()) proc toBytes*(key: SkPrivateKey, data: var openarray[byte]): int = ## Serialize Secp256k1 `private key` ``key`` to raw binary form and store it ## to ``data``. ## ## Procedure returns number of bytes (octets) needed to store ## Secp256k1 private key. result = SkRawPrivateKeySize if len(data) >= SkRawPrivateKeySize: data[0..= SkRawPublicKeySize: data[0..