nim-abc/abc/keys.nim

68 lines
2.1 KiB
Nim

import std/sugar
import std/sequtils
import std/hashes
import pkg/blscurve as bls
import pkg/nimcrypto
import pkg/questionable
type
PrivateKey* = distinct bls.SecretKey
PublicKey* = distinct bls.PublicKey
Signature* = distinct bls.Signature
func `==`*(a, b: PrivateKey): bool {.borrow.}
func `==`*(a, b: PublicKey): bool {.borrow.}
func `==`*(a, b: Signature): bool {.borrow.}
func `$`*(s: PrivateKey): string {.error: "Private keys should not be printed".}
func `$`*(s: PublicKey): string {.borrow.}
func `$`*(s: Signature): string {.borrow.}
proc random*(_: type PrivateKey): PrivateKey =
var seed = newSeq[byte](64)
doAssert randomBytes(seed) == seed.len
doAssert deriveMasterSecretKey(bls.SecretKey(result), seed)
burnArray(seed)
func erase*(key: var PrivateKey) =
burnMem(key)
func toPublicKey*(private: PrivateKey): PublicKey =
doAssert publicFromSecret(bls.PublicKey(result), bls.SecretKey(private))
func sign*(key: PrivateKey, message: openArray[byte]): Signature =
Signature(bls.SecretKey(key).sign(message))
func verify*(key: PublicKey,
message: openArray[byte],
signature: Signature): bool =
## TODO: not safe w.r.t. rogue public-key attack. Needs implementation of
## modified BLS multi-signature construction as described in:
## https://crypto.stanford.edu/~dabo/pubs/papers/BLSmultisig.html
bls.PublicKey(key).verify(message, bls.Signature(signature))
func aggregate*(keys: varargs[PublicKey]): PublicKey =
var aggregate: bls.PublicKey
doAssert aggregateAll(aggregate, @keys.map(key => bls.PublicKey(key)))
PublicKey(aggregate)
func aggregate*(signatures: varargs[Signature]): Signature =
var aggregate: bls.Signature
doAssert aggregateAll(aggregate, @signatures.map(sig => bls.Signature(sig)))
Signature(aggregate)
func toBytes*(key: PublicKey): seq[byte] =
var bytes: array[48, byte]
doAssert serialize(bytes, bls.PublicKey(key))
@bytes
func fromBytes*(_: type PublicKey, bytes: openArray[byte]): ?PublicKey =
var key: bls.PublicKey
if key.fromBytes(bytes):
PublicKey(key).some
else:
PublicKey.none
func hash*(key: PublicKey): Hash =
key.toBytes.hash