2021-06-28 14:08:56 +00:00
|
|
|
import std/sugar
|
|
|
|
import std/sequtils
|
2021-06-24 12:43:17 +00:00
|
|
|
import pkg/blscurve as bls
|
|
|
|
import pkg/nimcrypto
|
2021-06-28 10:55:12 +00:00
|
|
|
import pkg/questionable
|
2021-06-24 12:43:17 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
PrivateKey* = distinct bls.SecretKey
|
|
|
|
PublicKey* = distinct bls.PublicKey
|
2021-06-28 08:10:15 +00:00
|
|
|
Signature* = distinct bls.Signature
|
2021-06-24 12:43:17 +00:00
|
|
|
|
2021-06-28 08:15:03 +00:00
|
|
|
func `==`*(a, b: PrivateKey): bool {.borrow.}
|
|
|
|
func `==`*(a, b: PublicKey): bool {.borrow.}
|
|
|
|
func `==`*(a, b: Signature): bool {.borrow.}
|
2021-06-24 12:43:17 +00:00
|
|
|
|
|
|
|
proc random*(_: type PrivateKey): PrivateKey =
|
|
|
|
var seed = newSeq[byte](64)
|
|
|
|
doAssert randomBytes(seed) == seed.len
|
|
|
|
doAssert deriveMasterSecretKey(bls.SecretKey(result), seed)
|
|
|
|
burnArray(seed)
|
|
|
|
|
2021-06-28 08:15:03 +00:00
|
|
|
func erase*(key: var PrivateKey) =
|
2021-06-24 12:43:17 +00:00
|
|
|
burnMem(key)
|
|
|
|
|
2021-06-28 08:15:03 +00:00
|
|
|
func toPublicKey*(private: PrivateKey): PublicKey =
|
2021-06-24 12:43:17 +00:00
|
|
|
doAssert publicFromSecret(bls.PublicKey(result), bls.SecretKey(private))
|
|
|
|
|
2021-06-28 08:15:03 +00:00
|
|
|
func sign*(key: PrivateKey, message: openArray[byte]): Signature =
|
2021-06-28 08:10:15 +00:00
|
|
|
Signature(bls.SecretKey(key).sign(message))
|
|
|
|
|
2021-06-28 08:15:03 +00:00
|
|
|
func verify*(key: PublicKey,
|
2021-06-28 08:10:15 +00:00
|
|
|
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))
|
2021-06-28 10:55:12 +00:00
|
|
|
|
2021-06-28 14:08:56 +00:00
|
|
|
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)
|
|
|
|
|
2021-06-28 10:55:12 +00:00
|
|
|
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
|