mirror of
https://github.com/logos-storage/logos-storage-nim.git
synced 2026-01-05 23:13:09 +00:00
To enable the use of BN254, change the value of `C` in backend_constantine.nim to `BN254_Snarks` This also requires https://github.com/mratsim/constantine/pull/193 Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
190 lines
5.7 KiB
Nim
190 lines
5.7 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
|
|
constantine,
|
|
# constantine/platforms/abstractions,
|
|
constantine/math/arithmetic,
|
|
# constantine/math/extension_fields,
|
|
# constantine/math/config/curves,
|
|
constantine/math/elliptic/[ec_shortweierstrass_affine, ec_shortweierstrass_projective],
|
|
constantine/math/curves/[zoo_subgroups, zoo_pairings, zoo_generators],
|
|
# constantine/math/pairing/cyclotomic_subgroup,
|
|
# constantine/math/io/io_extfields,
|
|
constantine/math/io/io_bigints,
|
|
# constantine/math/config/[curves_declaration, type_ff],
|
|
constantine/math/config/type_ff,
|
|
constantine/blssig_pop_on_bls12381_g2,
|
|
constantine/hash_to_curve/hash_to_curve,
|
|
constantine/hashes,
|
|
constantine/math/pairings
|
|
|
|
export hashes
|
|
export matchingBigInt
|
|
export getNonResidueFp
|
|
|
|
when defined(debugConstantine):
|
|
import constantine/math/config/type_bigint
|
|
export `$`
|
|
|
|
#set up curve and G1/G2
|
|
#const C = BN254_Snarks
|
|
const C = BLS12_381
|
|
|
|
type
|
|
ec_SecretKey* = SecretKey
|
|
ec_PublicKey* = PublicKey
|
|
ec_p1* = ECP_ShortW_Jac[Fp[C], G1]
|
|
ec_p1_affine = ECP_ShortW_Aff[Fp[C], G1]
|
|
ec_p2* = ECP_ShortW_Jac[Fp2[C], G2]
|
|
ec_p2_affine = ECP_ShortW_Aff[Fp2[C], G2]
|
|
ec_scalar* = matchingOrderBigInt(C)
|
|
ec_fr* = Fr[C]
|
|
ec_signature* = Signature
|
|
|
|
let
|
|
EC_G1* = C.getGenerator($G1)
|
|
EC_G2* = C.getGenerator($G2)
|
|
|
|
func ec_p1_from_affine*(dst: var ec_p1, a: ec_p1_affine) =
|
|
dst.fromAffine(a)
|
|
|
|
#let ec_scalar_from_bendian* = unmarshalBE # not exposed
|
|
func ec_scalar_from_bendian*(
|
|
s: var ec_scalar,
|
|
b: openArray[byte]) =
|
|
s.unmarshal(b, bigEndian)
|
|
|
|
#let ec_scalar_fr_check* = blst_scalar_fr_check
|
|
func ec_scalar_fr_check*(
|
|
s: ec_scalar) : bool =
|
|
bool(s < C.getCurveOrder())
|
|
|
|
func ec_p2_from_affine*(dst: var ec_p2, a: ec_p2_affine) =
|
|
dst.fromAffine(a)
|
|
|
|
func ec_p2_mult*(
|
|
dst: var ec_p2,
|
|
p: ec_p2,
|
|
scalar: ec_scalar,
|
|
nbits: uint) =
|
|
dst = p
|
|
dst.scalarMul(scalar)
|
|
|
|
func ec_p1_mult*(
|
|
dst: var ec_p1,
|
|
p: ec_p1,
|
|
scalar: ec_scalar,
|
|
nbits: uint) =
|
|
dst = p
|
|
dst.scalarMul(scalar)
|
|
|
|
func ec_p1_add_or_double*(dst: var ec_p1, a: ec_p1, b: ec_p1) =
|
|
dst.sum(a,b)
|
|
|
|
# Workaround: using ec_fr makes bindConstant fail, hence Fr[C] type below
|
|
func ec_fr_from_scalar*(res: var Fr[C], scalar: ec_scalar) =
|
|
res.fromBig(scalar)
|
|
|
|
# Workaround: using ec_fr makes bindConstant fail, hence Fr[C] type below
|
|
func ec_scalar_from_fr*(res: var ec_scalar, fr: Fr[C]) =
|
|
res = toBig(fr)
|
|
|
|
func ec_fr_add*(res: var Fr[C], a, b: Fr[C]) =
|
|
sum(res, a, b)
|
|
|
|
func ec_fr_mul*(res: var Fr[C], a, b: Fr[C]) =
|
|
prod(res, a, b)
|
|
|
|
func ec_p1_on_curve*(p: ec_p1) : bool =
|
|
var aff : ec_p1_affine
|
|
aff.affine(p)
|
|
(bool) isOnCurve(aff.x, aff.y, G1)
|
|
|
|
func ec_keygen*(ikm: array[32, byte], pk: var PublicKey, sk: var SecretKey) : bool =
|
|
# TODO: HKDF key generation as in spec (https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature#section-2.3)
|
|
var ikm2 = ikm
|
|
ikm2[0] = 0 # TODO: this is a hack, not secure
|
|
let ok = sk.deserialize_secret_key(ikm2)
|
|
doAssert ok == cttBLS_Success
|
|
let ok2 = pk.derive_public_key(sk)
|
|
doAssert ok2 == cttBLS_Success
|
|
(ok == cttBLS_Success) and (ok2 == cttBLS_Success)
|
|
|
|
func ec_export_raw*(signature: Signature): array[96, byte] {.inline, noinit.} =
|
|
let ok = result.serialize_signature_compressed(signature)
|
|
doAssert ok == cttBLS_Success
|
|
|
|
proc ec_sign*(secretKey: SecretKey, message: openarray[char]): Signature =
|
|
let ok = result.sign(secretKey, message)
|
|
doAssert ok == cttBLS_Success
|
|
|
|
proc ec_hash_to_g1*(dst: var ec_p1,
|
|
msg: openArray[byte],
|
|
domainSepTag: openArray[char],
|
|
aug: openArray[char]) =
|
|
sha256.hashToCurve(128, dst, aug, msg, domainSepTag) #TODO: fix k
|
|
|
|
proc verifyPairingsNaive[C](a1: ECP_ShortW_Jac[Fp[C], G1], a2: ec_p2, b1: ec_p1, b2: ec_p2) : bool =
|
|
# first parameter is in extended form to allow inference of C
|
|
var
|
|
e1, e2: Fp12[C]
|
|
a1aff, b1aff {.noInit.}: ec_p1_affine
|
|
a2aff, b2aff {.noInit.}: ec_p2_affine
|
|
a1aff.affine(a1)
|
|
b1aff.affine(b1)
|
|
a2aff.affine(a2)
|
|
b2aff.affine(b2)
|
|
pairing(e1, a1aff, a2aff)
|
|
pairing(e2, b1aff, b2aff)
|
|
return (e1 == e2).bool()
|
|
|
|
proc verifyPairingsNeg[C](a1: ECP_ShortW_Jac[Fp[C], G1], a2: ec_p2, b1: ec_p1, b2: ec_p2) : bool =
|
|
# first parameter is in extended form to allow inference of C
|
|
when C.getEmbeddingDegree() == 12:
|
|
var gt {.noInit.}: Fp12[C]
|
|
else:
|
|
{.error: "Not implemented: signature on k=" & $C.getEmbeddingDegree() & " for curve " & $$C.}
|
|
|
|
var
|
|
a1aff, b1aff {.noInit.}: ec_p1_affine
|
|
a2aff, negb2aff {.noInit.}: ec_p2_affine
|
|
a1aff.affine(a1)
|
|
b1aff.affine(b1)
|
|
a2aff.affine(a2)
|
|
negb2aff.affine(b2)
|
|
negb2aff.neg(negb2aff)
|
|
gt.pairing([a1aff, b1aff], [a2aff, negb2aff])
|
|
return gt.isOne().bool()
|
|
|
|
proc verifyPairings*(a1: ec_p1, a2: ec_p2, b1: ec_p1, b2: ec_p2) : bool =
|
|
## Wrapper to select verify pairings implementation
|
|
when C == BLS12_381:
|
|
verifyPairingsNeg(a1, a2, b1, b2)
|
|
else:
|
|
verifyPairingsNaive(a1, a2, b1, b2)
|
|
|
|
|
|
func ec_from_bytes*(
|
|
dst: var Signature,
|
|
raw: array[96, byte] or array[192, byte]
|
|
): bool {.inline.} =
|
|
let ok = dst.deserialize_signature_compressed(raw)
|
|
ok == cttBLS_Success
|
|
|
|
func ec_verify*(
|
|
publicKey: PublicKey,
|
|
message: openarray[char],
|
|
signature: Signature) : bool =
|
|
publicKey.verify(message, signature) == cttBLS_Success
|