mirror of
https://github.com/codex-storage/nim-codex.git
synced 2025-02-28 04:20:49 +00:00
167 lines
5.2 KiB
Nim
167 lines
5.2 KiB
Nim
## Nim-POS
|
|
## Copyright (c) 2022 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.
|
|
|
|
# Implementation of the BLS-based public PoS scheme from
|
|
# Shacham H., Waters B., "Compact Proofs of Retrievability"
|
|
# using pairing over BLS12-381 ECC
|
|
|
|
import pkg/blscurve
|
|
import pkg/blscurve/blst/blst_abi
|
|
|
|
type
|
|
ec_SecretKey* = blscurve.SecretKey
|
|
ec_PublicKey* = blscurve.PublicKey
|
|
ec_p1* = blst_p1
|
|
ec_p2* = blst_p2
|
|
ec_p1_affine* = blst_p1_affine
|
|
ec_p2_affine* = blst_p2_affine
|
|
ec_scalar* = blst_scalar
|
|
ec_fr* = blst_fr
|
|
ec_signature* = Signature
|
|
|
|
const
|
|
EC_SUCCESS*: bool = true
|
|
|
|
# these need to be template as a workaround for const
|
|
template EC_G1* : blst_p1_affine = BLS12_381_G1
|
|
template EC_G2* : blst_p2_affine = BLS12_381_G2
|
|
|
|
func ec_p1_serialize*(dst: var array[96, byte]; src: ec_p1) =
|
|
blst_p1_serialize(dst, src)
|
|
|
|
func ec_p1_deserialize*(dst: var ec_p1_affine; src: array[96, byte]): bool =
|
|
blst_p1_deserialize(dst, src) == BLST_SUCCESS
|
|
|
|
func ec_p2_serialize*(dst: var array[192, byte]; src: ec_p2) =
|
|
blst_p2_serialize(dst, src)
|
|
|
|
func ec_p2_deserialize*(dst: var ec_p2_affine; src: array[192, byte]): bool =
|
|
blst_p2_deserialize(dst, src) == BLST_SUCCESS
|
|
|
|
func ec_export_uncompressed*(publicKey: ec_PublicKey): array[96, byte] {.inline, noinit.} =
|
|
blscurve.exportUncompressed(publicKey)
|
|
|
|
func ec_export_uncompressed*(signature: ec_Signature): array[192, byte] {.inline, noinit.} =
|
|
blscurve.exportUncompressed(signature)
|
|
|
|
func ec_p1_from_affine*(dst: var ec_p1, src: ec_p1_affine) =
|
|
blst_p1_from_affine(dst, src)
|
|
|
|
func ec_scalar_from_bendian*(ret: var ec_scalar, a: array[32, byte]) =
|
|
blst_scalar_from_bendian(ret, a)
|
|
|
|
func ec_bendian_from_scalar*(ret: var array[32, byte], a: ec_scalar) =
|
|
blst_bendian_from_scalar(ret, a)
|
|
|
|
func ec_scalar_fr_check*(a: ec_scalar): CTBool =
|
|
blst_scalar_fr_check(a)
|
|
|
|
func ec_p2_from_affine*(dst: var ec_p2, src: ec_p2_affine) =
|
|
blst_p2_from_affine(dst, src)
|
|
|
|
func ec_p2_mult*(dst: var blst_p2, p: blst_p2, scalar: blst_scalar, nbits: uint) =
|
|
blst_p2_mult(dst, p, scalar, nbits)
|
|
|
|
func ec_p1_mult*(dst: var ec_p1, p: ec_p1, scalar: ec_scalar, nbits: uint) =
|
|
blst_p1_mult(dst, p, scalar, nbits)
|
|
|
|
func ec_p1_add_or_double*(dst: var ec_p1, a: ec_p1, b: ec_p1) =
|
|
blst_p1_add_or_double(dst, a, b)
|
|
|
|
func ec_fr_from_scalar*(ret: var ec_fr, a: ec_scalar) =
|
|
blst_fr_from_scalar(ret, a)
|
|
|
|
func ec_fr_mul*(ret: var ec_fr, a: ec_fr, b: ec_fr) =
|
|
blst_fr_mul(ret, a, b)
|
|
|
|
func ec_scalar_from_fr*(ret: var ec_scalar, a: ec_fr) =
|
|
blst_scalar_from_fr(ret, a)
|
|
|
|
func ec_fr_add*(ret: var ec_fr, a: ec_fr, b: ec_fr) =
|
|
blst_fr_add(ret, a, b)
|
|
|
|
func ec_p1_on_curve*(p: ec_p1): CTBool =
|
|
blst_p1_on_curve(p)
|
|
|
|
func ec_keygen*(ikm: openarray[byte], publicKey: var ec_PublicKey, secretKey: var ec_SecretKey): bool =
|
|
blscurve.keyGen(ikm, publicKey, secretKey)
|
|
|
|
func ec_export_raw*(signature: Signature): array[96, byte] {.inline, noinit.} =
|
|
blscurve.exportRaw(signature)
|
|
|
|
proc ec_sign*[T: byte|char](secretKey: SecretKey, message: openarray[T]): Signature =
|
|
blscurve.sign(secretKey, message)
|
|
|
|
proc ec_hash_to_g1*[T,U,V: byte|char](dst: var blst_p1;
|
|
msg: openArray[T];
|
|
domainSepTag: openArray[U];
|
|
aug: openArray[V]) =
|
|
blst_hash_to_g1(dst, msg, domainSepTag, aug)
|
|
|
|
proc pairing(a: ec_p1, b: ec_p2): blst_fp12 =
|
|
## Calculate pairing G_1,G_2 -> G_T
|
|
var aa: blst_p1_affine
|
|
var bb: blst_p2_affine
|
|
blst_p1_to_affine(aa, a)
|
|
blst_p2_to_affine(bb, b)
|
|
var l: blst_fp12
|
|
blst_miller_loop(l, bb, aa)
|
|
blst_final_exp(result, l)
|
|
|
|
proc verifyPairingsNaive(a1: blst_p1, a2: blst_p2, b1: blst_p1, b2: blst_p2) : bool =
|
|
let e1 = pairing(a1, a2)
|
|
let e2 = pairing(b1, b2)
|
|
return e1 == e2
|
|
|
|
proc verifyPairingsNeg(a1: ec_p1, a2: ec_p2, b1: ec_p1, b2: ec_p2) : bool =
|
|
## Faster pairing verification using 2 miller loops but ony one final exponentiation
|
|
## based on https://github.com/benjaminion/c-kzg/blob/main/src/bls12_381.c
|
|
var
|
|
loop0, loop1, gt_point: blst_fp12
|
|
aa1, bb1: blst_p1_affine
|
|
aa2, bb2: blst_p2_affine
|
|
|
|
var a1neg = a1
|
|
blst_p1_cneg(a1neg, 1)
|
|
|
|
blst_p1_to_affine(aa1, a1neg)
|
|
blst_p1_to_affine(bb1, b1)
|
|
blst_p2_to_affine(aa2, a2)
|
|
blst_p2_to_affine(bb2, b2)
|
|
|
|
blst_miller_loop(loop0, aa2, aa1)
|
|
blst_miller_loop(loop1, bb2, bb1)
|
|
|
|
blst_fp12_mul(gt_point, loop0, loop1)
|
|
blst_final_exp(gt_point, gt_point)
|
|
|
|
return blst_fp12_is_one(gt_point).bool
|
|
|
|
proc verifyPairings*(a1: ec_p1, a2: ec_p2, b1: ec_p1, b2: ec_p2) : bool =
|
|
## Wrapper to select verify pairings implementation
|
|
verifyPairingsNaive(a1, a2, b1, b2)
|
|
#verifyPairingsNeg(a1, a2, b1, b2)
|
|
|
|
func ec_from_bytes*(
|
|
obj: var (Signature|ProofOfPossession),
|
|
raw: array[96, byte] or array[192, byte]
|
|
): bool {.inline.} =
|
|
fromBytes(obj, raw)
|
|
|
|
func ec_from_bytes*(
|
|
obj: var PublicKey,
|
|
raw: array[48, byte] or array[96, byte] or openArray[byte]
|
|
): bool {.inline.} =
|
|
fromBytes(obj, raw)
|
|
|
|
func ec_verify*[T: byte|char](
|
|
publicKey: PublicKey,
|
|
message: openarray[T],
|
|
signature: Signature) : bool =
|
|
verify(publicKey, message, signature) |