mirror of
https://github.com/logos-storage/constantine.git
synced 2026-01-02 13:13:07 +00:00
BLS signatures for Ethereum (BLS sig on BLS12-381 G2 with SHA256) (#183)
* Finally add the (Ethereum) bls signatures (on BLS12-381 G2) * fix test path and remove old low-level signature test
This commit is contained in:
parent
fe500a6a79
commit
5bc6d1d426
@ -45,7 +45,7 @@ After [installation](#installation), the available high-level protocols are:
|
||||
- [x] Ethereum EVM precompiles on BN254_Snarks (also called alt_bn128 or bn256 in Ethereum)
|
||||
|
||||
`import constantine/ethereum_evm_precompiles`
|
||||
- [ ] BLS signature on BLS12-381 G2 as used in Ethereum 2.
|
||||
- [x] BLS signature on BLS12-381 G2 as used in Ethereum 2.
|
||||
Cryptographic suite: `BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_`
|
||||
|
||||
This scheme is also used in the following blockchains:
|
||||
|
||||
187
benchmarks/bench_blssig_on_bls12_381_g2.nim
Normal file
187
benchmarks/bench_blssig_on_bls12_381_g2.nim
Normal file
@ -0,0 +1,187 @@
|
||||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
# Internals
|
||||
../constantine/blssig_pop_on_bls12381_g2,
|
||||
# Helpers
|
||||
../helpers/prng_unsafe,
|
||||
./bench_blueprint
|
||||
|
||||
proc separator*() = separator(132)
|
||||
|
||||
proc report(op, curve: string, startTime, stopTime: MonoTime, startClk, stopClk: int64, iters: int) =
|
||||
let ns = inNanoseconds((stopTime-startTime) div iters)
|
||||
let throughput = 1e9 / float64(ns)
|
||||
when SupportsGetTicks:
|
||||
echo &"{op:<40} {curve:<15} {throughput:>15.3f} ops/s {ns:>9} ns/op {(stopClk - startClk) div iters:>9} CPU cycles (approx)"
|
||||
else:
|
||||
echo &"{op:<40} {curve:<15} {throughput:>15.3f} ops/s {ns:>9} ns/op"
|
||||
|
||||
template bench(op: string, curve: string, iters: int, body: untyped): untyped =
|
||||
measure(iters, startTime, stopTime, startClk, stopClk, body)
|
||||
report(op, curve, startTime, stopTime, startClk, stopClk, iters)
|
||||
|
||||
proc benchDeserPubkey*(iters: int) =
|
||||
var seckey: array[32, byte]
|
||||
for i in 1 ..< 32:
|
||||
seckey[i] = byte 42
|
||||
var
|
||||
sk{.noInit.}: SecretKey
|
||||
pk{.noInit.}: PublicKey
|
||||
pk_comp{.noInit.}: array[48, byte]
|
||||
|
||||
let ok = sk.deserialize_secret_key(seckey)
|
||||
doAssert ok == cttBLS_Success
|
||||
let ok2 = pk.derive_public_key(sk)
|
||||
doAssert ok2 == cttBLS_Success
|
||||
|
||||
# Serialize compressed
|
||||
let ok3 = pk_comp.serialize_public_key_compressed(pk)
|
||||
doAssert ok3 == cttBLS_Success
|
||||
|
||||
var pk2{.noInit.}: PublicKey
|
||||
|
||||
bench("Pubkey deserialization (full checks)", "BLS12_381 G1", iters):
|
||||
let status = pk2.deserialize_public_key_compressed(pk_comp)
|
||||
|
||||
proc benchDeserPubkeyUnchecked*(iters: int) =
|
||||
var seckey: array[32, byte]
|
||||
for i in 1 ..< 32:
|
||||
seckey[i] = byte 42
|
||||
var
|
||||
sk{.noInit.}: SecretKey
|
||||
pk{.noInit.}: PublicKey
|
||||
pk_comp{.noInit.}: array[48, byte]
|
||||
|
||||
let ok = sk.deserialize_secret_key(seckey)
|
||||
doAssert ok == cttBLS_Success
|
||||
let ok2 = pk.derive_public_key(sk)
|
||||
doAssert ok2 == cttBLS_Success
|
||||
|
||||
# Serialize compressed
|
||||
let ok3 = pk_comp.serialize_public_key_compressed(pk)
|
||||
doAssert ok3 == cttBLS_Success
|
||||
|
||||
var pk2{.noInit.}: PublicKey
|
||||
|
||||
bench("Pubkey deserialization (skip checks)", "BLS12_381 G1", iters):
|
||||
let status = pk2.deserialize_public_key_compressed_unchecked(pk_comp)
|
||||
|
||||
proc benchDeserSig*(iters: int) =
|
||||
var seckey: array[32, byte]
|
||||
for i in 1 ..< 32:
|
||||
seckey[i] = byte 42
|
||||
const msg = "abcdef0123456789"
|
||||
|
||||
var
|
||||
sk{.noInit.}: SecretKey
|
||||
pk{.noInit.}: PublicKey
|
||||
sig_comp{.noInit.}: array[96, byte]
|
||||
sig {.noInit.}: Signature
|
||||
|
||||
let ok = sk.deserialize_secret_key(seckey)
|
||||
doAssert ok == cttBLS_Success
|
||||
let ok2 = pk.derive_public_key(sk)
|
||||
doAssert ok2 == cttBLS_Success
|
||||
|
||||
let status = sig.sign(sk, msg)
|
||||
doAssert status == cttBLS_Success
|
||||
|
||||
# Serialize compressed
|
||||
let ok3 = sig_comp.serialize_signature_compressed(sig)
|
||||
doAssert ok3 == cttBLS_Success
|
||||
|
||||
var sig2{.noInit.}: Signature
|
||||
|
||||
bench("Signature deserialization (full checks)", "BLS12_381 G2", iters):
|
||||
let status = sig2.deserialize_signature_compressed(sig_comp)
|
||||
|
||||
proc benchDeserSigUnchecked*(iters: int) =
|
||||
var seckey: array[32, byte]
|
||||
for i in 1 ..< 32:
|
||||
seckey[i] = byte 42
|
||||
const msg = "abcdef0123456789"
|
||||
|
||||
var
|
||||
sk{.noInit.}: SecretKey
|
||||
pk{.noInit.}: PublicKey
|
||||
sig_comp{.noInit.}: array[96, byte]
|
||||
sig {.noInit.}: Signature
|
||||
|
||||
let ok = sk.deserialize_secret_key(seckey)
|
||||
doAssert ok == cttBLS_Success
|
||||
let ok2 = pk.derive_public_key(sk)
|
||||
doAssert ok2 == cttBLS_Success
|
||||
|
||||
let status = sig.sign(sk, msg)
|
||||
doAssert status == cttBLS_Success
|
||||
|
||||
# Serialize compressed
|
||||
let ok3 = sig_comp.serialize_signature_compressed(sig)
|
||||
doAssert ok3 == cttBLS_Success
|
||||
|
||||
var sig2{.noInit.}: Signature
|
||||
|
||||
bench("Signature deserialization (skip checks)", "BLS12_381 G2", iters):
|
||||
let status = sig2.deserialize_signature_compressed_unchecked(sig_comp)
|
||||
|
||||
proc benchSign*(iters: int) =
|
||||
var seckey: array[32, byte]
|
||||
for i in 1 ..< 32:
|
||||
seckey[i] = byte 42
|
||||
let msg = "Mr F was here"
|
||||
|
||||
var pk: PublicKey
|
||||
var sk: SecretKey
|
||||
var sig: Signature
|
||||
|
||||
let ok = sk.deserialize_secret_key(seckey)
|
||||
doAssert ok == cttBLS_Success
|
||||
|
||||
bench("BLS signature", "BLS12_381 G2", iters):
|
||||
let status = sig.sign(sk, msg)
|
||||
doAssert status == cttBLS_Success
|
||||
|
||||
|
||||
proc benchVerify*(iters: int) =
|
||||
var seckey: array[32, byte]
|
||||
for i in 1 ..< 32:
|
||||
seckey[i] = byte 42
|
||||
let msg = "Mr F was here"
|
||||
|
||||
var pk: PublicKey
|
||||
var sk: SecretKey
|
||||
var sig: Signature
|
||||
|
||||
let ok = sk.deserialize_secret_key(seckey)
|
||||
doAssert ok == cttBLS_Success
|
||||
|
||||
let ok2 = sig.sign(sk, msg)
|
||||
|
||||
let ok3 = pk.derive_public_key(sk)
|
||||
doAssert ok3 == cttBLS_Success
|
||||
|
||||
bench("BLS verification", "BLS12_381", iters):
|
||||
let valid = pk.verify(msg, sig)
|
||||
|
||||
const Iters = 1000
|
||||
|
||||
proc main() =
|
||||
separator()
|
||||
benchDeserPubkey(Iters)
|
||||
benchDeserPubkeyUnchecked(Iters)
|
||||
benchDeserSig(Iters)
|
||||
benchDeserSigUnchecked(Iters)
|
||||
separator()
|
||||
benchSign(Iters)
|
||||
benchVerify(Iters)
|
||||
separator()
|
||||
|
||||
main()
|
||||
notes()
|
||||
@ -38,7 +38,7 @@ macro fixFieldDisplay(T: typedesc): untyped =
|
||||
# At compile-time, enums are integers and their display is buggy
|
||||
# we get the Curve ID instead of the curve name.
|
||||
let instantiated = T.getTypeInst()
|
||||
var name = $instantiated[1][0] # Fp
|
||||
var name = $instantiated[1][0] # 𝔽p
|
||||
name.add "[" & $Curve(instantiated[1][1].intVal) & "]"
|
||||
result = newLit name
|
||||
|
||||
|
||||
@ -190,8 +190,8 @@ const testDesc: seq[tuple[path: string, useGMP: bool]] = @[
|
||||
|
||||
# Protocols
|
||||
# ----------------------------------------------------------
|
||||
("tests/t_sig_bls_lowlevel.nim", false),
|
||||
("tests/t_ethereum_evm_precompiles.nim", false),
|
||||
("tests/t_blssig_pop_on_bls12381_g2.nim", false),
|
||||
]
|
||||
|
||||
# For temporary (hopefully) investigation that can only be reproduced in CI
|
||||
@ -209,9 +209,7 @@ const skipSanitizers = [
|
||||
"tests/backend/t_ec_sage_bls12_377.nim",
|
||||
"tests/backend/t_ec_sage_bls12_381.nim",
|
||||
"tests/backend/t_hash_to_field.nim",
|
||||
"tests/backend/t_hash_to_curve.nim",
|
||||
"tests/backend/t_sig_bls_lowlevel.nim",
|
||||
"tests/protocols/t_ethereum_evm_precompiles.nim"
|
||||
"tests/backend/t_hash_to_curve.nim"
|
||||
]
|
||||
|
||||
when defined(windows):
|
||||
@ -746,3 +744,20 @@ task bench_hash_to_curve_gcc_noasm, "Run Hash-to-Curve benchmarks":
|
||||
|
||||
task bench_hash_to_curve_clang_noasm, "Run Hash-to-Curve benchmarks":
|
||||
runBench("bench_hash_to_curve", "clang", useAsm = false)
|
||||
|
||||
# BLS signatures
|
||||
# ------------------------------------------
|
||||
task bench_blssig_on_bls12_381_g2, "Run Hash-to-Curve benchmarks":
|
||||
runBench("bench_blssig_on_bls12_381_g2")
|
||||
|
||||
task bench_blssig_on_bls12_381_g2_gcc, "Run Hash-to-Curve benchmarks":
|
||||
runBench("bench_blssig_on_bls12_381_g2", "gcc")
|
||||
|
||||
task bench_blssig_on_bls12_381_g2_clang, "Run Hash-to-Curve benchmarks":
|
||||
runBench("bench_blssig_on_bls12_381_g2", "clang")
|
||||
|
||||
task bench_blssig_on_bls12_381_g2_gcc_noasm, "Run Hash-to-Curve benchmarks":
|
||||
runBench("bench_blssig_on_bls12_381_g2", "gcc", useAsm = false)
|
||||
|
||||
task bench_blssig_on_bls12_381_g2_clang_noasm, "Run Hash-to-Curve benchmarks":
|
||||
runBench("bench_blssig_on_bls12_381_g2", "clang", useAsm = false)
|
||||
|
||||
@ -36,7 +36,7 @@ export CurveFamily, SexticTwist
|
||||
# - type Curve* = enum
|
||||
# - proc Mod*(curve: static Curve): auto
|
||||
# which returns the field modulus of the curve
|
||||
# - proc Family*(curve: static Curve): CurveFamily
|
||||
# - proc family*(curve: static Curve): CurveFamily
|
||||
# which returns the curve family
|
||||
|
||||
declareCurves:
|
||||
|
||||
32
constantine/backend/curves/bls12_381_generators.nim
Normal file
32
constantine/backend/curves/bls12_381_generators.nim
Normal file
@ -0,0 +1,32 @@
|
||||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
../config/[curves, type_ff],
|
||||
../elliptic/ec_shortweierstrass_affine,
|
||||
../io/[io_fields, io_towers]
|
||||
|
||||
# Generators
|
||||
# -----------------------------------------------------------------
|
||||
# https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-10#section-4.2.1
|
||||
|
||||
const BLS12_381_generator_G1* = ECP_ShortW_Aff[Fp[BLS12_381], G1](
|
||||
x: Fp[BLS12_381].fromHex"0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb",
|
||||
y: Fp[BLS12_381].fromHex"0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1"
|
||||
)
|
||||
|
||||
const BLS12_381_generator_G2* = ECP_ShortW_Aff[Fp2[BLS12_381], G2](
|
||||
x: Fp2[BLS12_381].fromHex(
|
||||
"0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8",
|
||||
"0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e"
|
||||
),
|
||||
y: Fp2[BLS12_381].fromHex(
|
||||
"0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801",
|
||||
"0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be"
|
||||
)
|
||||
)
|
||||
@ -82,11 +82,11 @@ const Cofactor_Eff_BLS12_381_G2 = BigInt[636].fromHex"0xbc69f08f2ee75b3584c6a0ea
|
||||
## P -> (x^2 - x - 1) P + (x - 1) ψ(P) + ψ(ψ(2P))
|
||||
|
||||
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp[BLS12_381], G1]) {.inline.} =
|
||||
## Clear the cofactor of BLS12_381 G1
|
||||
## Clear the cofactor of BLS12_381 𝔾1
|
||||
P.scalarMulGeneric(Cofactor_Eff_BLS12_381_G1)
|
||||
|
||||
func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp2[BLS12_381], G2]) {.inline.} =
|
||||
## Clear the cofactor of BLS12_381 G2
|
||||
## Clear the cofactor of BLS12_381 𝔾2
|
||||
# Endomorphism acceleration cannot be used if cofactor is not cleared
|
||||
P.scalarMulGeneric(Cofactor_Eff_BLS12_381_G2)
|
||||
|
||||
@ -96,11 +96,11 @@ func clearCofactorReference*(P: var ECP_ShortW_Prj[Fp2[BLS12_381], G2]) {.inline
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
# BLS12 G1
|
||||
# BLS12 𝔾1
|
||||
# ------------------------------------------------------------
|
||||
|
||||
func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp[BLS12_381], G1]) =
|
||||
## Clear the cofactor of BLS12_381 G1
|
||||
func clearCofactorFast*(P: var ECP_ShortW[Fp[BLS12_381], G1]) =
|
||||
## Clear the cofactor of BLS12_381 𝔾1
|
||||
##
|
||||
## Wahby et al "Fast and simple constant-time hashing to the BLS12-381 elliptic curve", https://eprint.iacr.org/2019/403
|
||||
## Optimized using endomorphisms
|
||||
@ -109,19 +109,19 @@ func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp[BLS12_381], G1]) =
|
||||
t.pow_bls12_381_minus_x(P) # [-x]P
|
||||
P += t # [1-x]P
|
||||
|
||||
# BLS12 G2
|
||||
# BLS12 𝔾2
|
||||
# ------------------------------------------------------------
|
||||
# From any point on the elliptic curve E2 of a BLS12 curve
|
||||
# Obtain a point in the G2 prime-order subgroup
|
||||
# Obtain a point in the 𝔾2 prime-order subgroup
|
||||
#
|
||||
# Described in https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-G.4
|
||||
#
|
||||
# Implementations, multiple implementations are possible in increasing order of speed:
|
||||
#
|
||||
# - The default, canonical, implementation is h_eff * P
|
||||
# - Scott et al, "Fast Hashing to G2 on Pairing-Friendly Curves", https://doi.org/10.1007/978-3-642-03298-1_8
|
||||
# - Fuentes-Castaneda et al, "Fast Hashing to G2 on Pairing-Friendly Curves", https://doi.org/10.1007/978-3-642-28496-0_25
|
||||
# - Budroni et al, "Hashing to G2 on BLS pairing-friendly curves", https://doi.org/10.1145/3313880.3313884
|
||||
# - Scott et al, "Fast Hashing to 𝔾2 on Pairing-Friendly Curves", https://doi.org/10.1007/978-3-642-03298-1_8
|
||||
# - Fuentes-Castaneda et al, "Fast Hashing to 𝔾2 on Pairing-Friendly Curves", https://doi.org/10.1007/978-3-642-28496-0_25
|
||||
# - Budroni et al, "Hashing to 𝔾2 on BLS pairing-friendly curves", https://doi.org/10.1145/3313880.3313884
|
||||
# - Wahby et al "Fast and simple constant-time hashing to the BLS12-381 elliptic curve", https://eprint.iacr.org/2019/403
|
||||
# - IETF "Hashing to Elliptic Curves", https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-G.4
|
||||
#
|
||||
@ -138,8 +138,8 @@ func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp[BLS12_381], G1]) =
|
||||
# with Psi (ψ) - untwist-Frobenius-Twist function
|
||||
# and x the curve BLS parameter
|
||||
|
||||
func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp2[BLS12_381], G2]) =
|
||||
## Clear the cofactor of BLS12_381 G2
|
||||
func clearCofactorFast*(P: var ECP_ShortW[Fp2[BLS12_381], G2]) =
|
||||
## Clear the cofactor of BLS12_381 𝔾2
|
||||
## Optimized using endomorphisms
|
||||
## P -> [x²-x-1]P + [x-1] ψ(P) + ψ²([2]P)
|
||||
|
||||
@ -166,18 +166,18 @@ func clearCofactorFast*(P: var ECP_ShortW_Prj[Fp2[BLS12_381], G2]) =
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
func isInSubgroup*(P: ECP_ShortW_Prj[Fp[BLS12_381], G1]): SecretBool =
|
||||
## Returns true if P is in G1 subgroup, i.e. P is a point of order r.
|
||||
func isInSubgroup*(P: ECP_ShortW_Jac[Fp[BLS12_381], G1] or ECP_ShortW_Prj[Fp[BLS12_381], G1]): SecretBool =
|
||||
## Returns true if P is in 𝔾1 subgroup, i.e. P is a point of order r.
|
||||
## A point may be on a curve but not on the prime order r subgroup.
|
||||
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||
##
|
||||
## Warning ⚠: Assumes that P is on curve
|
||||
# Implementation: Scott, https://eprint.iacr.org/2021/1130.pdf
|
||||
# A note on group membership tests for G1, G2 and GT
|
||||
# A note on group membership tests for 𝔾1, 𝔾2 and 𝔾T
|
||||
# on BLS pairing-friendly curves
|
||||
# P is in the G1 subgroup iff ϕ(P) == [-u²](P)
|
||||
var t0{.noInit.}, t1{.noInit.}: ECP_ShortW_Prj[Fp[BLS12_381], G1]
|
||||
|
||||
# P is in the 𝔾1 subgroup iff ϕ(P) == [-u²](P)
|
||||
var t0{.noInit.}, t1{.noInit.}: typeof(P)
|
||||
|
||||
# [-u²]P
|
||||
t0.pow_bls12_381_x(P)
|
||||
t1.pow_bls12_381_minus_x(t0)
|
||||
@ -189,18 +189,39 @@ func isInSubgroup*(P: ECP_ShortW_Prj[Fp[BLS12_381], G1]): SecretBool =
|
||||
|
||||
return t0 == t1
|
||||
|
||||
func isInSubgroup*(P: ECP_ShortW_Prj[Fp2[BLS12_381], G2]): SecretBool =
|
||||
## Returns true if P is in G2 subgroup, i.e. P is a point of order r.
|
||||
func isInSubgroup*(P: ECP_ShortW_Jac[Fp2[BLS12_381], G2] or ECP_ShortW_Prj[Fp2[BLS12_381], G2]): SecretBool =
|
||||
## Returns true if P is in 𝔾2 subgroup, i.e. P is a point of order r.
|
||||
## A point may be on a curve but not on the prime order r subgroup.
|
||||
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||
##
|
||||
## Warning ⚠: Assumes that P is on curve
|
||||
# Implementation: Scott, https://eprint.iacr.org/2021/1130.pdf
|
||||
# A note on group membership tests for G1, G2 and GT
|
||||
# A note on group membership tests for 𝔾1, 𝔾2 and 𝔾T
|
||||
# on BLS pairing-friendly curves
|
||||
# P is in the G1 subgroup iff ψ(P) == [u](P)
|
||||
var t0{.noInit.}, t1{.noInit.}: ECP_ShortW_Prj[Fp2[BLS12_381], G2]
|
||||
# P is in the 𝔾1 subgroup iff ψ(P) == [u](P)
|
||||
var t0{.noInit.}, t1{.noInit.}: typeof(P)
|
||||
t0.pow_bls12_381_x(P) # [u]P
|
||||
t1.frobenius_psi(P) # ψ(P)
|
||||
|
||||
return t0 == t1
|
||||
return t0 == t1
|
||||
|
||||
func isInSubgroup*(P: ECP_ShortW_Aff[Fp[BLS12_381], G1]): SecretBool =
|
||||
## Returns true if P is in 𝔾1 subgroup, i.e. P is a point of order r.
|
||||
## A point may be on a curve but not on the prime order r subgroup.
|
||||
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||
##
|
||||
## Warning ⚠: Assumes that P is on curve
|
||||
var t{.noInit.}: ECP_ShortW_Prj[Fp[BLS12_381], G1]
|
||||
t.fromAffine(P)
|
||||
return t.isInSubgroup()
|
||||
|
||||
|
||||
func isInSubgroup*(P: ECP_ShortW_Aff[Fp2[BLS12_381], G2]): SecretBool =
|
||||
## Returns true if P is in 𝔾2 subgroup, i.e. P is a point of order r.
|
||||
## A point may be on a curve but not on the prime order r subgroup.
|
||||
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||
##
|
||||
## Warning ⚠: Assumes that P is on curve
|
||||
var t{.noInit.}: ECP_ShortW_Jac[Fp2[BLS12_381], G2]
|
||||
t.fromAffine(P)
|
||||
return t.isInSubgroup()
|
||||
@ -9,11 +9,11 @@
|
||||
import
|
||||
std/macros,
|
||||
../config/curves,
|
||||
./bls12_377_g2_params,
|
||||
./bls12_381_g2_params,
|
||||
./bn254_nogami_g2_params,
|
||||
./bn254_snarks_g2_params,
|
||||
./bw6_761_g2_params
|
||||
./bls12_377_constants,
|
||||
./bls12_381_constants,
|
||||
./bn254_nogami_constants,
|
||||
./bn254_snarks_constants,
|
||||
./bw6_761_constants
|
||||
|
||||
{.experimental: "dynamicBindSym".}
|
||||
|
||||
23
constantine/backend/curves/zoo_generators.nim
Normal file
23
constantine/backend/curves/zoo_generators.nim
Normal file
@ -0,0 +1,23 @@
|
||||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
std/macros,
|
||||
../config/curves,
|
||||
./bls12_381_generators
|
||||
|
||||
{.experimental: "dynamicbindsym".}
|
||||
|
||||
macro getGenerator*(C: static Curve, subgroup: static string = ""): untyped =
|
||||
## Returns the curve subgroup generator.
|
||||
## Pairing-friendly curves expect G1 or G2
|
||||
|
||||
if subgroup == "":
|
||||
return bindSym($C & "_generator")
|
||||
else:
|
||||
return bindSym($C & "_generator_" & subgroup)
|
||||
@ -25,7 +25,7 @@ export
|
||||
func clearCofactor*[ECP](P: var ECP) {.inline.} =
|
||||
## Clear the cofactor of a point on the curve
|
||||
## From a point on the curve, returns a point on the subgroup of order r
|
||||
when ECP.F.C in {BLS12_381}:
|
||||
when ECP.F.C in {BN254_Nogami, BN254_SNarks, BLS12_377, BLS12_381}:
|
||||
P.clearCofactorFast()
|
||||
else:
|
||||
P.clearCofactorReference()
|
||||
|
||||
@ -29,7 +29,6 @@ import
|
||||
# using:
|
||||
# - GLV endomorphism on G1 (Gallant-Lambert-Vanstone)
|
||||
# - GLV and GLS endomorphisms on G2 (Galbraith-Lin-Scott)
|
||||
# - NAF recoding (windowed Non-Adjacent-Form)
|
||||
|
||||
# Decomposition into scalars -> miniscalars
|
||||
# ----------------------------------------------------------------------------------------
|
||||
|
||||
@ -12,7 +12,7 @@ import
|
||||
../arithmetic,
|
||||
../towers,
|
||||
../io/[io_fields, io_towers],
|
||||
../curves/zoo_g2_params
|
||||
../curves/zoo_constants
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
@ -45,6 +45,11 @@ func isInf*(P: ECP_ShortW_Aff): SecretBool =
|
||||
## and false otherwise
|
||||
result = P.x.isZero() and P.y.isZero()
|
||||
|
||||
func setInf*(P: var ECP_ShortW_Aff) =
|
||||
## Set P to the infinity point
|
||||
P.x.setZero()
|
||||
P.y.setZero()
|
||||
|
||||
func ccopy*(P: var ECP_ShortW_Aff, Q: ECP_ShortW_Aff, ctl: SecretBool) {.inline.} =
|
||||
## Constant-time conditional copy
|
||||
## If ctl is true: Q is copied into P
|
||||
@ -71,7 +76,7 @@ func curve_eq_rhs*[F](y2: var F, x: F, G: static Subgroup) =
|
||||
y2.fromUint uint -F.C.getCoefB()
|
||||
y2.diff(t, y2)
|
||||
else:
|
||||
y2.sum(F.C.getCoefB_G2, t)
|
||||
y2.sum(F.C.getCoefB_G2(), t)
|
||||
|
||||
when F.C.getCoefA() != 0:
|
||||
t = x
|
||||
|
||||
@ -41,14 +41,14 @@ template strxor(b_i: var array, b0: array): untyped =
|
||||
b_i[i] = b_i[i] xor b0[i]
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
func shortDomainSepTag[DigestSize: static int, B: byte|char](
|
||||
func shortDomainSepTag*[DigestSize: static int, B: byte|char](
|
||||
H: type CryptoHash,
|
||||
output: var array[DigestSize, byte],
|
||||
oversizedDST: openarray[B]) =
|
||||
## Compute a short Domain Separation Tag
|
||||
## from a domain separation tag larger than 255 bits
|
||||
## from a domain separation tag larger than 255 bytes
|
||||
##
|
||||
## https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-09#section-5.4.3
|
||||
## https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-14#section-5.4.3
|
||||
static: doAssert DigestSize == H.type.digestSize
|
||||
var ctx {.noInit.}: H
|
||||
ctx.init()
|
||||
@ -86,11 +86,10 @@ func expandMessageXMD*[B1, B2, B3: byte|char, len_in_bytes: static int](
|
||||
## and `CoreVerify(PK, PK || message, signature)`
|
||||
## - `message` is the message to hash
|
||||
## - `domainSepTag` is the protocol domain separation tag (DST).
|
||||
## If a domainSepTag larger than 255-bit is required,
|
||||
## it is recommended to cache the reduced DST
|
||||
|
||||
# TODO oversized DST support
|
||||
|
||||
## `domainSepTag` MUST be at most 255 bytes.
|
||||
## The function `shortDomainSepTag` MUST be used to compute an adequate DST
|
||||
## for an oversized source DST.
|
||||
## That DST can be cached.
|
||||
# Steps:
|
||||
# 1. ell = ceil(len_in_bytes / b_in_bytes)
|
||||
# 2. ABORT if ell > 255
|
||||
@ -210,7 +209,7 @@ func hashToField*[Field; B1, B2, B3: byte|char, count: static int](
|
||||
len_in_bytes = count * m * L
|
||||
|
||||
var uniform_bytes{.noInit.}: array[len_in_bytes, byte]
|
||||
sha256.expandMessageXMD(
|
||||
H.expandMessageXMD(
|
||||
uniform_bytes,
|
||||
augmentation = augmentation,
|
||||
message = message,
|
||||
|
||||
@ -54,7 +54,7 @@ func sgn0(x: Fp): SecretBool =
|
||||
# Another angle is that if M is odd,
|
||||
# a+M and a have different parity even though they are
|
||||
# the same modulo M.
|
||||
let canonical = x.toBig()
|
||||
let canonical {.noInit.} = x.toBig()
|
||||
result = canonical.isOdd()
|
||||
|
||||
func sgn0(x: Fp2): SecretBool =
|
||||
|
||||
@ -125,7 +125,7 @@ func hashToCurve*[
|
||||
B1, B2, B3: byte|char](
|
||||
H: type CryptoHash,
|
||||
k: static int,
|
||||
output: var ECP_ShortW_Prj[F, G],
|
||||
output: var ECP_ShortW_Jac[F, G],
|
||||
augmentation: openarray[B1],
|
||||
message: openarray[B2],
|
||||
domainSepTag: openarray[B3]
|
||||
@ -149,20 +149,52 @@ func hashToCurve*[
|
||||
## and `CoreVerify(PK, PK || message, signature)`
|
||||
## - `message` is the message to hash
|
||||
## - `domainSepTag` is the protocol domain separation tag (DST).
|
||||
## If a domainSepTag larger than 255-bit is required,
|
||||
## it is recommended to cache the reduced DST.
|
||||
|
||||
var u{.noInit.}: array[2, F]
|
||||
H.hashToField(k, u, augmentation, message, domainSepTag)
|
||||
|
||||
when false:
|
||||
var P{.noInit.}: array[2, ECP_ShortW_Prj[F, G]]
|
||||
P[0].mapToCurve(u[0])
|
||||
P[1].mapToCurve(u[1])
|
||||
output.sum(P[0], P[1])
|
||||
if domainSepTag.len <= 255:
|
||||
H.hashToField(k, u, augmentation, message, domainSepTag)
|
||||
else:
|
||||
var Pjac{.noInit.}: ECP_ShortW_Jac[F, G]
|
||||
Pjac.mapToCurve_fusedAdd(u[0], u[1])
|
||||
output.projectiveFromJacobian(Pjac)
|
||||
const N = H.type.digestSize()
|
||||
var dst {.noInit.}: array[N, byte]
|
||||
H.shortDomainSepTag(dst, domainSepTag)
|
||||
H.hashToField(k, u, augmentation, message, dst)
|
||||
|
||||
output.mapToCurve_fusedAdd(u[0], u[1])
|
||||
output.clearCofactor()
|
||||
|
||||
func hashToCurve*[
|
||||
F; G: static Subgroup;
|
||||
B1, B2, B3: byte|char](
|
||||
H: type CryptoHash,
|
||||
k: static int,
|
||||
output: var (ECP_ShortW_Prj[F, G] or ECP_ShortW_Aff[F, G]),
|
||||
augmentation: openarray[B1],
|
||||
message: openarray[B2],
|
||||
domainSepTag: openarray[B3]
|
||||
) =
|
||||
## Hash a message to an elliptic curve
|
||||
##
|
||||
## Arguments:
|
||||
## - `Hash` a cryptographic hash function.
|
||||
## - `Hash` MAY be a Merkle-Damgaard hash function like SHA-2
|
||||
## - `Hash` MAY be a sponge-based hash function like SHA-3 or BLAKE2
|
||||
## - Otherwise, H MUST be a hash function that has been proved
|
||||
## indifferentiable from a random oracle [MRH04] under a reasonable
|
||||
## cryptographic assumption.
|
||||
## - k the security parameter of the suite in bits (for example 128)
|
||||
## - `output`, an elliptic curve point that will be overwritten.
|
||||
## - `augmentation`, an optional augmentation to the message. This will be prepended,
|
||||
## prior to hashing.
|
||||
## This is used for building the "message augmentation" variant of BLS signatures
|
||||
## https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04#section-3.2
|
||||
## which requires `CoreSign(SK, PK || message)`
|
||||
## and `CoreVerify(PK, PK || message, signature)`
|
||||
## - `message` is the message to hash
|
||||
## - `domainSepTag` is the protocol domain separation tag (DST).
|
||||
|
||||
var Pjac{.noInit.}: ECP_ShortW_Jac[F, G]
|
||||
H.hashToCurve(k, Pjac, augmentation, message, domainSepTag)
|
||||
when output is ECP_ShortW_Prj:
|
||||
output.projectiveFromJacobian(Pjac)
|
||||
else:
|
||||
output.affine(Pjac)
|
||||
@ -25,8 +25,8 @@ type
|
||||
## - SHA3-512 block size is 72 bits
|
||||
|
||||
# should we avoid int to avoid exception? But they are compile-time
|
||||
H.digestSize is int
|
||||
H.internalBlockSize is int
|
||||
H.digestSize is static int
|
||||
H.internalBlockSize is static int
|
||||
|
||||
# Context
|
||||
# -------------------------------------------
|
||||
|
||||
@ -293,7 +293,8 @@ func exportRawUint*(
|
||||
## or zero-padded right for little-endian.
|
||||
## I.e least significant bit is aligned to buffer boundary
|
||||
|
||||
assert dst.len >= (BigInt.bits + 7) div 8, "BigInt -> Raw int conversion: destination buffer is too small"
|
||||
debug:
|
||||
doAssert dst.len >= (BigInt.bits + 7) div 8, "BigInt -> Raw int conversion: destination buffer is too small"
|
||||
|
||||
when BigInt.bits == 0:
|
||||
zeroMem(dst, dst.len)
|
||||
|
||||
@ -15,6 +15,7 @@ import
|
||||
],
|
||||
../isogeny/frobenius,
|
||||
../curves/zoo_pairings,
|
||||
../arithmetic,
|
||||
./cyclotomic_subgroup,
|
||||
./lines_eval,
|
||||
./miller_loops
|
||||
@ -118,7 +119,7 @@ func finalExpHard_BLS12*[C](f: var Fp12[C]) {.meter.} =
|
||||
v2.cyclotomic_square(f) # v2 = f²
|
||||
|
||||
# (x−1)²
|
||||
when C.pairing(ate_param).isEven.bool:
|
||||
when C.pairing(ate_param).isEven().bool:
|
||||
v0.cycl_exp_by_curve_param_div2(v2) # v0 = (f²)^(x/2) = f^x
|
||||
else:
|
||||
v0.cycl_exp_by_curve_param(f)
|
||||
|
||||
20
constantine/backend/pairings.nim
Normal file
20
constantine/backend/pairings.nim
Normal file
@ -0,0 +1,20 @@
|
||||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
./config/curves,
|
||||
./pairing/[pairing_bn, pairing_bls12],
|
||||
./towers
|
||||
|
||||
template pairing*[C](gt: var Fp12[C], P, Q: typed) =
|
||||
when family(C) == BarretoNaehrig:
|
||||
pairing_bn(gt, P, Q)
|
||||
elif family(C) == BarretoLynnScott:
|
||||
pairing_bls12(gt, P, Q)
|
||||
else:
|
||||
{.error: "Pairing not implemented for " & $C.}
|
||||
6
constantine/backend/signatures/README.md
Normal file
6
constantine/backend/signatures/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# Signatures schemes
|
||||
|
||||
## BLS signatures (Boneh-Lynn-Schacham)
|
||||
|
||||
- https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-04
|
||||
- https://github.com/cfrg/draft-irtf-cfrg-bls-signature
|
||||
126
constantine/backend/signatures/bls_signatures.nim
Normal file
126
constantine/backend/signatures/bls_signatures.nim
Normal file
@ -0,0 +1,126 @@
|
||||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
../ec_shortweierstrass,
|
||||
../hash_to_curve/hash_to_curve,
|
||||
../hashes, ../pairings,
|
||||
../curves/zoo_generators
|
||||
|
||||
# ############################################################
|
||||
#
|
||||
# BLS Signatures
|
||||
#
|
||||
# ############################################################
|
||||
|
||||
# This module implements generic BLS signatures
|
||||
# https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-04
|
||||
# https://github.com/cfrg/draft-irtf-cfrg-bls-signature
|
||||
#
|
||||
# We use generic shortnames SecKey, PubKey, Sig
|
||||
# so tat the algorithms fit whether Pubkey and Sig are on G1 or G2
|
||||
# Actual protocols should expose publicly the full names SecretKey, PublicKey and Signature
|
||||
|
||||
|
||||
{.push inline.} # inline in the main public procs
|
||||
{.push raises: [].} # No exceptions allowed in core cryptographic operations
|
||||
|
||||
|
||||
func derivePubkey*[Pubkey, SecKey](pubkey: var Pubkey, seckey: SecKey): bool =
|
||||
## Generates the public key associated with the input secret key.
|
||||
##
|
||||
## Returns:
|
||||
## - false is secret key is invalid (SK == 0 or >= BLS12-381 curve order),
|
||||
## true otherwise
|
||||
## By construction no public API should ever instantiate
|
||||
## an invalid secretkey in the first place.
|
||||
const Group = Pubkey.G
|
||||
type Field = Pubkey.F
|
||||
const EC = Field.C
|
||||
|
||||
if seckey.isZero().bool:
|
||||
return false
|
||||
if bool(seckey >= EC.getCurveOrder()):
|
||||
return false
|
||||
|
||||
var pk {.noInit.}: ECP_ShortW_Jac[Field, Group]
|
||||
pk.fromAffine(EC.getGenerator($Group))
|
||||
pk.scalarMul(seckey)
|
||||
pubkey.affine(pk)
|
||||
return true
|
||||
|
||||
func coreSign*[B1, B2, B3: byte|char, Sig, SecKey](
|
||||
signature: var Sig,
|
||||
secretKey: SecKey,
|
||||
message: openarray[B1],
|
||||
H: type CryptoHash,
|
||||
k: static int,
|
||||
augmentation: openarray[B2],
|
||||
domainSepTag: openarray[B3]) =
|
||||
## Computes a signature for the message from the specified secret key.
|
||||
##
|
||||
## Output:
|
||||
## - `signature` is overwritten with `message` signed with `secretKey`
|
||||
##
|
||||
## Inputs:
|
||||
## - `Hash` a cryptographic hash function.
|
||||
## - `Hash` MAY be a Merkle-Damgaard hash function like SHA-2
|
||||
## - `Hash` MAY be a sponge-based hash function like SHA-3 or BLAKE2
|
||||
## - Otherwise, H MUST be a hash function that has been proved
|
||||
## indifferentiable from a random oracle [MRH04] under a reasonable
|
||||
## cryptographic assumption.
|
||||
## - k the security parameter of the suite in bits (for example 128)
|
||||
## - `output`, an elliptic curve point that will be overwritten.
|
||||
## - `augmentation`, an optional augmentation to the message. This will be prepended,
|
||||
## prior to hashing.
|
||||
## This is used for building the "message augmentation" variant of BLS signatures
|
||||
## https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04#section-3.2
|
||||
## which requires `CoreSign(SK, PK || message)`
|
||||
## and `CoreVerify(PK, PK || message, signature)`
|
||||
## - `message` is the message to hash
|
||||
## - `domainSepTag` is the protocol domain separation tag (DST).
|
||||
|
||||
type ECP_Jac = ECP_ShortW_Jac[Sig.F, Sig.G]
|
||||
|
||||
var sig {.noInit.}: ECP_Jac
|
||||
H.hashToCurve(k, sig, augmentation, message, domainSepTag)
|
||||
sig.scalarMul(secretKey)
|
||||
|
||||
signature.affine(sig)
|
||||
|
||||
func coreVerify*[B1, B2, B3: byte|char, Pubkey, Sig](
|
||||
pubKey: Pubkey,
|
||||
message: openarray[B1],
|
||||
signature: Sig,
|
||||
H: type CryptoHash,
|
||||
k: static int,
|
||||
augmentation: openarray[B2],
|
||||
domainSepTag: openarray[B3]): bool =
|
||||
## Check that a signature is valid
|
||||
## for a message under the provided public key
|
||||
## This assumes that the PublicKey and Signatures
|
||||
## have been pre-checked for non-infinity and being in the correct subgroup
|
||||
## (likely on deserialization)
|
||||
var Q {.noInit.}: ECP_ShortW_Aff[Sig.F, Sig.G]
|
||||
var negG {.noInit.}: ECP_ShortW_Aff[Pubkey.F, Pubkey.G]
|
||||
|
||||
negG.neg(Pubkey.F.C.getGenerator($Pubkey.G))
|
||||
H.hashToCurve(k, Q, augmentation, message, domainSepTag)
|
||||
|
||||
when Sig.F.C.getEmbeddingDegree() == 12:
|
||||
var gt {.noInit.}: Fp12[Sig.F.C]
|
||||
else:
|
||||
{.error: "Not implemented: signature on k=" & $Sig.F.C.getEmbeddingDegree() & " for curve " & $$Sig.F.C.}
|
||||
|
||||
# e(PK, H(msg))*e(sig, -G) == 1
|
||||
when Sig.G == G2:
|
||||
pairing(gt, [pubKey, negG], [Q, signature])
|
||||
else:
|
||||
pairing(gt, [Q, signature], [pubKey, negG])
|
||||
|
||||
return gt.isOne().bool()
|
||||
408
constantine/blssig_pop_on_bls12381_g2.nim
Normal file
408
constantine/blssig_pop_on_bls12381_g2.nim
Normal file
@ -0,0 +1,408 @@
|
||||
# Constantine
|
||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import
|
||||
./backend/config/[
|
||||
common, curves, type_bigint, type_ff
|
||||
],
|
||||
./backend/[
|
||||
ec_shortweierstrass,
|
||||
hash_to_curve/hash_to_curve,
|
||||
hashes,
|
||||
towers,
|
||||
arithmetic,
|
||||
signatures/bls_signatures,
|
||||
curves/zoo_subgroups,
|
||||
primitives
|
||||
],
|
||||
./backend/io/[io_bigints, io_fields]
|
||||
|
||||
export
|
||||
curves, # generic sandwich on matchingBigInt
|
||||
towers, # generic sandwich on extension field access
|
||||
hashes, # generic sandwich on sha256
|
||||
ec_shortweierstrass # generic sandwich on affine
|
||||
|
||||
## ############################################################
|
||||
##
|
||||
## BLS Signatures on BLS12-381 G2
|
||||
##
|
||||
## ############################################################
|
||||
##
|
||||
## This module implements BLS Signatures (Boneh-Lynn-Schacham)
|
||||
## on top of the BLS12-381 curve (Barreto-Lynn-Scott).
|
||||
##
|
||||
## Ciphersuite:
|
||||
##
|
||||
## - Secret keys on Fr (32 bytes)
|
||||
## - Public keys on G1 (48 bytes compressed, 96 bytes uncompressed)
|
||||
## - Signatures on G2 (96 bytes compressed, 192 bytes uncompressed)
|
||||
##
|
||||
## Hash-to curve:
|
||||
## - Domain separation tag: "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"
|
||||
## - Hash function: SHA256
|
||||
##
|
||||
## Currently Constantine does not provide popProve and popVerify
|
||||
## which are thin wrapper over sign/verify with
|
||||
## - the message to sign or verify being the compressed or uncompressed public key
|
||||
## or another application-specific "hash_pubkey_to_point" scheme
|
||||
## - domain-separation-tag: "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"
|
||||
##
|
||||
## Constantine currently assumes that proof-of-possessions are handled at the application-level
|
||||
##
|
||||
## In proof-of-stake blockchains, being part of the staker/validator sets
|
||||
## already serve as proof-of-possession.
|
||||
|
||||
const DST = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"
|
||||
const ffi_prefix = "ctt_blssig_pop_on_bls12381_g2_"
|
||||
|
||||
{.push raises: [].} # No exceptions allowed in core cryptographic operations
|
||||
# {.push cdecl, dynlib, exportc:ffi_prefix & "$1".} # TODO, C API
|
||||
|
||||
type
|
||||
SecretKey* {.byref.} = object
|
||||
## A BLS12_381 secret key
|
||||
raw: matchingOrderBigInt(BLS12_381)
|
||||
|
||||
PublicKey* {.byref.} = object
|
||||
## A BLS12_381 public key for BLS signature schemes with public keys on G1 and signatures on G2
|
||||
raw: ECP_ShortW_Aff[Fp[BLS12_381], G1]
|
||||
|
||||
Signature* {.byref.} = object
|
||||
## A BLS12_381 signature for BLS signature schemes with public keys on G1 and signatures on G2
|
||||
raw: ECP_ShortW_Aff[Fp2[BLS12_381], G2]
|
||||
|
||||
CttBLSStatus* = enum
|
||||
cttBLS_Success
|
||||
cttBLS_VerificationFailure
|
||||
cttBLS_InvalidEncoding
|
||||
cttBLS_CoordinateGreaterOrEqualThanModulus
|
||||
cttBLS_PointAtInfinity
|
||||
cttBLS_PointNotOnCurve
|
||||
cttBLS_PointNotInSubgroup
|
||||
cttBLS_ZeroSecretKey
|
||||
cttBLS_SecretKeyLargerThanCurveOrder
|
||||
|
||||
# Comparisons
|
||||
# ------------------------------------------------------------------------------------------------
|
||||
|
||||
func isZero*(elem: PublicKey or Signature): bool =
|
||||
## Returns true if input is 0
|
||||
bool(elem.raw.isInf())
|
||||
|
||||
func `==`*(a, b: PublicKey or Signature): bool =
|
||||
## Returns true if inputs are equal
|
||||
bool(a.raw == b.raw)
|
||||
|
||||
# Input validation
|
||||
# ------------------------------------------------------------------------------------------------
|
||||
|
||||
func validate_seckey*(secret_key: SecretKey): CttBLSStatus =
|
||||
## Validate the secret key.
|
||||
## Regarding timing attacks, this will leak timing information only if the key is invalid.
|
||||
## Namely, the secret key is 0 or the secret key is too large.
|
||||
if secret_key.raw.isZero().bool():
|
||||
return cttBLS_ZeroSecretKey
|
||||
if bool(secret_key.raw >= BLS12_381.getCurveOrder()):
|
||||
return cttBLS_SecretKeyLargerThanCurveOrder
|
||||
return cttBLS_Success
|
||||
|
||||
func validate_pubkey*(public_key: PublicKey): CttBLSStatus =
|
||||
## Validate the public key.
|
||||
## This is an expensive operation that can be cached
|
||||
if public_key.raw.isInf().bool():
|
||||
return cttBLS_PointAtInfinity
|
||||
if not isOnCurve(public_key.raw.x, public_key.raw.y, G1).bool():
|
||||
return cttBLS_PointNotOnCurve
|
||||
if not public_key.raw.isInSubgroup().bool():
|
||||
return cttBLS_PointNotInSubgroup
|
||||
|
||||
func validate_sig*(signature: Signature): CttBLSStatus =
|
||||
## Validate the signature.
|
||||
## This is an expensive operation that can be cached
|
||||
if signature.raw.isInf().bool():
|
||||
return cttBLS_PointAtInfinity
|
||||
if not isOnCurve(signature.raw.x, signature.raw.y, G2).bool():
|
||||
return cttBLS_PointNotOnCurve
|
||||
if not signature.raw.isInSubgroup().bool():
|
||||
return cttBLS_PointNotInSubgroup
|
||||
|
||||
# Codecs
|
||||
# ------------------------------------------------------------------------------------------------
|
||||
|
||||
## BLS12-381 serialization
|
||||
##
|
||||
## 𝔽p elements are encoded in big-endian form. They occupy 48 bytes in this form.
|
||||
## 𝔽p2 elements are encoded in big-endian form, meaning that the 𝔽p2 element c0+c1u
|
||||
## is represented by the 𝔽p element c1 followed by the 𝔽p element c0.
|
||||
## This means 𝔽p2 elements occupy 96 bytes in this form.
|
||||
## The group 𝔾1 uses 𝔽p elements for coordinates. The group 𝔾2 uses 𝔽p2 elements for coordinates.
|
||||
## 𝔾1 and 𝔾2 elements can be encoded in uncompressed form (the x-coordinate followed by the y-coordinate) or in compressed form (just the x-coordinate).
|
||||
## 𝔾1 elements occupy 96 bytes in uncompressed form, and 48 bytes in compressed form.
|
||||
## 𝔾2 elements occupy 192 bytes in uncompressed form, and 96 bytes in compressed form.
|
||||
##
|
||||
## The most-significant three bits of a 𝔾1 or 𝔾2 encoding should be masked away before the coordinate(s) are interpreted. These bits are used to unambiguously represent the underlying element:
|
||||
##
|
||||
## The most significant bit, when set, indicates that the point is in compressed form. Otherwise, the point is in uncompressed form.
|
||||
## The second-most significant bit indicates that the point is at infinity. If this bit is set, the remaining bits of the group element’s encoding should be set to zero.
|
||||
## The third-most significant bit is set if (and only if) this point is in compressed form
|
||||
## and it is not the point at infinity and its y-coordinate is the lexicographically largest of the two associated with the encoded x-coordinate.
|
||||
##
|
||||
## - https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-04#appendix-A
|
||||
## - https://docs.rs/bls12_381/latest/bls12_381/notes/serialization/index.html
|
||||
## - https://github.com/zkcrypto/bls12_381/blob/0.6.0/src/notes/serialization.rs
|
||||
|
||||
func serialize_secret_key*(dst: var array[32, byte], secret_key: SecretKey): CttBLSStatus =
|
||||
## Serialize a secret key
|
||||
## Returns cttBLS_Success if successful
|
||||
dst.exportRawUint(secret_key.raw, bigEndian)
|
||||
return cttBLS_Success
|
||||
|
||||
func serialize_public_key_compressed*(dst: var array[48, byte], public_key: PublicKey): CttBLSStatus =
|
||||
## Serialize a public key in compressed (Zcash) format
|
||||
##
|
||||
## Returns cttBLS_Success if successful
|
||||
if public_key.raw.isInf().bool():
|
||||
for i in 0 ..< dst.len:
|
||||
dst[i] = byte 0
|
||||
dst[0] = byte 0b11000000 # Compressed + Infinity
|
||||
return cttBLS_Success
|
||||
|
||||
dst.exportRawUint(public_key.raw.x, bigEndian)
|
||||
# The curve equation has 2 solutions for y² = x³ + 4 with y unknown and x known
|
||||
# The lexicographically largest will have bit 381 set to 1
|
||||
# (and bit 383 for the compressed representation)
|
||||
# The solutions are {y, p-y} hence the lexicographyically largest is greater than p/2
|
||||
# so with exact integers, as p is odd, greater or equal (p+1)/2
|
||||
let lexicographicallyLargest = byte(public_key.raw.y.toBig() >= Fp[BLS12_381].getPrimePlus1div2())
|
||||
dst[0] = dst[0] or (0b10000000 or (lexicographicallyLargest shl 5))
|
||||
|
||||
return cttBLS_Success
|
||||
|
||||
func serialize_signature_compressed*(dst: var array[96, byte], signature: Signature): CttBLSStatus =
|
||||
## Serialize a signature in compressed (Zcash) format
|
||||
##
|
||||
## Returns cttBLS_Success if successful
|
||||
if signature.raw.isInf().bool():
|
||||
for i in 0 ..< dst.len:
|
||||
dst[i] = byte 0
|
||||
dst[0] = byte 0b11000000 # Compressed + Infinity
|
||||
return cttBLS_Success
|
||||
|
||||
dst.toOpenArray(0, 48-1).exportRawUint(signature.raw.x.c1, bigEndian)
|
||||
dst.toOpenArray(48, 96-1).exportRawUint(signature.raw.x.c0, bigEndian)
|
||||
|
||||
let isLexicographicallyLargest =
|
||||
if signature.raw.y.c1.isZero().bool():
|
||||
byte(signature.raw.y.c0.toBig() >= Fp[BLS12_381].getPrimePlus1div2())
|
||||
else:
|
||||
byte(signature.raw.y.c1.toBig() >= Fp[BLS12_381].getPrimePlus1div2())
|
||||
dst[0] = dst[0] or (byte 0b10000000 or (isLexicographicallyLargest shl 5))
|
||||
|
||||
return cttBLS_Success
|
||||
|
||||
func deserialize_secret_key*(dst: var SecretKey, src: array[32, byte]): CttBLSStatus =
|
||||
## deserialize a secret key
|
||||
##
|
||||
## This is protected against side-channel unless your key is invalid.
|
||||
## In that case it will like whether it's all zeros or larger than the curve order.
|
||||
dst.raw.fromRawUint(src, bigEndian)
|
||||
let status = validate_seckey(dst)
|
||||
if status != cttBLS_Success:
|
||||
dst.raw.setZero()
|
||||
return status
|
||||
return cttBLS_Success
|
||||
|
||||
func deserialize_public_key_compressed_unchecked*(dst: var PublicKey, src: array[48, byte]): CttBLSStatus =
|
||||
## Deserialize a public_key in compressed (Zcash) format.
|
||||
##
|
||||
## Warning ⚠:
|
||||
## This procedure skips the very expensive subgroup checks.
|
||||
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||
##
|
||||
## Returns cttBLS_Success if successful
|
||||
|
||||
# src must have the compressed flag
|
||||
if (src[0] and byte 0b10000000) == byte 0:
|
||||
return cttBLS_InvalidEncoding
|
||||
|
||||
# if infinity, src must be all zeros
|
||||
if (src[0] and byte 0b01000000) != 0:
|
||||
if (src[0] and byte 0b00111111) != 0: # Check all the remaining bytes in MSB
|
||||
return cttBLS_InvalidEncoding
|
||||
for i in 1 ..< src.len:
|
||||
if src[i] != byte 0:
|
||||
return cttBLS_InvalidEncoding
|
||||
dst.raw.setInf()
|
||||
return cttBLS_PointAtInfinity
|
||||
|
||||
# General case
|
||||
var t{.noInit.}: matchingBigInt(BLS12_381)
|
||||
t.fromRawUint(src, bigEndian)
|
||||
t.limbs[^1] = t.limbs[^1] and (MaxWord shr 3) # The first 3 bytes contain metadata to mask out
|
||||
|
||||
if bool(t >= BLS12_381.Mod()):
|
||||
return cttBLS_CoordinateGreaterOrEqualThanModulus
|
||||
|
||||
var x{.noInit.}: Fp[BLS12_381]
|
||||
x.fromBig(t)
|
||||
|
||||
let onCurve = dst.raw.trySetFromCoordX(x)
|
||||
if not(bool onCurve):
|
||||
return cttBLS_PointNotOnCurve
|
||||
|
||||
let isLexicographicallyLargest = dst.raw.y.toBig() >= Fp[BLS12_381].getPrimePlus1div2()
|
||||
let srcIsLargest = SecretBool((src[0] shr 5) and byte 1)
|
||||
dst.raw.y.cneg(isLexicographicallyLargest xor srcIsLargest)
|
||||
|
||||
func deserialize_public_key_compressed*(dst: var PublicKey, src: array[48, byte]): CttBLSStatus =
|
||||
## Deserialize a public_key in compressed (Zcash) format
|
||||
##
|
||||
## Returns cttBLS_Success if successful
|
||||
|
||||
result = deserialize_public_key_compressed_unchecked(dst, src)
|
||||
if result != cttBLS_Success:
|
||||
return result
|
||||
|
||||
if not(bool dst.raw.isInSubgroup):
|
||||
return cttBLS_PointNotInSubgroup
|
||||
|
||||
func deserialize_signature_compressed_unchecked*(dst: var Signature, src: array[96, byte]): CttBLSStatus =
|
||||
## Deserialize a signature in compressed (Zcash) format.
|
||||
##
|
||||
## Warning ⚠:
|
||||
## This procedure skips the very expensive subgroup checks.
|
||||
## Not checking subgroup exposes a protocol to small subgroup attacks.
|
||||
##
|
||||
## Returns cttBLS_Success if successful
|
||||
|
||||
# src must have the compressed flag
|
||||
if (src[0] and byte 0b10000000) == byte 0:
|
||||
return cttBLS_InvalidEncoding
|
||||
|
||||
# if infinity, src must be all zeros
|
||||
if (src[0] and byte 0b01000000) != 0:
|
||||
if (src[0] and byte 0b00111111) != 0: # Check all the remaining bytes in MSB
|
||||
return cttBLS_InvalidEncoding
|
||||
for i in 1 ..< src.len:
|
||||
if src[i] != byte 0:
|
||||
return cttBLS_InvalidEncoding
|
||||
dst.raw.setInf()
|
||||
return cttBLS_PointAtInfinity
|
||||
|
||||
# General case
|
||||
var t{.noInit.}: matchingBigInt(BLS12_381)
|
||||
t.fromRawUint(src.toOpenArray(0, 48-1), bigEndian)
|
||||
t.limbs[^1] = t.limbs[^1] and (MaxWord shr 3) # The first 3 bytes contain metadata to mask out
|
||||
|
||||
if bool(t >= BLS12_381.Mod()):
|
||||
return cttBLS_CoordinateGreaterOrEqualThanModulus
|
||||
|
||||
var x{.noInit.}: Fp2[BLS12_381]
|
||||
x.c1.fromBig(t)
|
||||
|
||||
t.fromRawUint(src.toOpenArray(48, 96-1), bigEndian)
|
||||
if bool(t >= BLS12_381.Mod()):
|
||||
return cttBLS_CoordinateGreaterOrEqualThanModulus
|
||||
|
||||
x.c0.fromBig(t)
|
||||
|
||||
let onCurve = dst.raw.trySetFromCoordX(x)
|
||||
if not(bool onCurve):
|
||||
return cttBLS_PointNotOnCurve
|
||||
|
||||
let isLexicographicallyLargest =
|
||||
if dst.raw.y.c1.isZero().bool():
|
||||
dst.raw.y.c0.toBig() >= Fp[BLS12_381].getPrimePlus1div2()
|
||||
else:
|
||||
dst.raw.y.c1.toBig() >= Fp[BLS12_381].getPrimePlus1div2()
|
||||
|
||||
let srcIsLargest = SecretBool((src[0] shr 5) and byte 1)
|
||||
dst.raw.y.cneg(isLexicographicallyLargest xor srcIsLargest)
|
||||
|
||||
func deserialize_signature_compressed*(dst: var Signature, src: array[96, byte]): CttBLSStatus =
|
||||
## Deserialize a public_key in compressed (Zcash) format
|
||||
##
|
||||
## Returns cttBLS_Success if successful
|
||||
|
||||
result = deserialize_signature_compressed_unchecked(dst, src)
|
||||
if result != cttBLS_Success:
|
||||
return result
|
||||
|
||||
if not(bool dst.raw.isInSubgroup):
|
||||
return cttBLS_PointNotInSubgroup
|
||||
|
||||
# Signatures
|
||||
# ------------------------------------------------------------------------------------------------
|
||||
|
||||
func derive_public_key*(public_key: var PublicKey, secret_key: SecretKey): CttBLSStatus =
|
||||
## Derive the public key matching with a secret key
|
||||
##
|
||||
## Secret protection:
|
||||
## - A valid secret key will only leak that it is valid.
|
||||
## - An invalid secret key will leak whether it's all zero or larger than the curve order.
|
||||
let status = validate_seckey(secret_key)
|
||||
if status != cttBLS_Success:
|
||||
return status
|
||||
|
||||
let ok = public_key.raw.derivePubkey(secret_key.raw)
|
||||
if not ok:
|
||||
# This is unreachable since validate_seckey would have caught those
|
||||
return cttBLS_InvalidEncoding
|
||||
return cttBLS_Success
|
||||
|
||||
func sign*[T: byte|char](signature: var Signature, secret_key: SecretKey, message: openArray[T]): CttBLSStatus =
|
||||
## Produce a signature for the message under the specified secret key
|
||||
## Signature is on BLS12-381 G2 (and public key on G1)
|
||||
##
|
||||
## For message domain separation purpose, the tag is `BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_`
|
||||
##
|
||||
## Input:
|
||||
## - A secret key
|
||||
## - A message
|
||||
##
|
||||
## Output:
|
||||
## - `signature` is overwritten with `message` signed with `secretKey`
|
||||
## with the scheme
|
||||
## - A status code indicating success or if the secret key is invalid.
|
||||
##
|
||||
## Secret protection:
|
||||
## - A valid secret key will only leak that it is valid.
|
||||
## - An invalid secret key will leak whether it's all zero or larger than the curve order.
|
||||
let status = validate_seckey(secret_key)
|
||||
if status != cttBLS_Success:
|
||||
signature.raw.setInf()
|
||||
return status
|
||||
|
||||
coreSign(signature.raw, secretKey.raw, message, sha256, 128, augmentation = "", DST)
|
||||
return cttBLS_Success
|
||||
|
||||
func verify*[T: byte|char](public_key: PublicKey, message: openarray[T], signature: Signature): CttBLSStatus =
|
||||
## Check that a signature is valid for a message
|
||||
## under the provided public key.
|
||||
## returns `true` if the signature is valid, `false` otherwise.
|
||||
##
|
||||
## For message domain separation purpose, the tag is `BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_`
|
||||
##
|
||||
## Input:
|
||||
## - A public key initialized by one of the key derivation or deserialization procedure.
|
||||
## Or validated via validate_pubkey
|
||||
## - A message
|
||||
## - A signature initialized by one of the key derivation or deserialization procedure.
|
||||
## Or validated via validate_pubkey
|
||||
##
|
||||
## In particular, the public key and signature are assumed to be on curve subgroup checked.
|
||||
|
||||
# Deal with cases were pubkey or signature were mistakenly zero-init, due to a generic aggregation tentative for example
|
||||
if bool(public_key.raw.isInf() or signature.raw.isInf()):
|
||||
return cttBLS_PointAtInfinity
|
||||
|
||||
let verified = coreVerify(public_key.raw, message, signature.raw, sha256, 128, augmentation = "", DST)
|
||||
if verified:
|
||||
return cttBLS_Success
|
||||
return cttBLS_VerificationFailure
|
||||
@ -0,0 +1,4 @@
|
||||
# BLS signature on BLS12-381 G2 tests
|
||||
|
||||
Source: https://github.com/ethereum/bls12-381-tests
|
||||
version 0.1.1 at https://github.com/ethereum/bls12-381-tests/releases/tag/v0.1.1
|
||||
@ -0,0 +1 @@
|
||||
{"input": ["0xb6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55", "0xb23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9", "0x948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115"], "output": "0x9683b3e6701f9a4b706709577963110043af78a5b41991b998475a3d3fd62abf35ce03b33908418efc95a058494a8ae504354b9f626231f6b3f3c849dfdeaf5017c4780e2aee1850ceaf4b4d9ce70971a3d2cfcd97b7e5ecf6759f8da5f76d31"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": ["0x882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972503a43eb", "0xaf1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363272ba4fe", "0xa4efa926610b8bd1c8330c918b7a5e9bf374e53435ef8b7ec186abf62e1b1f65aeaaeb365677ac1d1172a1f5b44b4e6d022c252c58486c0a759fbdc7de15a756acc4d343064035667a594b4c2a6f0b0b421975977f297dba63ee2f63ffe47bb6"], "output": "0xad38fc73846583b08d110d16ab1d026c6ea77ac2071e8ae832f56ac0cbcdeb9f5678ba5ce42bd8dce334cc47b5abcba40a58f7f1f80ab304193eb98836cc14d8183ec14cc77de0f80c4ffd49e168927a968b5cdaa4cf46b9805be84ad7efa77b"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": ["0x91347bccf740d859038fcdcaf233eeceb2a436bcaaee9b2aa3bfb70efe29dfb2677562ccbea1c8e061fb9971b0753c240622fab78489ce96768259fc01360346da5b9f579e5da0d941e4c6ba18a0e64906082375394f337fa1af2b7127b0d121", "0x9674e2228034527f4c083206032b020310face156d4a4685e2fcaec2f6f3665aa635d90347b6ce124eb879266b1e801d185de36a0a289b85e9039662634f2eea1e02e670bc7ab849d006a70b2f93b84597558a05b879c8d445f387a5d5b653df", "0xae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9975e4eb9"], "output": "0x9712c3edd73a209c742b8250759db12549b3eaf43b5ca61376d9f30e2747dbcf842d8b2ac0901d2a093713e20284a7670fcf6954e9ab93de991bb9b313e664785a075fc285806fa5224c82bde146561b446ccfc706a64b8579513cfc4ff1d930"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": ["0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], "output": "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": [], "output": null}
|
||||
@ -0,0 +1 @@
|
||||
{"input": ["0xb6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55"], "output": "0xb6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", "0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f", "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], "messages": ["0x0000000000000000000000000000000000000000000000000000000000000000", "0x5656565656565656565656565656565656565656565656565656565656565656", "0xabababababababababababababababababababababababababababababababab", "0x1212121212121212121212121212121212121212121212121212121212121212"], "signature": "0x9104e74b9dfd3ad502f25d6a5ef57db0ed7d9a0e00f3500586d8ce44231212542fcfaf87840539b398bf07626705cf1105d246ca1062c6c2e1a53029a0f790ed5e3cb1f52f8234dc5144c45fc847c0cd37a92d68e7c5ba7c648a8a339f171244"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": [], "messages": [], "signature": "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": [], "messages": [], "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", "0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f"], "messages": ["0x0000000000000000000000000000000000000000000000000000000000000000", "0x5656565656565656565656565656565656565656565656565656565656565656", "0xabababababababababababababababababababababababababababababababab"], "signature": "0x9104e74bffffffff"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", "0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f"], "messages": ["0x0000000000000000000000000000000000000000000000000000000000000000", "0x5656565656565656565656565656565656565656565656565656565656565656", "0xabababababababababababababababababababababababababababababababab"], "signature": "0x9104e74b9dfd3ad502f25d6a5ef57db0ed7d9a0e00f3500586d8ce44231212542fcfaf87840539b398bf07626705cf1105d246ca1062c6c2e1a53029a0f790ed5e3cb1f52f8234dc5144c45fc847c0cd37a92d68e7c5ba7c648a8a339f171244"}, "output": true}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81"], "messages": ["0x0000000000000000000000000000000000000000000000000000000000000000", "0x5656565656565656565656565656565656565656565656565656565656565656"], "signatures": ["0xa70f1f1b4bd97d182ebb55d08be3f90b1dc232bb50b44e259381a642ef0bad3629ad3542f3e8ff6a84e451fc0b595e090fc4f0e860cfc5584715ef1b6cd717b9994378f7a51b815bbf5a0d95bc3402583ad2e95a229731e539906249a5e4355c", "0xb758eb7e15c101f53be2214d2a6b65e8fe7053146dbe3c73c9fe9b5efecdf63ca06a4d5d938dbf18fe6600529c0011a7013f45ae012b02904d5c7c33316e935a0e084abead4f43f84383c52cd3b3f14024437e251a2a7c0d5147954022873a58"]}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", "0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f"], "messages": ["0x0000000000000000000000000000000000000000000000000000000000000000", "0x5656565656565656565656565656565656565656565656565656565656565656", "0xabababababababababababababababababababababababababababababababab"], "signatures": ["0xb6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55", "0xaf1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363272ba4fe", "0xae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9975e4eb9"]}, "output": true}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "8123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "8123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde0"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaa900"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "c123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "a491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a"}, "output": true}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": true}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "c01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "8123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "8123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde0"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "8123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "8123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefff"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "c123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaac"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "b2cc74bc9f089ed9764bbceac5edba416bef5e73701288977b9cac1ccb6964269d4ebf78b4e8aa7792ba09d3e49c8e6a1351bdf582971f796bbaf6320e81251c9d28f674d720cca07ed14596b96697cf18238e0e03ebd7fc1353d885a39407e0"}, "output": true}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"signature": "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": true}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", "0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f"], "message": "0x5656565656565656565656565656565656565656565656565656565656565656", "signature": "0x912c3615f69575407db9392eb21fee18fff797eeb2fbe1816366ca2a08ae574d8824dbfafb4c9eaa1cf61b63c6f9b69911f269b664c42947dd1b53ef1081926c1e82bb2a465f927124b08391a5249036146d6f3f1e17ff5f162f779746d830d1"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", "0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f", "0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f"], "message": "0xabababababababababababababababababababababababababababababababab", "signature": "0x9712c3edd73a209c742b8250759db12549b3eaf43b5ca61376d9f30e2747dbcf842d8b2ac0901d2a093713e20284a7670fcf6954e9ab93de991bb9b313e664785a075fc285806fa5224c82bde146561b446ccfc706a64b8579513cfc4ff1d930"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f"], "message": "0x0000000000000000000000000000000000000000000000000000000000000000", "signature": "0xb6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", "0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f", "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], "message": "0x1212121212121212121212121212121212121212121212121212121212121212", "signature": "0xafcb4d980f079265caa61aee3e26bf48bebc5dc3e7f2d7346834d76cbc812f636c937b6b44a9323d8bc4b1cdf71d6811035ddc2634017faab2845308f568f2b9a0356140727356eae9eded8b87fd8cb8024b440c57aee06076128bb32921f584"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": [], "message": "0xabababababababababababababababababababababababababababababababab", "signature": "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": [], "message": "0xabababababababababababababababababababababababababababababababab", "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", "0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f"], "message": "0xabababababababababababababababababababababababababababababababab", "signature": "0x9712c3edd73a209c742b8250759db12549b3eaf43b5ca61376d9f30e2747dbcf842d8b2ac0901d2a093713e20284a7670fcf6954e9ab93de991bb9b313e664785a075fc285806fa5224c82bde146561b446ccfc706a64b8579513cfcffffffff"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a"], "message": "0x0000000000000000000000000000000000000000000000000000000000000000", "signature": "0xb6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380bffffffff"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81"], "message": "0x5656565656565656565656565656565656565656565656565656565656565656", "signature": "0x912c3615f69575407db9392eb21fee18fff797eeb2fbe1816366ca2a08ae574d8824dbfafb4c9eaa1cf61b63c6f9b69911f269b664c42947dd1b53ef1081926c1e82bb2a465f927124b08391a5249036146d6f3f1e17ff5f162f7797ffffffff"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", "0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f"], "message": "0xabababababababababababababababababababababababababababababababab", "signature": "0x9712c3edd73a209c742b8250759db12549b3eaf43b5ca61376d9f30e2747dbcf842d8b2ac0901d2a093713e20284a7670fcf6954e9ab93de991bb9b313e664785a075fc285806fa5224c82bde146561b446ccfc706a64b8579513cfc4ff1d930"}, "output": true}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a"], "message": "0x0000000000000000000000000000000000000000000000000000000000000000", "signature": "0xb6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55"}, "output": true}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkeys": ["0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81"], "message": "0x5656565656565656565656565656565656565656565656565656565656565656", "signature": "0x912c3615f69575407db9392eb21fee18fff797eeb2fbe1816366ca2a08ae574d8824dbfafb4c9eaa1cf61b63c6f9b69911f269b664c42947dd1b53ef1081926c1e82bb2a465f927124b08391a5249036146d6f3f1e17ff5f162f779746d830d1"}, "output": true}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, "output": {"x": "0x01a6ba2f9a11fa5598b2d8ace0fbe0a0eacb65deceb476fbbcb64fd24557c2f4b18ecfc5663e54ae16a84f5ab7f62534,0x11fca2ff525572795a801eed17eb12785887c7b63fb77a42be46ce4a34131d71f7a73e95fee3f812aea3de78b4d01569", "y": "0x0b6798718c8aed24bc19cb27f866f1c9effcdbf92397ad6448b5c9db90d2b9da6cbabf48adc1adf59a1a28344e79d57e,0x03a47f8e6d1763ba0cad63d6114c0accbef65707825a511b251a660a9b3994249ae4e63fac38b23da0c398689ee2ab52"}}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"msg": "abc"}, "output": {"x": "0x02c2d18e033b960562aae3cab37a27ce00d80ccd5ba4b7fe0e7a210245129dbec7780ccc7954725f4168aff2787776e6,0x139cddbccdc5e91b9623efd38c49f81a6f83f175e80b06fc374de9eb4b41dfe4ca3a230ed250fbe3a2acf73a41177fd8", "y": "0x1787327b68159716a37440985269cf584bcb1e621d3a7202be6ea05c4cfe244aeb197642555a0645fb87bf7466b2ba48,0x00aa65dae3c8d732d10ecd2c50f8a1baf3001578f71c694e03866e9f3d49ac1e1ce70dd94a733534f106d4cec0eddd16"}}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"msg": ""}, "output": {"x": "0x0141ebfbdca40eb85b87142e130ab689c673cf60f1a3e98d69335266f30d9b8d4ac44c1038e9dcdd5393faf5c41fb78a,0x05cb8437535e20ecffaef7752baddf98034139c38452458baeefab379ba13dff5bf5dd71b72418717047f5b0f37da03d", "y": "0x0503921d7f6a12805e72940b963c0cf3471c7b2a524950ca195d11062ee75ec076daf2d4bc358c4b190c0c98064fdd92,0x12424ac32561493f3fe3c260708a12b7c620e7be00099a974e259ddc7d1f6395c3c811cdd19f1e8dbf3e9ecfdcbab8d6"}}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"msg": "abcdef0123456789"}, "output": {"x": "0x121982811d2491fde9ba7ed31ef9ca474f0e1501297f68c298e9f4c0028add35aea8bb83d53c08cfc007c1e005723cd0,0x190d119345b94fbd15497bcba94ecf7db2cbfd1e1fe7da034d26cbba169fb3968288b3fafb265f9ebd380512a71c3f2c", "y": "0x05571a0f8d3c08d094576981f4a3b8eda0a8e771fcdcc8ecceaf1356a6acf17574518acb506e435b639353c2e14827c8,0x0bb5e7572275c567462d91807de765611490205a941a5a6af3b1691bfe596c31225d3aabdf15faff860cb4ef17c7c3be"}}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"privkey": "0x47b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665138", "message": "0x0000000000000000000000000000000000000000000000000000000000000000"}, "output": "0xb23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dc6df96d9"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"privkey": "0x47b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665138", "message": "0x5656565656565656565656565656565656565656565656565656565656565656"}, "output": "0xaf1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363272ba4fe"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"privkey": "0x47b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665138", "message": "0xabababababababababababababababababababababababababababababababab"}, "output": "0x9674e2228034527f4c083206032b020310face156d4a4685e2fcaec2f6f3665aa635d90347b6ce124eb879266b1e801d185de36a0a289b85e9039662634f2eea1e02e670bc7ab849d006a70b2f93b84597558a05b879c8d445f387a5d5b653df"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"privkey": "0x328388aff0d4a5b7dc9205abd374e7e98f3cd9f3418edb4eafda5fb16473d216", "message": "0x0000000000000000000000000000000000000000000000000000000000000000"}, "output": "0x948a7cb99f76d616c2c564ce9bf4a519f1bea6b0a624a02276443c245854219fabb8d4ce061d255af5330b078d5380681751aa7053da2c98bae898edc218c75f07e24d8802a17cd1f6833b71e58f5eb5b94208b4d0bb3848cecb075ea21be115"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"privkey": "0x328388aff0d4a5b7dc9205abd374e7e98f3cd9f3418edb4eafda5fb16473d216", "message": "0xabababababababababababababababababababababababababababababababab"}, "output": "0xae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9975e4eb9"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"privkey": "0x328388aff0d4a5b7dc9205abd374e7e98f3cd9f3418edb4eafda5fb16473d216", "message": "0x5656565656565656565656565656565656565656565656565656565656565656"}, "output": "0xa4efa926610b8bd1c8330c918b7a5e9bf374e53435ef8b7ec186abf62e1b1f65aeaaeb365677ac1d1172a1f5b44b4e6d022c252c58486c0a759fbdc7de15a756acc4d343064035667a594b4c2a6f0b0b421975977f297dba63ee2f63ffe47bb6"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"privkey": "0x263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3", "message": "0x0000000000000000000000000000000000000000000000000000000000000000"}, "output": "0xb6ed936746e01f8ecf281f020953fbf1f01debd5657c4a383940b020b26507f6076334f91e2366c96e9ab279fb5158090352ea1c5b0c9274504f4f0e7053af24802e51e4568d164fe986834f41e55c8e850ce1f98458c0cfc9ab380b55285a55"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"privkey": "0x263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3", "message": "0x5656565656565656565656565656565656565656565656565656565656565656"}, "output": "0x882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972503a43eb"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"privkey": "0x263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3", "message": "0xabababababababababababababababababababababababababababababababab"}, "output": "0x91347bccf740d859038fcdcaf233eeceb2a436bcaaee9b2aa3bfb70efe29dfb2677562ccbea1c8e061fb9971b0753c240622fab78489ce96768259fc01360346da5b9f579e5da0d941e4c6ba18a0e64906082375394f337fa1af2b7127b0d121"}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"privkey": "0x0000000000000000000000000000000000000000000000000000000000000000", "message": "0xabababababababababababababababababababababababababababababababab"}, "output": null}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "message": "0x1212121212121212121212121212121212121212121212121212121212121212", "signature": "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f", "message": "0xabababababababababababababababababababababababababababababababab", "signature": "0xae82747ddeefe4fd64cf9cedb9b04ae3e8a43420cd255e3c7cd06a8d88b7c7f8638543719981c5d16fa3527c468c25f0026704a6951bde891360c7e8d12ddee0559004ccdbe6046b55bae1b257ee97f7cdb955773d7cf29adf3ccbb9ffffffff"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a", "message": "0x5656565656565656565656565656565656565656565656565656565656565656", "signature": "0x882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972ffffffff"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", "message": "0x0000000000000000000000000000000000000000000000000000000000000000", "signature": "0xb23c46be3a001c63ca711f87a005c200cc550b9429d5f4eb38d74322144f1b63926da3388979e5321012fb1a0526bcd100b5ef5fe72628ce4cd5e904aeaa3279527843fae5ca9ca675f4f51ed8f83bbf7155da9ecc9663100a885d5dffffffff"}, "output": false}
|
||||
@ -0,0 +1 @@
|
||||
{"input": {"pubkey": "0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", "message": "0x5656565656565656565656565656565656565656565656565656565656565656", "signature": "0xaf1390c3c47acdb37131a51216da683c509fce0e954328a59f93aebda7e4ff974ba208d9a4a2a2389f892a9d418d618418dd7f7a6bc7aa0da999a9d3a5b815bc085e14fd001f6a1948768a3f4afefc8b8240dda329f984cb345c6363ffffffff"}, "output": false}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user