mirror of
https://github.com/logos-storage/nim-libp2p.git
synced 2026-01-05 23:23:12 +00:00
secp: use upstream secp convenience api (#141)
* secp: use upstream secp convenience api
This commit is contained in:
parent
4d1fc9dacd
commit
e8b33c64fa
@ -8,7 +8,6 @@ license = "MIT"
|
|||||||
skipDirs = @["tests", "examples", "Nim"]
|
skipDirs = @["tests", "examples", "Nim"]
|
||||||
|
|
||||||
requires "nim >= 1.2.0",
|
requires "nim >= 1.2.0",
|
||||||
"secp256k1",
|
|
||||||
"nimcrypto >= 0.4.1",
|
"nimcrypto >= 0.4.1",
|
||||||
"chronos >= 2.3.8",
|
"chronos >= 2.3.8",
|
||||||
"bearssl >= 0.1.4",
|
"bearssl >= 0.1.4",
|
||||||
|
|||||||
@ -6,8 +6,7 @@
|
|||||||
## 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, nimcrypto/sysrand, nimcrypto/utils, nimcrypto/hash,
|
import secp256k1 as s, stew/byteutils, nimcrypto/hash, nimcrypto/sha2
|
||||||
nimcrypto/sha2
|
|
||||||
export sha2
|
export sha2
|
||||||
|
|
||||||
const
|
const
|
||||||
@ -19,177 +18,104 @@ const
|
|||||||
## Size of public key in octets (bytes)
|
## Size of public key in octets (bytes)
|
||||||
|
|
||||||
type
|
type
|
||||||
SkPublicKey* = secp256k1_pubkey
|
SkPublicKey* = distinct s.SkPublicKey
|
||||||
## Representation of public key.
|
SkPrivateKey* = distinct s.SkSecretKey
|
||||||
|
SkKeyPair* = distinct s.SkKeyPair
|
||||||
SkPrivateKey* = object
|
SkSignature* = distinct s.SkSignature
|
||||||
## Representation of secret key.
|
|
||||||
data*: array[SkRawPrivateKeySize, byte]
|
|
||||||
|
|
||||||
SkKeyPair* = object
|
|
||||||
## Representation of private/public keys pair.
|
|
||||||
seckey*: SkPrivateKey
|
|
||||||
pubkey*: SkPublicKey
|
|
||||||
|
|
||||||
SkSignature* = secp256k1_ecdsa_signature
|
|
||||||
## Representation of signature.
|
|
||||||
|
|
||||||
SkContext* = ref object
|
|
||||||
## Representation of Secp256k1 context object.
|
|
||||||
context: ptr secp256k1_context
|
|
||||||
error: string
|
|
||||||
|
|
||||||
Secp256k1Error* = object of CatchableError
|
Secp256k1Error* = object of CatchableError
|
||||||
## Exceptions generated by `libsecp256k1`
|
## Exceptions generated by `libsecp256k1`
|
||||||
|
|
||||||
##
|
template toException(v: cstring): (ref Secp256k1Error) =
|
||||||
## Private procedures interface
|
(ref Secp256k1Error)(msg: $v)
|
||||||
##
|
|
||||||
|
|
||||||
var secpContext {.threadvar.}: SkContext
|
template pubkey*(v: SkKeyPair): SkPublicKey = SkPublicKey(s.SkKeyPair(v).pubkey)
|
||||||
## Thread local variable which holds current context
|
template seckey*(v: SkKeyPair): SkPrivateKey = SkPrivateKey(s.SkKeyPair(v).seckey)
|
||||||
|
|
||||||
proc illegalCallback(message: cstring, data: pointer) {.cdecl, raises: [].} =
|
proc init*(key: var SkPrivateKey, data: openarray[byte]): bool {.raises: [Defect].} =
|
||||||
let ctx = cast[SkContext](data)
|
|
||||||
ctx.error = $message
|
|
||||||
|
|
||||||
proc errorCallback(message: cstring, data: pointer) {.cdecl, raises: [].} =
|
|
||||||
let ctx = cast[SkContext](data)
|
|
||||||
ctx.error = $message
|
|
||||||
|
|
||||||
proc shutdownLibsecp256k1(ctx: SkContext) =
|
|
||||||
# TODO: use destructor when finalizer are deprecated for destructors
|
|
||||||
if not(isNil(ctx.context)):
|
|
||||||
secp256k1_context_destroy(ctx.context)
|
|
||||||
|
|
||||||
proc newSkContext(): SkContext =
|
|
||||||
## Create new Secp256k1 context object.
|
|
||||||
new(result, shutdownLibsecp256k1)
|
|
||||||
let flags = cuint(SECP256K1_CONTEXT_VERIFY or SECP256K1_CONTEXT_SIGN)
|
|
||||||
result.context = secp256k1_context_create(flags)
|
|
||||||
secp256k1_context_set_illegal_callback(result.context, illegalCallback,
|
|
||||||
cast[pointer](result))
|
|
||||||
secp256k1_context_set_error_callback(result.context, errorCallback,
|
|
||||||
cast[pointer](result))
|
|
||||||
result.error = ""
|
|
||||||
|
|
||||||
proc getContext(): SkContext =
|
|
||||||
## Get current `EccContext`
|
|
||||||
if isNil(secpContext):
|
|
||||||
secpContext = newSkContext()
|
|
||||||
result = secpContext
|
|
||||||
|
|
||||||
template raiseSecp256k1Error() =
|
|
||||||
## Raises `libsecp256k1` error as exception
|
|
||||||
let mctx = getContext()
|
|
||||||
if len(mctx.error) > 0:
|
|
||||||
let msg = mctx.error
|
|
||||||
mctx.error.setLen(0)
|
|
||||||
raise newException(Secp256k1Error, msg)
|
|
||||||
else:
|
|
||||||
raise newException(Secp256k1Error, "")
|
|
||||||
|
|
||||||
proc init*(key: var SkPrivateKey, data: openarray[byte]): bool =
|
|
||||||
## Initialize Secp256k1 `private key` ``key`` from raw binary
|
## Initialize Secp256k1 `private key` ``key`` from raw binary
|
||||||
## representation ``data``.
|
## representation ``data``.
|
||||||
##
|
##
|
||||||
## Procedure returns ``true`` on success.
|
## Procedure returns ``true`` on success.
|
||||||
let ctx = getContext()
|
if (let v = SkSecretKey.fromRaw(data); v.isOk):
|
||||||
if len(data) >= SkRawPrivateKeySize:
|
key = SkPrivateKey(v[])
|
||||||
let res = secp256k1_ec_seckey_verify(ctx.context,
|
return true
|
||||||
cast[ptr cuchar](unsafeAddr data[0]))
|
|
||||||
result = (res == 1) and (len(ctx.error) == 0)
|
|
||||||
if result:
|
|
||||||
copyMem(addr key.data[0], unsafeAddr data[0], SkRawPrivateKeySize)
|
|
||||||
|
|
||||||
proc init*(key: var SkPrivateKey, data: string): bool {.inline.} =
|
proc init*(key: var SkPrivateKey, data: string): bool {.raises: [Defect].} =
|
||||||
## Initialize Secp256k1 `private key` ``key`` from hexadecimal string
|
## Initialize Secp256k1 `private key` ``key`` from hexadecimal string
|
||||||
## representation ``data``.
|
## representation ``data``.
|
||||||
##
|
##
|
||||||
## Procedure returns ``true`` on success.
|
## Procedure returns ``true`` on success.
|
||||||
var buffer: seq[byte]
|
|
||||||
try:
|
try:
|
||||||
buffer = utils.fromHex(stripSpaces(data))
|
key = SkPrivateKey(SkSecretKey.fromHex(data).tryGet())
|
||||||
except:
|
return true
|
||||||
return false
|
except Secp256k1Error:
|
||||||
result = init(key, buffer)
|
discard
|
||||||
|
|
||||||
proc init*(key: var SkPublicKey, data: openarray[byte]): bool =
|
proc init*(key: var SkPublicKey, data: openarray[byte]): bool {.raises: [Defect].} =
|
||||||
## Initialize Secp256k1 `public key` ``key`` from raw binary
|
## Initialize Secp256k1 `public key` ``key`` from raw binary
|
||||||
## representation ``data``.
|
## representation ``data``.
|
||||||
##
|
##
|
||||||
## Procedure returns ``true`` on success.
|
## Procedure returns ``true`` on success.
|
||||||
let ctx = getContext()
|
try:
|
||||||
var length = 0
|
key = SkPublicKey(s.SkPublicKey.fromRaw(data).tryGet())
|
||||||
if len(data) > 0:
|
return true
|
||||||
if data[0] == 0x02'u8 or data[0] == 0x03'u8:
|
except Secp256k1Error:
|
||||||
length = min(len(data), 33)
|
discard
|
||||||
elif data[0] == 0x04'u8 or data[0] == 0x06'u8 or data[0] == 0x07'u8:
|
|
||||||
length = min(len(data), 65)
|
|
||||||
else:
|
|
||||||
return false
|
|
||||||
let res = secp256k1_ec_pubkey_parse(ctx.context, addr key,
|
|
||||||
cast[ptr cuchar](unsafeAddr data[0]),
|
|
||||||
csize_t(length))
|
|
||||||
result = (res == 1) and (len(ctx.error) == 0)
|
|
||||||
|
|
||||||
proc init*(key: var SkPublicKey, data: string): bool =
|
proc init*(key: var SkPublicKey, data: string): bool {.raises: [Defect].} =
|
||||||
## Initialize Secp256k1 `public key` ``key`` from hexadecimal string
|
## Initialize Secp256k1 `public key` ``key`` from hexadecimal string
|
||||||
## representation ``data``.
|
## representation ``data``.
|
||||||
##
|
##
|
||||||
## Procedure returns ``true`` on success.
|
## Procedure returns ``true`` on success.
|
||||||
var buffer: seq[byte]
|
|
||||||
try:
|
try:
|
||||||
buffer = utils.fromHex(stripSpaces(data))
|
key = SkPublicKey(s.SkPublicKey.fromHex(data).tryGet())
|
||||||
except:
|
return true
|
||||||
return false
|
except Secp256k1Error:
|
||||||
result = init(key, buffer)
|
discard
|
||||||
|
|
||||||
proc init*(sig: var SkSignature, data: openarray[byte]): bool =
|
proc init*(sig: var SkSignature, data: openarray[byte]): bool {.raises: [Defect].} =
|
||||||
## Initialize Secp256k1 `signature` ``sig`` from raw binary
|
## Initialize Secp256k1 `signature` ``sig`` from raw binary
|
||||||
## representation ``data``.
|
## representation ``data``.
|
||||||
##
|
##
|
||||||
## Procedure returns ``true`` on success.
|
## Procedure returns ``true`` on success.
|
||||||
let ctx = getContext()
|
try:
|
||||||
let length = len(data)
|
sig = SkSignature(s.SkSignature.fromDer(data).tryGet())
|
||||||
if length >= 0:
|
return true
|
||||||
let res = secp256k1_ecdsa_signature_parse_der(ctx.context, addr sig,
|
except Secp256k1Error:
|
||||||
cast[ptr cuchar](unsafeAddr data[0]),
|
discard
|
||||||
csize_t(length))
|
|
||||||
result = (res == 1) and (len(ctx.error) == 0)
|
|
||||||
|
|
||||||
proc init*(sig: var SkSignature, data: string): bool =
|
proc init*(sig: var SkSignature, data: string): bool {.raises: [Defect].} =
|
||||||
## Initialize Secp256k1 `signature` ``sig`` from hexadecimal string
|
## Initialize Secp256k1 `signature` ``sig`` from hexadecimal string
|
||||||
## representation ``data``.
|
## representation ``data``.
|
||||||
##
|
##
|
||||||
## Procedure returns ``true`` on success.
|
## Procedure returns ``true`` on success.
|
||||||
|
# TODO DER vs raw here is fishy
|
||||||
var buffer: seq[byte]
|
var buffer: seq[byte]
|
||||||
try:
|
try:
|
||||||
buffer = utils.fromHex(stripSpaces(data))
|
buffer = hexToSeqByte(data)
|
||||||
except:
|
except ValueError:
|
||||||
return false
|
return false
|
||||||
result = init(sig, buffer)
|
result = init(sig, buffer)
|
||||||
|
|
||||||
proc init*(t: typedesc[SkPrivateKey],
|
proc init*(t: typedesc[SkPrivateKey],
|
||||||
data: openarray[byte]): SkPrivateKey {.inline.} =
|
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.
|
||||||
if not init(result, data):
|
SkPrivateKey(s.SkSecretKey.fromRaw(data).tryGet())
|
||||||
raise newException(Secp256k1Error, "Incorrect binary form")
|
|
||||||
|
|
||||||
proc init*(t: typedesc[SkPrivateKey],
|
proc init*(t: typedesc[SkPrivateKey],
|
||||||
data: string): SkPrivateKey {.inline.} =
|
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.
|
||||||
if not init(result, data):
|
s.SkSecretKey.fromHex(data).tryGet()
|
||||||
raise newException(Secp256k1Error, "Incorrect binary form")
|
|
||||||
|
|
||||||
proc init*(t: typedesc[SkPublicKey],
|
proc init*(t: typedesc[SkPublicKey],
|
||||||
data: openarray[byte]): SkPublicKey {.inline.} =
|
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``.
|
||||||
##
|
##
|
||||||
@ -198,7 +124,7 @@ proc init*(t: typedesc[SkPublicKey],
|
|||||||
raise newException(Secp256k1Error, "Incorrect binary form")
|
raise newException(Secp256k1Error, "Incorrect binary form")
|
||||||
|
|
||||||
proc init*(t: typedesc[SkPublicKey],
|
proc init*(t: typedesc[SkPublicKey],
|
||||||
data: string): SkPublicKey {.inline.} =
|
data: string): SkPublicKey {.raises: [Defect, Secp256k1Error].} =
|
||||||
## Initialize Secp256k1 `public key` from hexadecimal string
|
## Initialize Secp256k1 `public key` from hexadecimal string
|
||||||
## representation ``data``.
|
## representation ``data``.
|
||||||
##
|
##
|
||||||
@ -207,7 +133,7 @@ proc init*(t: typedesc[SkPublicKey],
|
|||||||
raise newException(Secp256k1Error, "Incorrect binary form")
|
raise newException(Secp256k1Error, "Incorrect binary form")
|
||||||
|
|
||||||
proc init*(t: typedesc[SkSignature],
|
proc init*(t: typedesc[SkSignature],
|
||||||
data: openarray[byte]): SkSignature {.inline.} =
|
data: openarray[byte]): SkSignature {.raises: [Defect, Secp256k1Error].} =
|
||||||
## Initialize Secp256k1 `signature` from raw binary
|
## Initialize Secp256k1 `signature` from raw binary
|
||||||
## representation ``data``.
|
## representation ``data``.
|
||||||
##
|
##
|
||||||
@ -216,7 +142,7 @@ proc init*(t: typedesc[SkSignature],
|
|||||||
raise newException(Secp256k1Error, "Incorrect binary form")
|
raise newException(Secp256k1Error, "Incorrect binary form")
|
||||||
|
|
||||||
proc init*(t: typedesc[SkSignature],
|
proc init*(t: typedesc[SkSignature],
|
||||||
data: string): SkSignature {.inline.} =
|
data: string): SkSignature {.raises: [Defect, Secp256k1Error].} =
|
||||||
## Initialize Secp256k1 `signature` from hexadecimal string
|
## Initialize Secp256k1 `signature` from hexadecimal string
|
||||||
## representation ``data``.
|
## representation ``data``.
|
||||||
##
|
##
|
||||||
@ -224,28 +150,17 @@ proc init*(t: typedesc[SkSignature],
|
|||||||
if not init(result, data):
|
if not init(result, data):
|
||||||
raise newException(Secp256k1Error, "Incorrect binary form")
|
raise newException(Secp256k1Error, "Incorrect binary form")
|
||||||
|
|
||||||
proc getKey*(key: SkPrivateKey): SkPublicKey =
|
proc getKey*(key: SkPrivateKey): SkPublicKey {.raises: [Defect, Secp256k1Error].} =
|
||||||
## Calculate and return Secp256k1 `public key` from `private key` ``key``.
|
## Calculate and return Secp256k1 `public key` from `private key` ``key``.
|
||||||
let ctx = getContext()
|
SkPublicKey(s.SkSecretKey(key).toPublicKey().tryGet())
|
||||||
let res = secp256k1_ec_pubkey_create(ctx.context, addr result,
|
|
||||||
cast[ptr cuchar](unsafeAddr key))
|
|
||||||
if (res != 1) or (len(ctx.error) != 0):
|
|
||||||
raiseSecp256k1Error()
|
|
||||||
|
|
||||||
proc random*(t: typedesc[SkPrivateKey]): SkPrivateKey =
|
proc random*(t: typedesc[SkPrivateKey]): SkPrivateKey =
|
||||||
## Generates new random private key.
|
## Generates new random private key.
|
||||||
let ctx = getContext()
|
SkPrivateKey(s.SkSecretKey.random().tryGet())
|
||||||
while true:
|
|
||||||
if randomBytes(result.data) == SkRawPrivateKeySize:
|
|
||||||
let res = secp256k1_ec_seckey_verify(ctx.context,
|
|
||||||
cast[ptr cuchar](addr result.data[0]))
|
|
||||||
if (res == 1) and (len(ctx.error) == 0):
|
|
||||||
break
|
|
||||||
|
|
||||||
proc random*(t: typedesc[SkKeyPair]): SkKeyPair {.inline.} =
|
proc random*(t: typedesc[SkKeyPair]): SkKeyPair {.inline.} =
|
||||||
## Generates new random key pair.
|
## Generates new random key pair.
|
||||||
result.seckey = SkPrivateKey.random()
|
SkKeyPair(s.SkKeyPair.random().tryGet())
|
||||||
result.pubkey = result.seckey.getKey()
|
|
||||||
|
|
||||||
proc toBytes*(key: SkPrivateKey, data: var openarray[byte]): int =
|
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
|
||||||
@ -255,7 +170,7 @@ proc toBytes*(key: SkPrivateKey, data: var openarray[byte]): int =
|
|||||||
## Secp256k1 private key.
|
## Secp256k1 private key.
|
||||||
result = SkRawPrivateKeySize
|
result = SkRawPrivateKeySize
|
||||||
if len(data) >= SkRawPrivateKeySize:
|
if len(data) >= SkRawPrivateKeySize:
|
||||||
copyMem(addr data[0], unsafeAddr key.data[0], SkRawPrivateKeySize)
|
data[0..<SkRawPrivateKeySize] = s.SkSecretKey(key).toRaw()
|
||||||
|
|
||||||
proc toBytes*(key: SkPublicKey, data: var openarray[byte]): int =
|
proc toBytes*(key: SkPublicKey, data: var openarray[byte]): 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
|
||||||
@ -263,14 +178,9 @@ proc toBytes*(key: SkPublicKey, data: var openarray[byte]): int =
|
|||||||
##
|
##
|
||||||
## Procedure returns number of bytes (octets) needed to store
|
## Procedure returns number of bytes (octets) needed to store
|
||||||
## Secp256k1 public key.
|
## Secp256k1 public key.
|
||||||
let ctx = getContext()
|
|
||||||
var length = csize_t(len(data))
|
|
||||||
result = SkRawPublicKeySize
|
result = SkRawPublicKeySize
|
||||||
if len(data) >= SkRawPublicKeySize:
|
if len(data) >= SkRawPublicKeySize:
|
||||||
discard secp256k1_ec_pubkey_serialize(ctx.context,
|
data[0..<SkRawPublicKeySize] = s.SkPublicKey(key).toRawCompressed()
|
||||||
cast[ptr cuchar](addr data[0]),
|
|
||||||
addr length, unsafeAddr key,
|
|
||||||
SECP256K1_EC_COMPRESSED)
|
|
||||||
|
|
||||||
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
|
||||||
@ -278,25 +188,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.
|
||||||
let ctx = getContext()
|
s.SkSignature(sig).toDer(data)
|
||||||
var buffer: array[72, byte]
|
|
||||||
let pdata = cast[ptr cuchar](addr buffer[0])
|
|
||||||
var plength = csize_t(len(buffer))
|
|
||||||
discard secp256k1_ecdsa_signature_serialize_der(ctx.context, pdata,
|
|
||||||
addr plength,
|
|
||||||
unsafeAddr sig)
|
|
||||||
result = int(plength)
|
|
||||||
if len(data) >= result:
|
|
||||||
copyMem(addr data[0], addr buffer[0], result)
|
|
||||||
|
|
||||||
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 = @(key.data)
|
result = @(s.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 = newSeq[byte](SkRawPublicKeySize)
|
result = @(s.SkPublicKey(key).toRawCompressed())
|
||||||
discard toBytes(key, result)
|
|
||||||
|
|
||||||
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.
|
||||||
@ -306,74 +206,47 @@ proc getBytes*(sig: SkSignature): seq[byte] {.inline.} =
|
|||||||
|
|
||||||
proc `==`*(ska, skb: SkPrivateKey): bool =
|
proc `==`*(ska, skb: SkPrivateKey): bool =
|
||||||
## Compare Secp256k1 `private key` objects for equality.
|
## Compare Secp256k1 `private key` objects for equality.
|
||||||
result = (ska.data == skb.data)
|
result = (s.SkSecretKey(ska).toRaw == s.SkSecretKey(skb).toRaw)
|
||||||
|
|
||||||
proc `==`*(pka, pkb: SkPublicKey): bool =
|
proc `==`*(pka, pkb: SkPublicKey): bool =
|
||||||
## Compare Secp256k1 `public key` objects for equality.
|
## Compare Secp256k1 `public key` objects for equality.
|
||||||
var
|
result = (s.SkPublicKey(pka).toRaw == s.SkPublicKey(pkb).toRaw)
|
||||||
akey: array[SkRawPublicKeySize, byte]
|
|
||||||
bkey: array[SkRawPublicKeySize, byte]
|
|
||||||
discard pka.toBytes(akey)
|
|
||||||
discard pkb.toBytes(bkey)
|
|
||||||
result = (akey == bkey)
|
|
||||||
|
|
||||||
proc `==`*(sia, sib: SkSignature): bool =
|
proc `==`*(sia, sib: SkSignature): bool =
|
||||||
## Compare Secp256k1 `signature` objects for equality.
|
## Compare Secp256k1 `signature` objects for equality.
|
||||||
var
|
result = (s.SkSignature(sia).toRaw == s.SkSignature(sib).toRaw)
|
||||||
asig: array[SkRawSignatureSize, byte]
|
|
||||||
bsig: array[SkRawSignatureSize, byte]
|
|
||||||
discard sia.toBytes(asig)
|
|
||||||
discard sib.toBytes(bsig)
|
|
||||||
result = (asig == bsig)
|
|
||||||
|
|
||||||
proc `$`*(key: SkPrivateKey): string = toHex(key.data)
|
proc `$`*(key: SkPrivateKey): string = s.SkSecretKey(key).toHex()
|
||||||
## Return string representation of Secp256k1 `private key`.
|
## Return string representation of Secp256k1 `private key`.
|
||||||
|
|
||||||
proc `$`*(key: SkPublicKey): string =
|
proc `$`*(key: SkPublicKey): string =
|
||||||
## Return string representation of Secp256k1 `private key`.s
|
## Return string representation of Secp256k1 `private key`.s
|
||||||
var spub: array[SkRawPublicKeySize, byte]
|
result = toHex(s.SkPublicKey(key).toRawCompressed())
|
||||||
discard key.toBytes(spub)
|
|
||||||
result = toHex(spub)
|
|
||||||
|
|
||||||
proc `$`*(sig: SkSignature): string =
|
proc `$`*(sig: SkSignature): string =
|
||||||
## Return string representation of Secp256k1 `signature`.s
|
## Return string representation of Secp256k1 `signature`.s
|
||||||
result = toHex(sig.data)
|
result = toHex(s.SkSignature(sig).toDer())
|
||||||
|
|
||||||
proc sign*[T: byte|char](key: SkPrivateKey, msg: openarray[T]): SkSignature =
|
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 ctx = getContext()
|
let h = sha256.digest(msg)
|
||||||
var hash = sha256.digest(msg)
|
SkSignature(sign(s.SkSecretKey(key), h).tryGet())
|
||||||
let res = secp256k1_ecdsa_sign(ctx.context, addr result,
|
|
||||||
cast[ptr cuchar](addr hash.data[0]),
|
|
||||||
cast[ptr cuchar](unsafeAddr key),
|
|
||||||
nil, nil)
|
|
||||||
if (res != 1) or (len(ctx.error) != 0):
|
|
||||||
raiseSecp256k1Error()
|
|
||||||
|
|
||||||
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 ctx = getContext()
|
let h = sha256.digest(msg)
|
||||||
var hash = sha256.digest(msg)
|
verify(s.SkSignature(sig), h, s.SkPublicKey(key))
|
||||||
let res = secp256k1_ecdsa_verify(ctx.context, unsafeAddr sig,
|
|
||||||
cast[ptr cuchar](addr hash.data[0]),
|
|
||||||
unsafeAddr key)
|
|
||||||
if (res == 1) and (len(ctx.error) == 0):
|
|
||||||
result = true
|
|
||||||
|
|
||||||
proc clear*(key: var SkPrivateKey) {.inline.} =
|
proc clear*(key: var SkPrivateKey) {.borrow.}
|
||||||
## Wipe and clear memory of Secp256k1 `private key`.
|
## Wipe and clear memory of Secp256k1 `private key`.
|
||||||
burnMem(key.data)
|
|
||||||
|
|
||||||
proc clear*(key: var SkPublicKey) {.inline.} =
|
proc clear*(key: var SkPublicKey) {.borrow.}
|
||||||
## Wipe and clear memory of Secp256k1 `public key`.
|
## Wipe and clear memory of Secp256k1 `public key`.
|
||||||
burnMem(addr key, SkRawPrivateKeySize * 2)
|
|
||||||
|
|
||||||
proc clear*(sig: var SkSignature) {.inline.} =
|
proc clear*(sig: var SkSignature) {.borrow.}
|
||||||
## Wipe and clear memory of Secp256k1 `signature`.
|
## Wipe and clear memory of Secp256k1 `signature`.
|
||||||
# Internal memory representation size of signature object is 64 bytes.
|
# Internal memory representation size of signature object is 64 bytes.
|
||||||
burnMem(addr sig, SkRawPrivateKeySize * 2)
|
|
||||||
|
|
||||||
proc clear*(pair: var SkKeyPair) {.inline.} =
|
proc clear*(pair: var SkKeyPair) {.borrow.}
|
||||||
## Wipe and clear memory of Secp256k1 `key pair`.
|
|
||||||
pair.seckey.clear()
|
proc verify*(seckey: SkPrivateKey): bool {.borrow.}
|
||||||
pair.pubkey.clear()
|
|
||||||
|
|||||||
@ -35,8 +35,8 @@ suite "Secp256k1 testing suite":
|
|||||||
rkey1.clear()
|
rkey1.clear()
|
||||||
rkey2.clear()
|
rkey2.clear()
|
||||||
check:
|
check:
|
||||||
isFullZero(rkey1.data) == true
|
not rkey1.verify()
|
||||||
isFullZero(rkey2.data) == true
|
not rkey2.verify()
|
||||||
test "Public key serialize/deserialize test":
|
test "Public key serialize/deserialize test":
|
||||||
for i in 0..<TestsCount:
|
for i in 0..<TestsCount:
|
||||||
var rkey1, rkey2: SkPublicKey
|
var rkey1, rkey2: SkPublicKey
|
||||||
@ -68,6 +68,7 @@ suite "Secp256k1 testing suite":
|
|||||||
var pubkey = SkPublicKey.init(serpk)
|
var pubkey = SkPublicKey.init(serpk)
|
||||||
var csig = SkSignature.init(sersig)
|
var csig = SkSignature.init(sersig)
|
||||||
check csig.verify(message, pubkey) == true
|
check csig.verify(message, pubkey) == true
|
||||||
let error = len(csig.data) - 1
|
var error = csig.getBytes()
|
||||||
csig.data[error] = not(csig.data[error])
|
error[^1] = not error[^1]
|
||||||
|
csig = SkSignature.init(error)
|
||||||
check csig.verify(message, pubkey) == false
|
check csig.verify(message, pubkey) == false
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user