Csaba Kiraly 8a76817b76
port: serialization should use the backend as well
Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
2022-05-26 15:48:56 +02:00

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)