From 3878b9bf324fd895f07f2c3a07622fac7c939e21 Mon Sep 17 00:00:00 2001 From: Mamy Ratsimbazafy Date: Mon, 26 Oct 2020 21:08:02 +0100 Subject: [PATCH] BLS signature v4 (#91) * Update vectors to BLSv4 v1.0.0-rc0 [skip ci] * Workaround https://github.com/ethereum/eth2.0-spec-tests/issues/22, https://github.com/ethereum/eth2.0-specs/pull/2099 * Rework BLSv4 API https://github.com/ethereum/eth2.0-specs/pull/2080 and address https://github.com/status-im/nim-blscurve/issues/76 https://github.com/status-im/nim-blscurve/issues/77 * Upgade Milagro vectors * Upgrade BLST backend with new API * BLST forgot to return true for publicFromSecret --- blscurve.nim | 3 +- blscurve/bls_backend.nim | 4 +- blscurve/blst/bls_sig_min_pubkey_size_pop.nim | 55 +++--- blscurve/eth2_keygen/hkdf_mod_r_blst.nim | 3 +- blscurve/eth2_keygen/hkdf_mod_r_miracl.nim | 8 +- blscurve/miracl/bls_sig_io.nim | 16 ++ blscurve/miracl/bls_signature_scheme.nim | 124 ++++++++++--- blscurve/miracl/common.nim | 4 + .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../aggregate_infinity_signature/data.yaml | 2 + .../small/aggregate_na_signatures}/data.yaml | 0 .../data.yaml | 10 + .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../small/aggregate_verify_valid/data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 8 + .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../sign_case_11b8c7cad5238946/data.yaml | 0 .../sign_case_142f678a8d05fcd1/data.yaml | 0 .../sign_case_37286e1a6d1f6eb3/data.yaml | 0 .../sign_case_7055381f640f2c1d/data.yaml | 0 .../sign_case_84d45c9c7cca6b92/data.yaml | 0 .../sign_case_8cd3d4d0d9a5b265/data.yaml | 0 .../sign_case_c82df61aa3ee60fb/data.yaml | 0 .../sign_case_d0e28d7e76eb6e9c/data.yaml | 0 .../sign_case_f2ae1097e7d0e18b/data.yaml | 0 .../small/sign_case_zero_privkey/data.yaml | 3 + .../data.yaml | 4 +- .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 .../data.yaml | 0 tests/eth2_vectors.nim | 175 +++++++++--------- tests/priv_to_pub.nim | 8 +- tests/test_locator.nim | 2 +- 71 files changed, 281 insertions(+), 148 deletions(-) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/aggregate/small/aggregate_0x0000000000000000000000000000000000000000000000000000000000000000/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/aggregate/small/aggregate_0x5656565656565656565656565656565656565656565656565656565656565656/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/aggregate/small/aggregate_0xabababababababababababababababababababababababababababababababab/data.yaml (100%) create mode 100644 tests/eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_infinity_signature/data.yaml rename tests/{eth2.0_v0.12.0_vectors/aggregate/small/aggregate_na_pubkeys => eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_na_signatures}/data.yaml (100%) create mode 100644 tests/eth2.0_v1.0.0-rc0_vectors/aggregate_verify/small/aggregate_verify_infinity_pubkey/data.yaml rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/aggregate_verify/small/aggregate_verify_na_pubkeys_and_infinity_signature/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/aggregate_verify/small/aggregate_verify_na_pubkeys_and_na_signature/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/aggregate_verify/small/aggregate_verify_tampered_signature/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/aggregate_verify/small/aggregate_verify_valid/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_4f079f946446fabf/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_5a38e6b4017fe4dd/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_a698ea45b109f303/data.yaml (100%) create mode 100644 tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_infinity_pubkey/data.yaml rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/fast_aggregate_verify/small/fast_aggregate_verify_na_pubkeys_and_infinity_signature/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/fast_aggregate_verify/small/fast_aggregate_verify_na_pubkeys_and_na_signature/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_3d7576f3c0e3570a/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_5e745ad0c6199a6c/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_652ce62f09290811/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/fast_aggregate_verify/small/fast_aggregate_verify_valid_3d7576f3c0e3570a/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/fast_aggregate_verify/small/fast_aggregate_verify_valid_5e745ad0c6199a6c/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/fast_aggregate_verify/small/fast_aggregate_verify_valid_652ce62f09290811/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/sign/small/sign_case_11b8c7cad5238946/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/sign/small/sign_case_142f678a8d05fcd1/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/sign/small/sign_case_37286e1a6d1f6eb3/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/sign/small/sign_case_7055381f640f2c1d/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/sign/small/sign_case_84d45c9c7cca6b92/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/sign/small/sign_case_8cd3d4d0d9a5b265/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/sign/small/sign_case_c82df61aa3ee60fb/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/sign/small/sign_case_d0e28d7e76eb6e9c/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/sign/small/sign_case_f2ae1097e7d0e18b/data.yaml (100%) create mode 100644 tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_zero_privkey/data.yaml rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_infinity_pubkey_and_infinity_signature/data.yaml (66%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_tampered_signature_case_195246ee3bd3b6ec/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_tampered_signature_case_2ea479adf8c40300/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_tampered_signature_case_2f09d443ab8a3ac2/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_tampered_signature_case_3208262581c8fc09/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_tampered_signature_case_6b3b17f6962a490c/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_tampered_signature_case_6eeb7c52dfd9baf0/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_tampered_signature_case_8761a0b7e920c323/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_tampered_signature_case_d34885d766d5f705/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_tampered_signature_case_e8a50c445c855360/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_valid_case_195246ee3bd3b6ec/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_valid_case_2ea479adf8c40300/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_valid_case_2f09d443ab8a3ac2/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_valid_case_3208262581c8fc09/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_valid_case_6b3b17f6962a490c/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_valid_case_6eeb7c52dfd9baf0/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_valid_case_8761a0b7e920c323/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_valid_case_d34885d766d5f705/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_valid_case_e8a50c445c855360/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_wrong_pubkey_case_195246ee3bd3b6ec/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_wrong_pubkey_case_2ea479adf8c40300/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_wrong_pubkey_case_2f09d443ab8a3ac2/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_wrong_pubkey_case_3208262581c8fc09/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_wrong_pubkey_case_6b3b17f6962a490c/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_wrong_pubkey_case_6eeb7c52dfd9baf0/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_wrong_pubkey_case_8761a0b7e920c323/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_wrong_pubkey_case_d34885d766d5f705/data.yaml (100%) rename tests/{eth2.0_v0.12.0_vectors => eth2.0_v1.0.0-rc0_vectors}/verify/small/verify_wrong_pubkey_case_e8a50c445c855360/data.yaml (100%) diff --git a/blscurve.nim b/blscurve.nim index f82111c..edde112 100644 --- a/blscurve.nim +++ b/blscurve.nim @@ -7,8 +7,7 @@ # This file may not be copied, modified, or distributed except according to # those terms. -const BLS_ETH2_SPEC* = "v0.12.x (deprecated)" - +const BLS_ETH2_SPEC* = "v1.0.0-rc0" import blscurve/bls_backend, blscurve/keygen_eip2333 diff --git a/blscurve/bls_backend.nim b/blscurve/bls_backend.nim index 11b9882..43870ee 100644 --- a/blscurve/bls_backend.nim +++ b/blscurve/bls_backend.nim @@ -48,7 +48,7 @@ else: SecretKey, PublicKey, Signature, ProofOfPossession, AggregateSignature, `==`, - init, aggregate, finish, + init, aggregate, finish, aggregateAll, sign, verify, aggregateVerify, fastAggregateVerify, - privToPub, + publicFromSecret, isZero, fromHex, fromBytes, toHex, serialize, exportRaw diff --git a/blscurve/blst/bls_sig_min_pubkey_size_pop.nim b/blscurve/blst/bls_sig_min_pubkey_size_pop.nim index 1a56167..445f036 100644 --- a/blscurve/blst/bls_sig_min_pubkey_size_pop.nim +++ b/blscurve/blst/bls_sig_min_pubkey_size_pop.nim @@ -148,24 +148,27 @@ func fromBytes*( return false let pa = cast[ptr array[L, byte]](raw[0].unsafeAddr) result = obj.point.blst_p1_uncompress(pa[]) == BLST_SUCCESS + if obj.vec_is_zero(): + return false func fromBytes*( obj: var SecretKey, raw: openarray[byte] or array[32, byte] ): bool {.inline.} = - ## Initialize a BLS signature scheme object from + ## Initialize a BLS secret key from ## its raw bytes representation. ## Returns true on success and false otherwise const L = 32 when raw is array: obj.scalar.blst_scalar_from_bendian(raw) - return true else: if raw.len != 32: return false let pa = cast[ptr array[L, byte]](raw[0].unsafeAddr) obj.scalar.blst_scalar_from_bendian(pa[]) - return true + if obj.vec_is_zero(): + return false + return true func fromHex*( obj: var (SecretKey|PublicKey|Signature|ProofOfPossession), @@ -229,15 +232,18 @@ func exportRaw*(signature: Signature): array[96, byte] {.inline.}= # Primitives # ---------------------------------------------------------------------- -func privToPub*(secretKey: SecretKey): PublicKey {.inline.} = +func publicFromSecret*(pubkey: var PublicKey, seckey: SecretKey): bool = ## Generates a public key from a secret key ## Generates a public key from a secret key ## This requires some -O3 compiler optimizations to be off - ## as such {.passC: "-fno-peel-loops -fno-tree-loop-vectorize".} - ## is automatically added to the compiler flags + ## as such {.passC: "-fno-tree-vectorize".} + ## is automatically added to the compiler flags in blst_lowlevel + if seckey.vec_is_zero(): + return false var pk {.noInit.}: blst_p1 - pk.blst_sk_to_pk_in_g1(secretKey.scalar) - result.point.blst_p1_to_affine(pk) + pk.blst_sk_to_pk_in_g1(seckey.scalar) + pubkey.point.blst_p1_to_affine(pk) + return true # Aggregate # ---------------------------------------------------------------------- @@ -248,6 +254,7 @@ func init*(agg: var AggregateSignature, sig: Signature) {.inline.} = func aggregate*(agg: var AggregateSignature, sig: Signature) {.inline.} = ## Aggregates signature ``sig`` into ``agg`` + # Precondition n >= 1 is respected agg.point.blst_p2_add_or_double_affine( agg.point, sig.point @@ -255,6 +262,7 @@ func aggregate*(agg: var AggregateSignature, sig: Signature) {.inline.} = proc aggregate*(agg: var AggregateSignature, sigs: openarray[Signature]) = ## Aggregates an array of signatures `sigs` into a signature `sig` + # Precondition n >= 1 is respected even if sigs.len == 0 for s in sigs: agg.point.blst_p2_add_or_double_affine( agg.point, @@ -265,18 +273,22 @@ proc finish*(sig: var Signature, agg: AggregateSignature) {.inline.} = ## Canonicalize the AggregateSignature into a Signature sig.point.blst_p2_to_affine(agg.point) -proc aggregate*(sigs: openarray[Signature]): Signature = - ## Aggregates array of signatures ``sigs`` - ## and return aggregated signature. - ## +proc aggregateAll*(dst: var Signature, sigs: openarray[Signature]): bool = + ## Returns the aggregate signature of ``sigs[0.. 0) + ## + ## Returns false if `sigs` is the empty array + ## and true otherwise + if len(sigs) == 0: + return false var agg{.noInit.}: AggregateSignature agg.init(sigs[0]) agg.aggregate(sigs.toOpenArray(1, sigs.high)) - result.finish(agg) + dst.finish(agg) + return true # Core operations # ---------------------------------------------------------------------- @@ -322,13 +334,6 @@ func coreVerify[T: byte|char]( domainSepTag: static string): bool {.inline.} = ## Check that a signature (or proof-of-possession) is valid ## for a message (or serialized publickey) under the provided public key - - # TODO - # ETH2~BLST difference https://github.com/supranational/blst/issues/11 - if publicKey.point.vec_is_zero() and - sig_or_proof.point.vec_is_zero(): - return true - result = BLST_SUCCESS == blst_core_verify_pk_in_g1( publicKey.point, sig_or_proof.point, @@ -470,7 +475,9 @@ func popProve*(secretKey: SecretKey): ProofOfPossession = # 4. R = SK * Q # 5. proof = point_to_signature(R) # 6. return proof - let pubkey = privToPub(secretKey) + var pubkey {.noInit.}: PublicKey + let ok {.used.} = pubkey.publicFromSecret(secretKey) + assert ok, "The secret key is INVALID, it should be initialized non-zero with keyGen or derive_child_secretKey" result = popProve(secretKey, pubkey) func popVerify*(publicKey: PublicKey, proof: ProofOfPossession): bool = diff --git a/blscurve/eth2_keygen/hkdf_mod_r_blst.nim b/blscurve/eth2_keygen/hkdf_mod_r_blst.nim index e6fa179..d1f8dd5 100644 --- a/blscurve/eth2_keygen/hkdf_mod_r_blst.nim +++ b/blscurve/eth2_keygen/hkdf_mod_r_blst.nim @@ -184,5 +184,4 @@ func keyGen*(ikm: openarray[byte], publicKey: var PublicKey, secretKey: var Secr # The cast is a workaround for private field access cast[ptr blst_scalar](secretKey.addr)[].blst_keygen(ikm, info = "") - publicKey = privToPub(secretKey) - return true + result = publicKey.publicFromSecret(secretKey) diff --git a/blscurve/eth2_keygen/hkdf_mod_r_miracl.nim b/blscurve/eth2_keygen/hkdf_mod_r_miracl.nim index c71320c..dfb840a 100644 --- a/blscurve/eth2_keygen/hkdf_mod_r_miracl.nim +++ b/blscurve/eth2_keygen/hkdf_mod_r_miracl.nim @@ -56,7 +56,7 @@ func hkdf_mod_r*(secretKey: var SecretKey, ikm: openArray[byte], key_info: strin # The cast is a workaround for private field access BIG_384_dmod(cast[ptr BIG_384](secretKey.addr)[], dseckey, CURVE_Order) - if bool cast[ptr BIG_384](secretKey.addr)[].BIG_384_iszilch(): + if secretKey.isZero(): salt = sha256.digest(salt0) else: return true @@ -120,11 +120,13 @@ func keyGen*(ikm: openarray[byte], publicKey: var PublicKey, secretKey: var Secr if ikm.len < 32: return false - let ok = secretKey.hkdf_mod_r(ikm, key_info) + var ok = secretKey.hkdf_mod_r(ikm, key_info) if not ok: return false # 4. xP = x * P # 6. PK = point_to_pubkey(xP) - publicKey = privToPub(secretKey) + ok = publicKey.publicFromSecret(secretKey) + if not ok: + return false return true diff --git a/blscurve/miracl/bls_sig_io.nim b/blscurve/miracl/bls_sig_io.nim index 481e6ee..a75ae48 100644 --- a/blscurve/miracl/bls_sig_io.nim +++ b/blscurve/miracl/bls_sig_io.nim @@ -22,10 +22,18 @@ func fromHex*[T: SecretKey|PublicKey|Signature|ProofOfPossession]( ## Initialize a BLS signature scheme object from ## its hex raw bytes representation. ## Returns true on a success and false otherwise + ## For secret key deserialization + ## A zero key is invalid when obj is SecretKey: result = obj.intVal.fromHex(hexStr) + if obj.intVal.isZilch(): + return false else: result = obj.point.fromHex(hexStr) + when obj is PublicKey: + # KeyValidate + if obj.point.isInf(): + result = false func fromBytes*[T: SecretKey|PublicKey|Signature|ProofOfPossession]( obj: var T, @@ -34,10 +42,18 @@ func fromBytes*[T: SecretKey|PublicKey|Signature|ProofOfPossession]( ## Initialize a BLS signature scheme object from ## its raw bytes representation. ## Returns true on success and false otherwise + ## For secret key deserialization + ## A zero key is invalid when obj is SecretKey: result = obj.intVal.fromBytes(raw) + if obj.intVal.isZilch(): + return false else: result = obj.point.fromBytes(raw) + when obj is PublicKey: + # KeyValidate + if obj.point.isInf(): + result = false func toHex*(obj: SecretKey|PublicKey|Signature|ProofOfPossession): string {.inline.} = ## Return the hex representation of a BLS signature scheme object diff --git a/blscurve/miracl/bls_signature_scheme.nim b/blscurve/miracl/bls_signature_scheme.nim index 7bd9026..6540ec6 100644 --- a/blscurve/miracl/bls_signature_scheme.nim +++ b/blscurve/miracl/bls_signature_scheme.nim @@ -41,6 +41,9 @@ import ./hash_to_curve type SecretKey* = object ## A secret key in the BLS (Boneh-Lynn-Shacham) signature scheme. + ## + ## This SecretKey is non-zero by construction. + ## ## This secret key SHOULD be protected against: ## - side-channel attacks: ## implementation must perform exactly the same memory access @@ -103,55 +106,103 @@ func subgroupCheck(P: GroupG1 or GroupG2): bool = rP.mul(CURVE_Order) result = rP.isInf() -func secretKeyToPublickey*(secretKey: SecretKey): PublicKey {.noInit.} = +func isZero*(seckey: SecretKey): bool = + ## Returns true if the secret key is zero + ## Those are invalid + result = seckey.intVal.iszilch() + +func publicFromSecret*(pubkey: var PublicKey, seckey: SecretKey): bool = ## Generates a public key from a secret key - # Inputs: - # - SK, a secret integer such that 0 <= SK < r. - # - # Outputs: - # - PK, a public key encoded as an octet string. + ## Inputs: + ## - SK, a secret integer such that 1 <= SK < r. + ## + ## Outputs: + ## - PK, a public key encoded as an octet string. + ## + ## Returns: + ## - false is secret key is invalid (SK == 0), true otherwise + ## + ## Side-channel/Constant-time considerations: + ## The SK content is not revealed unless its value + ## is exactly 0 # # Procedure: # 1. xP = SK * P # 2. PK = point_to_pubkey(xP) # 3. return PK - result.point = generator1() - result.point.mul(secretKey.intVal) -func privToPub*(secretKey: SecretKey): PublicKey {.noInit, inline, deprecated: "Use secretKeyToPublickey instead".} = - secretKeyToPublickey(secretKey) + + # Always != 0: + # keyGen, deriveChild_secretKey, fromHex, fromBytes guarantee that. + if seckey.isZero(): + return false + pubkey.point = generator1() + pubkey.point.mul(secKey.intVal) + return true # Aggregate # ---------------------------------------------------------------------- +# 2.8. Aggregate (BLSv4) +# +# The Aggregate algorithm aggregates multiple signatures into one. +# signature = Aggregate((signature_1, ..., signature_n)) +# +# Inputs: +# - signature_1, ..., signature_n, octet strings output by +# either CoreSign or Aggregate. +# +# Outputs: +# - signature, an octet string encoding a aggregated signature +# that combines all inputs; or INVALID. +# +# Precondition: n >= 1, otherwise return INVALID. +# +# Procedure: +# 1. aggregate = signature_to_point(signature_1) +# 2. If aggregate is INVALID, return INVALID +# 3. for i in 2, ..., n: +# 4. next = signature_to_point(signature_i) +# 5. If next is INVALID, return INVALID +# 6. aggregate = aggregate + next +# 7. signature = point_to_signature(aggregate) +# +# Comments: +# - This does not require signatures to be non-zero func init*(agg: var AggregateSignature, sig: Signature) {.inline.} = ## Initialize an aggregate signature with a signature agg = AggregateSignature(sig) proc aggregate*(agg: var AggregateSignature, sig: Signature) {.inline.} = - ## Aggregates signature ``sig2`` into ``sig1``. + ## Returns the aggregate signature of ``sig1`` + ``sig2``. + # Precondition n >= 1 is respected agg.point.add(sig.point) proc aggregate*(agg: var AggregateSignature, sigs: openarray[Signature]) = - ## Aggregates an array of signatures `sigs` into a signature `sig` + ## Returns the aggregate signature of ``sig1`` + ``sigs[0..= 1 is respected even if sigs.len == 0 for s in sigs: - agg.point.add(s.point) + agg.aggregate(s) proc finish*(sig: var Signature, agg: AggregateSignature) {.inline.} = ## Canonicalize the AggregateSignature into a Signature sig = Signature(agg) -proc aggregate*(sigs: openarray[Signature]): Signature = - ## Aggregates array of signatures ``sigs`` - ## and return aggregated signature. - ## +proc aggregateAll*(dst: var Signature, sigs: openarray[Signature]): bool = + ## Returns the aggregate signature of ``sigs[0.. 0) - result = sigs[0] + ## + ## Returns false if `sigs` is the empty array + ## and true otherwise + if len(sigs) == 0: + return false + dst = sigs[0] for i in 1 ..< sigs.len: - result.point.add(sigs[i].point) + dst.point.add(sigs[i].point) + return true # Core operations # ---------------------------------------------------------------------- @@ -175,6 +226,11 @@ func coreSign[T: byte|char]( domainSepTag: static string): GroupG2 = ## Computes a signature or proof-of-possession ## from a secret key and a message + ## + ## The SecretKey MUST be directly created via + ## `keyGen` or `derive_child_secretKey` + ## or deserialized from `fromBytes` or `fromHex`. + ## This ensures the precondition that it's not a zero key. # Spec # 1. Q = hash_to_point(message) # 2. R = SK * Q @@ -190,6 +246,10 @@ func coreVerify[T: byte|char]( domainSepTag: static string): bool = ## Check that a signature (or proof-of-possession) is valid ## for a message (or serialized publickey) under the provided public key + ## + ## PublicKey MUST be non-zero + ## `publicFromSecret`, `fromHex`, `fromBytes` ensure that. + ## # Spec # 1. R = signature_to_point(signature) # 2. If R is INVALID, return INVALID @@ -213,6 +273,7 @@ func coreVerify[T: byte|char]( if not subgroupCheck(sig_or_proof.point): return false # 4. If KeyValidate(PK) is INVALID, return INVALID + # We assumes PK is not 0 if not subgroupCheck(publicKey.point): return false let Q = hashToG2(message, domainSepTag) @@ -331,7 +392,9 @@ func popProve*(secretKey: SecretKey): ProofOfPossession = # 4. R = SK * Q # 5. proof = point_to_signature(R) # 6. return proof - let pubkey = privToPub(secretKey) + var pubkey {.noInit.}: PublicKey + let ok {.used.} = pubkey.publicFromSecret(secretKey) + assert ok, "The secret key is INVALID, it should be initialized non-zero with keyGen or derive_child_secretKey" result = popProve(secretKey, pubkey) func popVerify*(publicKey: PublicKey, proof: ProofOfPossession): bool = @@ -351,6 +414,11 @@ func popVerify*(publicKey: PublicKey, proof: ProofOfPossession): bool = func sign*[T: byte|char](secretKey: SecretKey, message: openarray[T]): Signature = ## Computes a signature ## from a secret key and a message + ## + ## The SecretKey MUST be directly created via + ## `keyGen` or `derive_child_secretKey` + ## or deserialized from `fromBytes` or `fromHex`. + ## This ensures the precondition that it's not a zero key. result.point = secretKey.coreSign(message, DST) func verify*[T: byte|char]( @@ -364,6 +432,11 @@ func verify*[T: byte|char]( ## ## Compared to the IETF spec API, it is modified to ## enforce proper usage of the proof-of-possession + ## + ## The PublicKey MUST be directly created via + ## `publicFromPrivate` + ## or deserialized from `fromBytes` or `fromHex`. + ## This ensures the precondition that it's not a zero key. if not publicKey.popVerify(proof): return false return publicKey.coreVerify(message, signature, DST) @@ -379,6 +452,11 @@ func verify*[T: byte|char]( ## The proof-of-possession MUST be verified before calling this function. ## It is recommended to use the overload that accepts a proof-of-possession ## to enforce correct usage. + ## + ## The PublicKey MUST be directly created via + ## `publicFromPrivate` + ## or deserialized from `fromBytes` or `fromHex`. + ## This ensures the precondition that it's not a zero key. return publicKey.coreVerify(message, signature, DST) func aggregateVerify*( diff --git a/blscurve/miracl/common.nim b/blscurve/miracl/common.nim index 429e0ac..3e20f96 100644 --- a/blscurve/miracl/common.nim +++ b/blscurve/miracl/common.nim @@ -155,6 +155,10 @@ proc cmp*(a: BIG_384, b: BIG_384): int {.inline.} = ## Returns ``-1`` if ``a < b``, ``0`` if ``a == b``, ``1`` if ``a > b`` result = int(BIG_384_comp(a, b)) +proc iszilch*(a: BIG_384): bool {.inline.} = + ## Returns ``true`` if ``a`` is zero. + result = bool(BIG_384_iszilch(a)) + proc iszilch*(a: FP_BLS12381): bool {.inline.} = ## Returns ``true`` if ``a`` is zero. result = (FP_BLS12381_iszilch(unsafeAddr a) == 1) diff --git a/tests/eth2.0_v0.12.0_vectors/aggregate/small/aggregate_0x0000000000000000000000000000000000000000000000000000000000000000/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_0x0000000000000000000000000000000000000000000000000000000000000000/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/aggregate/small/aggregate_0x0000000000000000000000000000000000000000000000000000000000000000/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_0x0000000000000000000000000000000000000000000000000000000000000000/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/aggregate/small/aggregate_0x5656565656565656565656565656565656565656565656565656565656565656/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_0x5656565656565656565656565656565656565656565656565656565656565656/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/aggregate/small/aggregate_0x5656565656565656565656565656565656565656565656565656565656565656/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_0x5656565656565656565656565656565656565656565656565656565656565656/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/aggregate/small/aggregate_0xabababababababababababababababababababababababababababababababab/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_0xabababababababababababababababababababababababababababababababab/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/aggregate/small/aggregate_0xabababababababababababababababababababababababababababababababab/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_0xabababababababababababababababababababababababababababababababab/data.yaml diff --git a/tests/eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_infinity_signature/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_infinity_signature/data.yaml new file mode 100644 index 0000000..d3b64e5 --- /dev/null +++ b/tests/eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_infinity_signature/data.yaml @@ -0,0 +1,2 @@ +input: ['0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'] +output: '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' diff --git a/tests/eth2.0_v0.12.0_vectors/aggregate/small/aggregate_na_pubkeys/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_na_signatures/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/aggregate/small/aggregate_na_pubkeys/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/aggregate/small/aggregate_na_signatures/data.yaml diff --git a/tests/eth2.0_v1.0.0-rc0_vectors/aggregate_verify/small/aggregate_verify_infinity_pubkey/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/aggregate_verify/small/aggregate_verify_infinity_pubkey/data.yaml new file mode 100644 index 0000000..5a59eae --- /dev/null +++ b/tests/eth2.0_v1.0.0-rc0_vectors/aggregate_verify/small/aggregate_verify_infinity_pubkey/data.yaml @@ -0,0 +1,10 @@ +input: + pubkeys: ['0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a', + '0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81', + '0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f', + '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'] + messages: ['0x0000000000000000000000000000000000000000000000000000000000000000', + '0x5656565656565656565656565656565656565656565656565656565656565656', '0xabababababababababababababababababababababababababababababababab', + '0x1212121212121212121212121212121212121212121212121212121212121212'] + signature: '0x9104e74b9dfd3ad502f25d6a5ef57db0ed7d9a0e00f3500586d8ce44231212542fcfaf87840539b398bf07626705cf1105d246ca1062c6c2e1a53029a0f790ed5e3cb1f52f8234dc5144c45fc847c0cd37a92d68e7c5ba7c648a8a339f171244' +output: false diff --git a/tests/eth2.0_v0.12.0_vectors/aggregate_verify/small/aggregate_verify_na_pubkeys_and_infinity_signature/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/aggregate_verify/small/aggregate_verify_na_pubkeys_and_infinity_signature/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/aggregate_verify/small/aggregate_verify_na_pubkeys_and_infinity_signature/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/aggregate_verify/small/aggregate_verify_na_pubkeys_and_infinity_signature/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/aggregate_verify/small/aggregate_verify_na_pubkeys_and_na_signature/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/aggregate_verify/small/aggregate_verify_na_pubkeys_and_na_signature/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/aggregate_verify/small/aggregate_verify_na_pubkeys_and_na_signature/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/aggregate_verify/small/aggregate_verify_na_pubkeys_and_na_signature/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/aggregate_verify/small/aggregate_verify_tampered_signature/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/aggregate_verify/small/aggregate_verify_tampered_signature/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/aggregate_verify/small/aggregate_verify_tampered_signature/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/aggregate_verify/small/aggregate_verify_tampered_signature/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/aggregate_verify/small/aggregate_verify_valid/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/aggregate_verify/small/aggregate_verify_valid/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/aggregate_verify/small/aggregate_verify_valid/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/aggregate_verify/small/aggregate_verify_valid/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_4f079f946446fabf/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_4f079f946446fabf/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_4f079f946446fabf/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_4f079f946446fabf/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_5a38e6b4017fe4dd/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_5a38e6b4017fe4dd/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_5a38e6b4017fe4dd/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_5a38e6b4017fe4dd/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_a698ea45b109f303/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_a698ea45b109f303/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_a698ea45b109f303/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_extra_pubkey_a698ea45b109f303/data.yaml diff --git a/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_infinity_pubkey/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_infinity_pubkey/data.yaml new file mode 100644 index 0000000..cb9f486 --- /dev/null +++ b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_infinity_pubkey/data.yaml @@ -0,0 +1,8 @@ +input: + pubkeys: ['0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a', + '0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81', + '0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f', + '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'] + message: '0x1212121212121212121212121212121212121212121212121212121212121212' + signature: '0xafcb4d980f079265caa61aee3e26bf48bebc5dc3e7f2d7346834d76cbc812f636c937b6b44a9323d8bc4b1cdf71d6811035ddc2634017faab2845308f568f2b9a0356140727356eae9eded8b87fd8cb8024b440c57aee06076128bb32921f584' +output: false diff --git a/tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_na_pubkeys_and_infinity_signature/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_na_pubkeys_and_infinity_signature/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_na_pubkeys_and_infinity_signature/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_na_pubkeys_and_infinity_signature/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_na_pubkeys_and_na_signature/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_na_pubkeys_and_na_signature/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_na_pubkeys_and_na_signature/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_na_pubkeys_and_na_signature/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_3d7576f3c0e3570a/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_3d7576f3c0e3570a/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_3d7576f3c0e3570a/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_3d7576f3c0e3570a/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_5e745ad0c6199a6c/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_5e745ad0c6199a6c/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_5e745ad0c6199a6c/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_5e745ad0c6199a6c/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_652ce62f09290811/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_652ce62f09290811/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_652ce62f09290811/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_tampered_signature_652ce62f09290811/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_valid_3d7576f3c0e3570a/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_valid_3d7576f3c0e3570a/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_valid_3d7576f3c0e3570a/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_valid_3d7576f3c0e3570a/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_valid_5e745ad0c6199a6c/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_valid_5e745ad0c6199a6c/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_valid_5e745ad0c6199a6c/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_valid_5e745ad0c6199a6c/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_valid_652ce62f09290811/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_valid_652ce62f09290811/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_valid_652ce62f09290811/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/fast_aggregate_verify/small/fast_aggregate_verify_valid_652ce62f09290811/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_11b8c7cad5238946/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_11b8c7cad5238946/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_11b8c7cad5238946/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_11b8c7cad5238946/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_142f678a8d05fcd1/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_142f678a8d05fcd1/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_142f678a8d05fcd1/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_142f678a8d05fcd1/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_37286e1a6d1f6eb3/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_37286e1a6d1f6eb3/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_37286e1a6d1f6eb3/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_37286e1a6d1f6eb3/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_7055381f640f2c1d/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_7055381f640f2c1d/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_7055381f640f2c1d/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_7055381f640f2c1d/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_84d45c9c7cca6b92/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_84d45c9c7cca6b92/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_84d45c9c7cca6b92/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_84d45c9c7cca6b92/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_8cd3d4d0d9a5b265/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_8cd3d4d0d9a5b265/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_8cd3d4d0d9a5b265/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_8cd3d4d0d9a5b265/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_c82df61aa3ee60fb/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_c82df61aa3ee60fb/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_c82df61aa3ee60fb/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_c82df61aa3ee60fb/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_d0e28d7e76eb6e9c/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_d0e28d7e76eb6e9c/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_d0e28d7e76eb6e9c/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_d0e28d7e76eb6e9c/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_f2ae1097e7d0e18b/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_f2ae1097e7d0e18b/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/sign/small/sign_case_f2ae1097e7d0e18b/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_f2ae1097e7d0e18b/data.yaml diff --git a/tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_zero_privkey/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_zero_privkey/data.yaml new file mode 100644 index 0000000..61f428f --- /dev/null +++ b/tests/eth2.0_v1.0.0-rc0_vectors/sign/small/sign_case_zero_privkey/data.yaml @@ -0,0 +1,3 @@ +input: {privkey: '0x0000000000000000000000000000000000000000000000000000000000000000', + message: '0xabababababababababababababababababababababababababababababababab'} +output: diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_infinity_pubkey_and_infinity_signature/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_infinity_pubkey_and_infinity_signature/data.yaml similarity index 66% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_infinity_pubkey_and_infinity_signature/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_infinity_pubkey_and_infinity_signature/data.yaml index 7005d3c..afdc293 100644 --- a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_infinity_pubkey_and_infinity_signature/data.yaml +++ b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_infinity_pubkey_and_infinity_signature/data.yaml @@ -1,3 +1,3 @@ input: {pubkey: '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - message: '0xabababababababababababababababababababababababababababababababab', signature: '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'} -output: true + message: '0x1212121212121212121212121212121212121212121212121212121212121212', signature: '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'} +output: false diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_195246ee3bd3b6ec/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_195246ee3bd3b6ec/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_195246ee3bd3b6ec/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_195246ee3bd3b6ec/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_2ea479adf8c40300/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_2ea479adf8c40300/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_2ea479adf8c40300/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_2ea479adf8c40300/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_2f09d443ab8a3ac2/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_2f09d443ab8a3ac2/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_2f09d443ab8a3ac2/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_2f09d443ab8a3ac2/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_3208262581c8fc09/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_3208262581c8fc09/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_3208262581c8fc09/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_3208262581c8fc09/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_6b3b17f6962a490c/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_6b3b17f6962a490c/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_6b3b17f6962a490c/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_6b3b17f6962a490c/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_6eeb7c52dfd9baf0/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_6eeb7c52dfd9baf0/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_6eeb7c52dfd9baf0/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_6eeb7c52dfd9baf0/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_8761a0b7e920c323/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_8761a0b7e920c323/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_8761a0b7e920c323/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_8761a0b7e920c323/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_d34885d766d5f705/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_d34885d766d5f705/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_d34885d766d5f705/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_d34885d766d5f705/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_e8a50c445c855360/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_e8a50c445c855360/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_tampered_signature_case_e8a50c445c855360/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_tampered_signature_case_e8a50c445c855360/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_195246ee3bd3b6ec/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_195246ee3bd3b6ec/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_195246ee3bd3b6ec/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_195246ee3bd3b6ec/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_2ea479adf8c40300/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_2ea479adf8c40300/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_2ea479adf8c40300/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_2ea479adf8c40300/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_2f09d443ab8a3ac2/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_2f09d443ab8a3ac2/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_2f09d443ab8a3ac2/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_2f09d443ab8a3ac2/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_3208262581c8fc09/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_3208262581c8fc09/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_3208262581c8fc09/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_3208262581c8fc09/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_6b3b17f6962a490c/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_6b3b17f6962a490c/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_6b3b17f6962a490c/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_6b3b17f6962a490c/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_6eeb7c52dfd9baf0/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_6eeb7c52dfd9baf0/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_6eeb7c52dfd9baf0/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_6eeb7c52dfd9baf0/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_8761a0b7e920c323/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_8761a0b7e920c323/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_8761a0b7e920c323/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_8761a0b7e920c323/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_d34885d766d5f705/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_d34885d766d5f705/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_d34885d766d5f705/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_d34885d766d5f705/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_e8a50c445c855360/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_e8a50c445c855360/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_valid_case_e8a50c445c855360/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_valid_case_e8a50c445c855360/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_195246ee3bd3b6ec/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_195246ee3bd3b6ec/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_195246ee3bd3b6ec/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_195246ee3bd3b6ec/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_2ea479adf8c40300/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_2ea479adf8c40300/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_2ea479adf8c40300/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_2ea479adf8c40300/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_2f09d443ab8a3ac2/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_2f09d443ab8a3ac2/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_2f09d443ab8a3ac2/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_2f09d443ab8a3ac2/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_3208262581c8fc09/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_3208262581c8fc09/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_3208262581c8fc09/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_3208262581c8fc09/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_6b3b17f6962a490c/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_6b3b17f6962a490c/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_6b3b17f6962a490c/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_6b3b17f6962a490c/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_6eeb7c52dfd9baf0/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_6eeb7c52dfd9baf0/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_6eeb7c52dfd9baf0/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_6eeb7c52dfd9baf0/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_8761a0b7e920c323/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_8761a0b7e920c323/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_8761a0b7e920c323/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_8761a0b7e920c323/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_d34885d766d5f705/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_d34885d766d5f705/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_d34885d766d5f705/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_d34885d766d5f705/data.yaml diff --git a/tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_e8a50c445c855360/data.yaml b/tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_e8a50c445c855360/data.yaml similarity index 100% rename from tests/eth2.0_v0.12.0_vectors/verify/small/verify_wrong_pubkey_case_e8a50c445c855360/data.yaml rename to tests/eth2.0_v1.0.0-rc0_vectors/verify/small/verify_wrong_pubkey_case_e8a50c445c855360/data.yaml diff --git a/tests/eth2_vectors.nim b/tests/eth2_vectors.nim index 9de70c9..6f03bbe 100644 --- a/tests/eth2_vectors.nim +++ b/tests/eth2_vectors.nim @@ -44,59 +44,74 @@ template testGen*(name, testJson, body: untyped): untyped = if skipped > 0: echo "[Warning]: ", skipped, " tests skipped." -proc getFrom(T: typedesc, test: JsonNode, inout: static InOut): T = +proc getFrom(T: typedesc, test: JsonNode, inout: static InOut): tuple[val: T, ok: bool] = when inout == Output: when T is bool: - result = test["output"].getBool() + result = (test["output"].getBool(), true) else: - let maybeParsed = result.fromHex(test["output"].getStr()) - if not maybeParsed: # We might read an empty string for N/A pubkeys - doAssert test["output"].getStr() == "", - "Couldn't parse output " & $T & ": " & test["output"].getStr() + result.ok = result.val.fromHex(test["output"].getStr()) + # if not result.ok: # We might read an empty string for N/A pubkeys + # echo "Couldn't parse output " & $T & ": " & test["output"].getStr() else: when T is seq[Signature]: for sigHex in test["input"]: - result.setLen(result.len + 1) - doAssert result[^1].fromHex(sigHex.getStr()), + result.val.setLen(result.val.len + 1) + doAssert result.val[^1].fromHex(sigHex.getStr()), "Couldn't parse input Signature: " & sigHex.getStr() + result.ok = true else: {.error: "Unreachable".} -proc getFrom(T: typedesc, test: JsonNode, inout: static InOut, name: string): T = +proc getFrom(T: typedesc, test: JsonNode, inout: static InOut, name: string): tuple[val: T, ok: bool] = when inout == Output: {.error: "Unreachable".} else: when T is seq[byte]: - result = test["input"][name].getStr().hexToSeqByte() + result = (test["input"][name].getStr().hexToSeqByte(), true) elif T is seq[PublicKey]: for pubKeyHex in test["input"][name]: - result.setLen(result.len + 1) - doAssert result[^1].fromHex(pubKeyHex.getStr()), - "Couldn't parse input PublicKey: " & pubKeyHex.getStr() + result.val.setLen(result.val.len + 1) + let ok = result.val[^1].fromHex(pubKeyHex.getStr()) + if not ok: + # echo "Couldn't parse input PublicKey: " & pubKeyHex.getStr() + result.ok = false + return + result.ok = true else: - doAssert result.fromHex(test["input"][name].getStr()), - "Couldn't parse input '" & name & "' (" & $T & - "): " & test["input"][name].getStr() + result.ok = result.val.fromHex(test["input"][name].getStr()) + # if not result.ok: + # echo "Couldn't parse input '" & name & "' (" & $T & + # "): " & test["input"][name].getStr() -proc aggFrom(T: typedesc, test: JsonNode): T = +proc aggFrom(T: typedesc, test: JsonNode): tuple[val: T, ok: bool] = when T is seq[(PublicKey, seq[byte])]: for pubkey in test["input"]["pubkeys"]: - result.setLen(result.len + 1) - doAssert result[^1][0].fromHex(pubkey.getStr()), - "Couldn't parse input PublicKey: " & pubkey.getStr() + result.val.setLen(result.val.len + 1) + let ok = result.val[^1][0].fromHex(pubkey.getStr()) + if not ok: + # echo "Couldn't parse input PublicKey: " & pubkey.getStr() + result.ok = false + return + var i = 0 for message in test["input"]["messages"]: - result[i][1] = message.getStr().hexToSeqByte() + result.val[i][1] = message.getStr().hexToSeqByte() inc i + result.ok = true elif T is seq[PublicKey]: for pubkey in test["input"]["pubkeys"]: - result.setLen(result.len + 1) - doAssert result[^1].fromHex(pubkey.getStr()), - "Couldn't parse input PublicKey: " & pubkey.getStr() + result.val.setLen(result.val.len + 1) + let ok = result.val[^1].fromHex(pubkey.getStr()) + if not ok: + # echo "Couldn't parse input PublicKey: " & pubkey.getStr() + result.ok = false + return + result.ok = true elif T is seq[seq[byte]]: for message in test["input"]["messages"]: - result.setLen(result.len + 1) - result[^1] = message.getStr().hexToSeqByte() + result.val.setLen(result.val.len + 1) + result.val[^1] = message.getStr().hexToSeqByte() + result.ok = true else: {.error: "Unreachable".} @@ -107,110 +122,98 @@ testGen(sign, test): expectedSig = Signature.getFrom(test, Output) - let libSig = privKey.sign(message) + doAssert privkey.ok == expectedSig.ok + if not privkey.ok or not expectedSig.ok: + return + + let libSig = privKey.val.sign(message.val) - doAssert libSig == expectedSig, block: + doAssert libSig == expectedSig.val, block: "\nSignature differs from expected \n" & " computed: " & libSig.toHex() & "\n" & - " expected: " & expectedSig.toHex() + " expected: " & expectedSig.val.toHex() testGen(verify, test): - let expected = bool.getFrom(test, Output) - var - pubkey: PublicKey - message: seq[byte] - signature: Signature - try: + let + expected = bool.getFrom(test, Output) pubKey = PublicKey.getFrom(test, Input, "pubkey") message = seq[byte].getFrom(test, Input, "message") signature = Signature.getFrom(test, Input, "signature") - except: - let emsg = getCurrentExceptionMsg() - if expected: - doAssert false, "Verification was not supposed to fail, but one of the inputs was invalid." & emsg - else: - echo "[INFO] Expected verification failure at parsing stage: " & emsg - let libValid = pubKey.verify(message, signature) + if not pubkey.ok: + # Infinity pubkey and infinity signature + doAssert not expected.val + return + + let libValid = pubKey.val.verify(message.val, signature.val) - doAssert libValid == expected, block: + doAssert libValid == expected.val, block: "\nVerification differs from expected \n" & " computed: " & $libValid & "\n" & - " expected: " & $expected + " expected: " & $expected.val testGen(aggregate, test): let sigs = seq[Signature].getFrom(test, Input) let expectedAgg = Signature.getFrom(test, Output) - # TODO - at which level should we catch the empty signatures? - if sigs.len == 0: - echo " ⚠⚠⚠ Skipping empty aggregation, handled at the client level" + var libAggSig {.noInit.}: Signature + let ok = libAggSig.aggregateAll(sigs.val) + if not ok: + doAssert not expectedAgg.ok + doAssert sigs.val.len == 0 return - let libAggSig = aggregate(sigs) - - doAssert libAggSig == expectedAgg, block: + doAssert libAggSig == expectedAgg.val, block: "\nSignature aggregation differs from expected \n" & " computed: " & libAggSig.toHex() & "\n" & - " expected: " & expectedAgg.toHex() + " expected: " & expectedAgg.val.toHex() testGen(fast_aggregate_verify, test): - let expected = bool.getFrom(test, Output) - var - pubkeys: seq[PublicKey] - message: seq[byte] - signature: Signature - try: + let + expected = bool.getFrom(test, Output) pubKeys = seq[PublicKey].getFrom(test, Input, "pubkeys") message = seq[byte].getFrom(test, Input, "message") signature = Signature.getFrom(test, Input, "signature") - except: - let emsg = getCurrentExceptionMsg() - if expected: - doAssert false, "Verification was not supposed to fail, but one of the inputs was invalid." & emsg - else: - echo "[INFO] Expected verification failure at parsing stage: " & emsg - let libValid = pubKeys.fastAggregateVerify(message, signature) + if not pubkeys.ok: + # Infinity pubkey in the mix + doAssert not expected.val + return + + let libValid = pubKeys.val.fastAggregateVerify(message.val, signature.val) - doAssert libValid == expected, block: + doAssert libValid == expected.val, block: "\nFast Aggregate Verification differs from expected \n" & " computed: " & $libValid & "\n" & - " expected: " & $expected + " expected: " & $expected.val testGen(aggregate_verify, test): - let expected = bool.getFrom(test, Output) - var + let + expected = bool.getFrom(test, Output) # We test both the SoA and AoS API - pubkey_msg_pairs: seq[(PublicKey, seq[byte])] - pubkeys: seq[PublicKey] - msgs: seq[seq[byte]] - signature: Signature - - try: pubkey_msg_pairs = seq[(PublicKey, seq[byte])].aggFrom(test) pubkeys = seq[PublicKey].aggFrom(test) msgs = seq[seq[byte]].aggFrom(test) signature = Signature.getFrom(test, Input, "signature") - except: - let emsg = getCurrentExceptionMsg() - if expected: - doAssert false, "Verification was not supposed to fail, but one of the inputs was invalid." & emsg - else: - echo "[INFO] Expected verification failure at parsing stage: " & emsg - let libAoSValid = aggregateVerify(pubkey_msg_pairs, signature) - let libSoAValid = aggregateVerify(pubkeys, msgs, signature) + let libAoSValid = aggregateVerify(pubkey_msg_pairs.val, signature.val) + let libSoAValid = aggregateVerify(pubkeys.val, msgs.val, signature.val) + + if not pubkeys.ok: + # Infinity pubkey in the mix + doAssert not pubkey_msg_pairs.ok + doAssert not expected.val + return - doAssert libAoSValid == expected, block: + doAssert libAoSValid == expected.val, block: "\nAggregate Verification differs from expected \n" & " computed: " & $libAoSValid & "\n" & - " expected: " & $expected + " expected: " & $expected.val - doAssert libSoAValid == expected, block: + doAssert libSoAValid == expected.val, block: "\nAggregate Verification differs from expected \n" & " computed: " & $libSoAValid & "\n" & - " expected: " & $expected + " expected: " & $expected.val suite "ETH 2.0 " & BLS_ETH2_SPEC & " test vectors - " & $BLS_BACKEND: test "[" & BLS_ETH2_SPEC & "] sign(SecretKey, message) -> Signature": diff --git a/tests/priv_to_pub.nim b/tests/priv_to_pub.nim index b250bab..4dcc9b5 100644 --- a/tests/priv_to_pub.nim +++ b/tests/priv_to_pub.nim @@ -19,11 +19,13 @@ echo "----------------------------------\n" proc test_sk_to_pk(seckey, pubkey: string) = - var sk{.noInit.}: SecretKey + var + sk{.noInit.}: SecretKey + pk{.noInit.}: PublicKey let ok = sk.fromHex(seckey) doAssert ok - let pk = sk.privToPub() - + let ok2 = pk.publicFromSecret(sk) + doAssert ok2 doAssert pk.toHex() == pubkey, "\ncomputed: " & pk.toHex() & "\nexpected: " & pubkey & '\n' echo "SUCCESS" diff --git a/tests/test_locator.nim b/tests/test_locator.nim index 08d439b..5a7f111 100644 --- a/tests/test_locator.nim +++ b/tests/test_locator.nim @@ -9,7 +9,7 @@ import export os, json -const ETH2_DIR = currentSourcePath.rsplit(DirSep, 1)[0] / "eth2.0_v0.12.0_vectors" +const ETH2_DIR = currentSourcePath.rsplit(DirSep, 1)[0] / "eth2.0_v1.0.0-rc0_vectors" proc parseTest*(file: string): JsonNode = var yamlStream = openFileStream(file)