mirror of
https://github.com/bitcoin/bips.git
synced 2026-11-02 19:41:29 +00:00
bip-0458: Add half-aggregation of BIP 340 signatures
This commit is contained in:
7 files changed
+1463
No files matched your search
@@ -0,0 +1,831 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate test vectors for Schnorr signature half-aggregation.
|
||||
|
||||
Usage:
|
||||
python gen_test_vectors.py
|
||||
|
||||
Outputs:
|
||||
- vectors/test_vectors_aggregate.csv
|
||||
- vectors/test_vectors_incaggregate.csv
|
||||
- vectors/test_vectors_verify.csv
|
||||
"""
|
||||
|
||||
import csv
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple
|
||||
|
||||
from halfagg import Aggregate, IncAggregate, hashHalfAgg_randomizer
|
||||
from secp256k1lab.secp256k1 import GE, FE, Scalar
|
||||
from secp256k1lab.util import bytes_from_int
|
||||
from secp256k1lab.bip340 import pubkey_gen, schnorr_sign, schnorr_verify
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
VECTORS_DIR = ROOT / "vectors"
|
||||
AGGREGATE_VECTORS = VECTORS_DIR / 'test_vectors_aggregate.csv'
|
||||
INCAGGREGATE_VECTORS = VECTORS_DIR / 'test_vectors_incaggregate.csv'
|
||||
VERIFY_VECTORS = VECTORS_DIR / 'test_vectors_verify.csv'
|
||||
|
||||
n = GE.ORDER
|
||||
p = FE.SIZE
|
||||
|
||||
|
||||
def create_signature(index: int, msg_len: int = 32) -> Tuple[bytes, bytes, bytes]:
|
||||
"""Create a deterministic (pubkey, message, signature) triple."""
|
||||
sk = bytes([index + 1] * 32)
|
||||
pk = pubkey_gen(sk)
|
||||
msg = bytes([index + 2] * msg_len)
|
||||
aux = bytes([index + 3] * 32)
|
||||
sig = schnorr_sign(msg, sk, aux)
|
||||
return pk, msg, sig
|
||||
|
||||
|
||||
def format_list(items: List[bytes], sep: str = ";") -> str:
|
||||
"""Format a list of bytes as semicolon-separated hex strings."""
|
||||
if not items:
|
||||
return ""
|
||||
return sep.join(item.hex().upper() for item in items)
|
||||
|
||||
|
||||
def gen_aggregate_vectors(f):
|
||||
"""Generate test vectors for Aggregate function."""
|
||||
writer = csv.writer(f)
|
||||
writer.writerow((
|
||||
"index",
|
||||
"pubkeys",
|
||||
"messages",
|
||||
"signatures",
|
||||
"expected_result",
|
||||
"expected_aggsig",
|
||||
"comment"
|
||||
))
|
||||
|
||||
idx = 0
|
||||
sigs = [create_signature(i) for i in range(5)]
|
||||
|
||||
# Success: Empty aggregation
|
||||
aggsig_empty = Aggregate([])
|
||||
writer.writerow((
|
||||
idx, "", "", "",
|
||||
"TRUE",
|
||||
aggsig_empty.hex().upper(),
|
||||
"Empty signature list"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Success: Single signature
|
||||
pk0, msg0, sig0 = sigs[0]
|
||||
aggsig_1 = Aggregate([(pk0, msg0, sig0)])
|
||||
writer.writerow((
|
||||
idx,
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
sig0.hex().upper(),
|
||||
"TRUE",
|
||||
aggsig_1.hex().upper(),
|
||||
"Single signature"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Success: Two signatures
|
||||
pk1, msg1, sig1 = sigs[1]
|
||||
pms_2 = [(pk0, msg0, sig0), (pk1, msg1, sig1)]
|
||||
aggsig_2 = Aggregate(pms_2)
|
||||
writer.writerow((
|
||||
idx,
|
||||
format_list([pk0, pk1]),
|
||||
format_list([msg0, msg1]),
|
||||
format_list([sig0, sig1]),
|
||||
"TRUE",
|
||||
aggsig_2.hex().upper(),
|
||||
"Two signatures"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Success: Three signatures
|
||||
pk2, msg2, sig2 = sigs[2]
|
||||
pms_3 = [(pk0, msg0, sig0), (pk1, msg1, sig1), (pk2, msg2, sig2)]
|
||||
aggsig_3 = Aggregate(pms_3)
|
||||
writer.writerow((
|
||||
idx,
|
||||
format_list([pk0, pk1, pk2]),
|
||||
format_list([msg0, msg1, msg2]),
|
||||
format_list([sig0, sig1, sig2]),
|
||||
"TRUE",
|
||||
aggsig_3.hex().upper(),
|
||||
"Three signatures"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Success: Five signatures
|
||||
pms_5 = [sigs[i] for i in range(5)]
|
||||
aggsig_5 = Aggregate(pms_5)
|
||||
writer.writerow((
|
||||
idx,
|
||||
format_list([s[0] for s in pms_5]),
|
||||
format_list([s[1] for s in pms_5]),
|
||||
format_list([s[2] for s in pms_5]),
|
||||
"TRUE",
|
||||
aggsig_5.hex().upper(),
|
||||
"Five signatures"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Success: Strange aggregation - individual invalid sigs that are valid
|
||||
# in aggregate
|
||||
pk_a, msg_a, sig_a = sigs[0]
|
||||
pk_b, msg_b, sig_b = sigs[1]
|
||||
pms_valid = [(pk_a, msg_a, sig_a), (pk_b, msg_b, sig_b)]
|
||||
aggsig_valid = Aggregate(pms_valid)
|
||||
|
||||
pmr = []
|
||||
z = []
|
||||
for i in range(2):
|
||||
pk, msg, sig = pms_valid[i]
|
||||
pmr.append((pk, msg, sig[:32]))
|
||||
z.append(hashHalfAgg_randomizer(pmr))
|
||||
|
||||
sagg = Scalar.from_bytes_wrapping(aggsig_valid[64:96])
|
||||
s1_new = Scalar.from_int_wrapping(0x123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0)
|
||||
s0_new = (sagg - z[1] * s1_new) / z[0]
|
||||
|
||||
sig_a_invalid = sig_a[:32] + s0_new.to_bytes()
|
||||
assert not schnorr_verify(msg_a, pk_a, sig_a_invalid), "sig_a_invalid should not verify"
|
||||
sig_b_invalid = sig_b[:32] + s1_new.to_bytes()
|
||||
assert not schnorr_verify(msg_b, pk_b, sig_b_invalid), "sig_b_invalid should not verify"
|
||||
|
||||
pms_strange = [(pk_a, msg_a, sig_a_invalid), (pk_b, msg_b, sig_b_invalid)]
|
||||
aggsig_strange = Aggregate(pms_strange)
|
||||
|
||||
writer.writerow((
|
||||
idx,
|
||||
format_list([pk_a, pk_b]),
|
||||
format_list([msg_a, msg_b]),
|
||||
format_list([sig_a_invalid, sig_b_invalid]),
|
||||
"TRUE",
|
||||
aggsig_strange.hex().upper(),
|
||||
"Strange aggregation - invalid individual sigs, valid aggregate"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Signature with s = n
|
||||
invalid_sig_n = sig0[0:32] + bytes_from_int(n)
|
||||
writer.writerow((
|
||||
idx,
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
invalid_sig_n.hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Signature s = n (at boundary)"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Signature with s > n
|
||||
invalid_sig_gt_n = sig0[0:32] + bytes_from_int(n + 1000)
|
||||
writer.writerow((
|
||||
idx,
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
invalid_sig_gt_n.hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Signature s > n"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Signature with s = 2^256 - 1
|
||||
invalid_sig_max = sig0[0:32] + bytes([0xff] * 32)
|
||||
writer.writerow((
|
||||
idx,
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
invalid_sig_max.hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Signature s = 2^256 - 1"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Public key too short
|
||||
writer.writerow((
|
||||
idx,
|
||||
pk0[0:31].hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
sig0.hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Public key too short"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Message too long
|
||||
pk_long, msg_long, sig_long = create_signature(0, 33)
|
||||
writer.writerow((
|
||||
idx,
|
||||
pk_long.hex().upper(),
|
||||
msg_long.hex().upper(),
|
||||
sig_long.hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Message too long"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Signature too short
|
||||
writer.writerow((
|
||||
idx,
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
sig0[0:63].hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Signature too short"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Signature too long
|
||||
writer.writerow((
|
||||
idx,
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
(sig0 + bytes([0])).hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Signature too long"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Public key too long
|
||||
writer.writerow((
|
||||
idx,
|
||||
(bytes([2]) + pk0).hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
sig0.hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Public key too long"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Message too short
|
||||
pk_short, msg_short, sig_short = create_signature(0, 31)
|
||||
writer.writerow((
|
||||
idx,
|
||||
pk_short.hex().upper(),
|
||||
msg_short.hex().upper(),
|
||||
sig_short.hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Message too short"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
|
||||
def gen_incaggregate_vectors(f):
|
||||
"""Generate test vectors for IncAggregate function."""
|
||||
writer = csv.writer(f)
|
||||
writer.writerow((
|
||||
"index",
|
||||
"aggsig",
|
||||
"pm_aggd_pubkeys",
|
||||
"pm_aggd_messages",
|
||||
"pms_pubkeys",
|
||||
"pms_messages",
|
||||
"pms_signatures",
|
||||
"expected_result",
|
||||
"expected_aggsig",
|
||||
"comment"
|
||||
))
|
||||
|
||||
idx = 0
|
||||
sigs = [create_signature(i) for i in range(4)]
|
||||
pk0, msg0, sig0 = sigs[0]
|
||||
pk1, msg1, sig1 = sigs[1]
|
||||
pk2, msg2, sig2 = sigs[2]
|
||||
|
||||
# Success: Increment empty aggregate with single signature
|
||||
empty_aggsig = bytes([0] * 32)
|
||||
result_0 = IncAggregate(empty_aggsig, [], [(pk0, msg0, sig0)])
|
||||
writer.writerow((
|
||||
idx,
|
||||
empty_aggsig.hex().upper(),
|
||||
"", "",
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
sig0.hex().upper(),
|
||||
"TRUE",
|
||||
result_0.hex().upper(),
|
||||
"Add single signature to empty aggregate"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Success: Increment single-sig aggregate with another signature
|
||||
aggsig_1 = Aggregate([(pk0, msg0, sig0)])
|
||||
result_1 = IncAggregate(aggsig_1, [(pk0, msg0)], [(pk1, msg1, sig1)])
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_1.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
pk1.hex().upper(),
|
||||
msg1.hex().upper(),
|
||||
sig1.hex().upper(),
|
||||
"TRUE",
|
||||
result_1.hex().upper(),
|
||||
"Add second signature to single-sig aggregate"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Success: Add two signatures at once
|
||||
result_2 = IncAggregate(aggsig_1, [(pk0, msg0)], [(pk1, msg1, sig1), (pk2, msg2, sig2)])
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_1.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
format_list([pk1, pk2]),
|
||||
format_list([msg1, msg2]),
|
||||
format_list([sig1, sig2]),
|
||||
"TRUE",
|
||||
result_2.hex().upper(),
|
||||
"Add two signatures at once"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Success: Increment with empty new signatures (no change)
|
||||
result_3 = IncAggregate(aggsig_1, [(pk0, msg0)], [])
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_1.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"", "", "",
|
||||
"TRUE",
|
||||
result_3.hex().upper(),
|
||||
"Add no new signatures (unchanged)"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Wrong aggsig length (too long)
|
||||
wrong_len_aggsig = bytes([0] * 64)
|
||||
writer.writerow((
|
||||
idx,
|
||||
wrong_len_aggsig.hex().upper(),
|
||||
"", "",
|
||||
"", "", "",
|
||||
"FALSE",
|
||||
"",
|
||||
"Aggregate signature wrong length"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Empty aggsig
|
||||
writer.writerow((
|
||||
idx,
|
||||
"",
|
||||
"", "",
|
||||
"", "", "",
|
||||
"FALSE",
|
||||
"",
|
||||
"Aggregate signature empty"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Existing aggsig with s = n
|
||||
invalid_aggsig_s = bytes_from_int(n)
|
||||
writer.writerow((
|
||||
idx,
|
||||
invalid_aggsig_s.hex().upper(),
|
||||
"", "",
|
||||
"", "", "",
|
||||
"FALSE",
|
||||
"",
|
||||
"Existing aggregate has s = n"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: New signature with s = n
|
||||
invalid_new_sig = sig0[0:32] + bytes_from_int(n)
|
||||
writer.writerow((
|
||||
idx,
|
||||
empty_aggsig.hex().upper(),
|
||||
"", "",
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
invalid_new_sig.hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"New signature has s = n"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Existing public key too short
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_1.hex().upper(),
|
||||
pk0[0:31].hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
pk1.hex().upper(),
|
||||
msg1.hex().upper(),
|
||||
sig1.hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Existing public key too short"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Existing message too long
|
||||
pk_long, msg_long, sig_long = create_signature(0, 33)
|
||||
writer.writerow((
|
||||
idx,
|
||||
sig_long.hex().upper(),
|
||||
pk_long.hex().upper(),
|
||||
msg_long.hex().upper(),
|
||||
pk1.hex().upper(),
|
||||
msg1.hex().upper(),
|
||||
sig1.hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Existing message too long"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Existing public key too long
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_1.hex().upper(),
|
||||
(bytes([2]) + pk0).hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
pk1.hex().upper(),
|
||||
msg1.hex().upper(),
|
||||
sig1.hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Existing public key too long"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Existing message too short
|
||||
pk_short, msg_short, sig_short = create_signature(0, 31)
|
||||
writer.writerow((
|
||||
idx,
|
||||
sig_short.hex().upper(),
|
||||
pk_short.hex().upper(),
|
||||
msg_short.hex().upper(),
|
||||
pk1.hex().upper(),
|
||||
msg1.hex().upper(),
|
||||
sig1.hex().upper(),
|
||||
"FALSE",
|
||||
"",
|
||||
"Existing message too short"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
|
||||
def gen_verify_vectors(f):
|
||||
"""Generate test vectors for VerifyAggregate function."""
|
||||
writer = csv.writer(f)
|
||||
writer.writerow((
|
||||
"index",
|
||||
"aggsig",
|
||||
"pubkeys",
|
||||
"messages",
|
||||
"expected_result",
|
||||
"comment"
|
||||
))
|
||||
|
||||
idx = 0
|
||||
sigs = [create_signature(i) for i in range(5)]
|
||||
pk0, msg0, sig0 = sigs[0]
|
||||
pk1, msg1, sig1 = sigs[1]
|
||||
pk2, msg2, sig2 = sigs[2]
|
||||
|
||||
# Success: Empty signature list
|
||||
writer.writerow((
|
||||
idx,
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"", "",
|
||||
"TRUE",
|
||||
"Empty signature list"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Success: Single signature
|
||||
writer.writerow((
|
||||
idx,
|
||||
"B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F",
|
||||
"1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F",
|
||||
"0202020202020202020202020202020202020202020202020202020202020202",
|
||||
"TRUE",
|
||||
"Single signature"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Success: Two signatures
|
||||
pk3, msg3, sig3 = sigs[3]
|
||||
aggsig_2 = Aggregate([(pk0, msg0, sig0), (pk3, msg3, sig3)])
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_2.hex().upper(),
|
||||
format_list([pk0, pk3]),
|
||||
format_list([msg0, msg3]),
|
||||
"TRUE",
|
||||
"Two signatures"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Success: Three signatures
|
||||
aggsig_3 = Aggregate([(pk0, msg0, sig0), (pk1, msg1, sig1), (pk2, msg2, sig2)])
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_3.hex().upper(),
|
||||
format_list([pk0, pk1, pk2]),
|
||||
format_list([msg0, msg1, msg2]),
|
||||
"TRUE",
|
||||
"Three signatures"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Success: Five signatures
|
||||
pms_5 = [sigs[i] for i in range(5)]
|
||||
aggsig_5 = Aggregate(pms_5)
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_5.hex().upper(),
|
||||
format_list([s[0] for s in pms_5]),
|
||||
format_list([s[1] for s in pms_5]),
|
||||
"TRUE",
|
||||
"Five signatures"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Public key not on curve
|
||||
aggsig_1 = Aggregate([(pk0, msg0, sig0)])
|
||||
invalid_x = 0x4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D # From BIP340
|
||||
invalid_pk = bytes_from_int(invalid_x)
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_1.hex().upper(),
|
||||
invalid_pk.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"Public key not on curve"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Public key is zero
|
||||
zero_pk = bytes([0] * 32)
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_1.hex().upper(),
|
||||
zero_pk.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"Public key is zero"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Public key >= field size
|
||||
pk_too_large = bytes_from_int(p)
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_1.hex().upper(),
|
||||
pk_too_large.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"Public key >= field size"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: R value not on curve
|
||||
invalid_r = bytes_from_int(invalid_x)
|
||||
invalid_r_aggsig = invalid_r + sig0[32:64]
|
||||
writer.writerow((
|
||||
idx,
|
||||
invalid_r_aggsig.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"R value not on curve"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: R value is zero
|
||||
zero_r_aggsig = bytes([0] * 32) + sig0[32:64]
|
||||
writer.writerow((
|
||||
idx,
|
||||
zero_r_aggsig.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"R value is zero"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: R value >= field size
|
||||
r_too_large_aggsig = bytes_from_int(p + 100) + sig0[32:64]
|
||||
writer.writerow((
|
||||
idx,
|
||||
r_too_large_aggsig.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"R value >= field size"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Aggregate s = n
|
||||
s_n_aggsig = sig0[0:32] + bytes_from_int(n)
|
||||
writer.writerow((
|
||||
idx,
|
||||
s_n_aggsig.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"Aggregate s = n"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Aggregate s > n
|
||||
s_gt_n_aggsig = sig0[0:32] + bytes_from_int(n + 1000)
|
||||
writer.writerow((
|
||||
idx,
|
||||
s_gt_n_aggsig.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"Aggregate s > n"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Aggregate s = 2^256 - 1
|
||||
max_s_aggsig = sig0[0:32] + bytes([0xff] * 32)
|
||||
writer.writerow((
|
||||
idx,
|
||||
max_s_aggsig.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"Aggregate s = 2^256 - 1"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Wrong message
|
||||
wrong_msg = bytes([0xff] * 32)
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_1.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
wrong_msg.hex().upper(),
|
||||
"FALSE",
|
||||
"Wrong message"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Wrong public key
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_1.hex().upper(),
|
||||
pk1.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"Wrong public key"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Tampered signature
|
||||
tampered_aggsig = aggsig_1[:-1] + bytes([(aggsig_1[-1] + 1) % 256])
|
||||
writer.writerow((
|
||||
idx,
|
||||
tampered_aggsig.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"Tampered signature (bit flip)"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Swapped order
|
||||
aggsig_2 = Aggregate([(pk0, msg0, sig0), (pk1, msg1, sig1)])
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_2.hex().upper(),
|
||||
format_list([pk1, pk0]),
|
||||
format_list([msg1, msg0]),
|
||||
"FALSE",
|
||||
"Swapped order"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: s = n - 1 (valid range, wrong signature)
|
||||
s_n_minus_1_aggsig = sig0[0:32] + bytes_from_int(n - 1)
|
||||
writer.writerow((
|
||||
idx,
|
||||
s_n_minus_1_aggsig.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"s = n-1 (valid range, wrong sig)"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: s = 0 (valid range, wrong signature)
|
||||
s_zero_aggsig = sig0[0:32] + bytes([0] * 32)
|
||||
writer.writerow((
|
||||
idx,
|
||||
s_zero_aggsig.hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"s = 0 (valid range, wrong sig)"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Aggsig too short
|
||||
writer.writerow((
|
||||
idx,
|
||||
sig0[0:31].hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"Aggregate signature too short"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Aggsig too long
|
||||
writer.writerow((
|
||||
idx,
|
||||
(aggsig_1 + bytes([0] * 32)).hex().upper(),
|
||||
pk0.hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"Aggregate signature too long"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Public key too short
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_1.hex().upper(),
|
||||
pk0[0:31].hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"Public key too short"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Message too long
|
||||
pk_long, msg_long, sig_long = create_signature(0, 33)
|
||||
writer.writerow((
|
||||
idx,
|
||||
sig_long.hex().upper(),
|
||||
pk_long.hex().upper(),
|
||||
msg_long.hex().upper(),
|
||||
"FALSE",
|
||||
"Message too long"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Public key too long
|
||||
writer.writerow((
|
||||
idx,
|
||||
aggsig_1.hex().upper(),
|
||||
(bytes([2]) + pk0).hex().upper(),
|
||||
msg0.hex().upper(),
|
||||
"FALSE",
|
||||
"Public key too long"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
# Failure: Message too short
|
||||
pk_short, msg_short, sig_short = create_signature(0, 31)
|
||||
writer.writerow((
|
||||
idx,
|
||||
sig_short.hex().upper(),
|
||||
pk_short.hex().upper(),
|
||||
msg_short.hex().upper(),
|
||||
"FALSE",
|
||||
"Message too short"
|
||||
))
|
||||
idx += 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.makedirs(VECTORS_DIR, exist_ok=True)
|
||||
|
||||
print(f"Generating {AGGREGATE_VECTORS}")
|
||||
with open(AGGREGATE_VECTORS, "w", newline='', encoding="utf-8") as f:
|
||||
gen_aggregate_vectors(f)
|
||||
|
||||
print(f"Generating {INCAGGREGATE_VECTORS}")
|
||||
with open(INCAGGREGATE_VECTORS, "w", newline='', encoding="utf-8") as f:
|
||||
gen_incaggregate_vectors(f)
|
||||
|
||||
print(f"Generating {VERIFY_VECTORS}")
|
||||
with open(VERIFY_VECTORS, "w", newline='', encoding="utf-8") as f:
|
||||
gen_verify_vectors(f)
|
||||
|
||||
print("Done.")
|
||||
@@ -0,0 +1,197 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Schnorr signature half-aggregation reference implementation
|
||||
|
||||
WARNING: This implementation is for demonstration purposes only and _not_ to
|
||||
be used in production environments.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent / "secp256k1lab/src"))
|
||||
from secp256k1lab.secp256k1 import (
|
||||
G,
|
||||
GE,
|
||||
Scalar,
|
||||
)
|
||||
from secp256k1lab.util import (
|
||||
tagged_hash,
|
||||
)
|
||||
|
||||
|
||||
def Aggregate(pms):
|
||||
"""
|
||||
Aggregates an array of triples (public key, message, signature) into a single aggregate signature.
|
||||
|
||||
:param pms: An array of triples (public key, message, signature).
|
||||
:return: The aggregate signature.
|
||||
"""
|
||||
|
||||
# Let aggsig = bytes(0)
|
||||
aggsig = bytes([0] * 32)
|
||||
|
||||
pm_aggd = []
|
||||
|
||||
# Return IncAggregate(aggsig, pms0..u-1); fail if that fails.
|
||||
return IncAggregate(aggsig, pm_aggd, pms)
|
||||
|
||||
|
||||
# IncAggregate(aggsig, pm_aggd0..v-1, pms_to_agg0..u-1)
|
||||
def IncAggregate(aggsig, pm_aggd, pms_to_agg):
|
||||
"""
|
||||
Incrementally aggregates an additional array of triples (public key, message, signature)
|
||||
into an existing aggregate signature.
|
||||
|
||||
:param aggsig: A byte array representing the aggregate signature.
|
||||
:param pm_aggd: An array of tuples (public key, message).
|
||||
:param pms_to_agg: An array of triples (public key, message, signature).
|
||||
:return: The new aggregate signature.
|
||||
"""
|
||||
|
||||
v = len(pm_aggd)
|
||||
u = len(pms_to_agg)
|
||||
|
||||
# Fail if len(aggsig) ≠ 32 * (v + 1)
|
||||
if len(aggsig) != 32 * (v + 1):
|
||||
raise ValueError("Length of aggsig must be 32 * (v + 1)")
|
||||
|
||||
r_values = []
|
||||
pmr_to_agg = []
|
||||
|
||||
# For i = 0 .. v-1:
|
||||
for i in range(v):
|
||||
# Let (pki, mi) = pm_aggdi
|
||||
(pki, mi) = pm_aggd[i]
|
||||
if len(pki) != 32 or len(mi) != 32:
|
||||
raise ValueError("Public key and message must be 32 bytes")
|
||||
|
||||
# Let ri = aggsig[i⋅32:(i+1)⋅32]
|
||||
ri = aggsig[i * 32:(i + 1) * 32]
|
||||
r_values.append(ri)
|
||||
|
||||
pmr_to_agg.append((pki, mi, ri))
|
||||
|
||||
z_values = []
|
||||
s_values = []
|
||||
|
||||
# For i = v .. v+u-1:
|
||||
for i in range(v, v + u):
|
||||
# Let (pki, mi, sigi) = pms_to_aggi-v
|
||||
(pki, mi, sigi) = pms_to_agg[i - v]
|
||||
if len(pki) != 32 or len(mi) != 32 or len(sigi) != 64:
|
||||
raise ValueError("Public key and message must be 32 bytes and signature 64 bytes")
|
||||
|
||||
# Let ri = sigi[0:32]
|
||||
ri = sigi[0:32]
|
||||
r_values.append(ri)
|
||||
|
||||
# Let si = int(sigi[32:64]); fail if si ≥ n
|
||||
si = Scalar.from_bytes_checked(sigi[32:64])
|
||||
s_values.append(si)
|
||||
|
||||
# If i = 0:
|
||||
# Let zi = 1
|
||||
# Else:
|
||||
# Let zi = int(hashBIP0458/randomizer(r0 || pk0 || m0 || ... || ri || pki || mi)) mod n
|
||||
pmr_to_agg.append((pki, mi, ri))
|
||||
z_values.append(hashHalfAgg_randomizer(pmr_to_agg))
|
||||
|
||||
# Let sagg = int(aggsig[v⋅32:(v+1)⋅32]); fail if sagg ≥ n
|
||||
s = Scalar.from_bytes_checked(aggsig[v * 32:(v + 1) * 32])
|
||||
|
||||
# Let s = sagg + zv⋅sv + ... + zv+u-1⋅sv+u-1 mod n
|
||||
for i in range(u):
|
||||
s = s + z_values[i] * s_values[i]
|
||||
|
||||
# Return r0 || ... || rv+u-1 || bytes(s)
|
||||
return b''.join(r_values) + s.to_bytes()
|
||||
|
||||
|
||||
# VerifyAggregate(aggsig, pm_aggd0..u-1)
|
||||
def VerifyAggregate(aggsig, pm_aggd):
|
||||
"""
|
||||
Verifies an aggregate signature against an array of public key and message tuples.
|
||||
|
||||
:param aggsig: A byte array representing the aggregate signature.
|
||||
:param pm_aggd: An array of tuples (public key, message).
|
||||
:return: Boolean indicating whether the verification is successful.
|
||||
"""
|
||||
|
||||
u = len(pm_aggd)
|
||||
|
||||
# Fail if len(aggsig) ≠ 32 * (u + 1)
|
||||
if len(aggsig) != 32 * (u + 1):
|
||||
raise ValueError("Length of aggsig must be 32 * (u + 1)")
|
||||
|
||||
z_values = []
|
||||
R_values = []
|
||||
P_values = []
|
||||
e_values = []
|
||||
r_values = []
|
||||
|
||||
# For i = 0 .. u-1:
|
||||
for i in range(u):
|
||||
# Let (pki, mi) = pm_aggdi
|
||||
(pki, mi) = pm_aggd[i]
|
||||
if len(pki) != 32 or len(mi) != 32:
|
||||
raise ValueError("Public key and message must be 32 bytes")
|
||||
|
||||
# Let Pi = lift_x(int(pki)); fail if that fails
|
||||
try:
|
||||
Pi = GE.from_bytes_xonly(pki)
|
||||
except ValueError:
|
||||
return False
|
||||
P_values.append(Pi)
|
||||
|
||||
# Let ri = aggsig[i⋅32:(i+1)⋅32]
|
||||
ri = aggsig[i * 32:(i + 1) * 32]
|
||||
# Let Ri = lift_x(int(ri)); fail if that fails
|
||||
try:
|
||||
Ri = GE.from_bytes_xonly(ri)
|
||||
except ValueError:
|
||||
return False
|
||||
R_values.append(Ri)
|
||||
r_values.append(ri)
|
||||
|
||||
# Let ei = int(hashBIP0340/challenge(ri || pki || mi)) mod n
|
||||
ei = Scalar.from_bytes_wrapping(hashBIP0340_challenge(ri, pki, mi))
|
||||
e_values.append(ei)
|
||||
|
||||
# If i = 0:
|
||||
# Let zi = 1
|
||||
# Else:
|
||||
# Let zi = int(hashBIP0458/randomizer(r0 || pk0 || m0 || ... || ri || pki || mi)) mod n
|
||||
pmr = [(pki, mi, ri) for (pki, mi), ri in zip(pm_aggd, r_values)]
|
||||
z_values.append(hashHalfAgg_randomizer(pmr))
|
||||
|
||||
# Let s = int(aggsig[u⋅32:(u+1)⋅32]); fail if s ≥ n
|
||||
try:
|
||||
s = Scalar.from_bytes_checked(aggsig[u * 32:(u + 1) * 32])
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
# Fail if s⋅G ≠ z0⋅(R0 + e0⋅P0) + ... + zu-1⋅(Ru-1 + eu-1⋅Pu-1)
|
||||
lhs = s * G
|
||||
rhs = GE()
|
||||
for i in range(u):
|
||||
rhs += z_values[i] * (R_values[i] + e_values[i] * P_values[i])
|
||||
|
||||
return lhs == rhs
|
||||
|
||||
|
||||
def hashBIP0340_challenge(sig, pubkey, msg):
|
||||
return tagged_hash("BIP0340/challenge", sig + pubkey + msg)
|
||||
|
||||
|
||||
def hashHalfAgg_randomizer(pmr):
|
||||
if len(pmr) == 1:
|
||||
return Scalar(1)
|
||||
|
||||
random_input = bytes()
|
||||
for (pki, mi, ri) in pmr:
|
||||
random_input += ri
|
||||
random_input += pki
|
||||
random_input += mi
|
||||
|
||||
return Scalar.from_bytes_wrapping(tagged_hash("BIP0458/randomizer", random_input))
|
||||
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Run test vectors for Schnorr signature half-aggregation.
|
||||
|
||||
Usage:
|
||||
python run_test_vectors.py
|
||||
|
||||
Expects CSV files generated by gen_test_vectors.py in vectors/ directory.
|
||||
"""
|
||||
|
||||
import csv
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from typing import List, Tuple
|
||||
|
||||
from halfagg import Aggregate, IncAggregate, VerifyAggregate
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
VECTORS_DIR = ROOT / "vectors"
|
||||
AGGREGATE_VECTORS = VECTORS_DIR / 'test_vectors_aggregate.csv'
|
||||
INCAGGREGATE_VECTORS = VECTORS_DIR / 'test_vectors_incaggregate.csv'
|
||||
VERIFY_VECTORS = VECTORS_DIR / 'test_vectors_verify.csv'
|
||||
|
||||
|
||||
def parse_hex_list(hex_str: str) -> List[bytes]:
|
||||
if not hex_str:
|
||||
return []
|
||||
return [bytes.fromhex(h) for h in hex_str.split(';')]
|
||||
|
||||
|
||||
def parse_pms(pks_str: str, msgs_str: str, sigs_str: str) -> List[Tuple[bytes, bytes, bytes]]:
|
||||
pks = parse_hex_list(pks_str)
|
||||
msgs = parse_hex_list(msgs_str)
|
||||
sigs = parse_hex_list(sigs_str)
|
||||
if not pks:
|
||||
return []
|
||||
return list(zip(pks, msgs, sigs))
|
||||
|
||||
|
||||
def parse_pm(pks_str: str, msgs_str: str) -> List[Tuple[bytes, bytes]]:
|
||||
pks = parse_hex_list(pks_str)
|
||||
msgs = parse_hex_list(msgs_str)
|
||||
if not pks:
|
||||
return []
|
||||
return list(zip(pks, msgs))
|
||||
|
||||
|
||||
def run_aggregate_tests() -> List[str]:
|
||||
"""Run Aggregate test vectors. Returns list of failed test descriptions."""
|
||||
failures = []
|
||||
|
||||
with open(AGGREGATE_VECTORS, newline='', encoding='utf-8') as f:
|
||||
reader = csv.reader(f)
|
||||
next(reader)
|
||||
|
||||
for row in reader:
|
||||
index, pks_str, msgs_str, sigs_str, expected_result, expected_aggsig, comment = row
|
||||
pms = parse_pms(pks_str, msgs_str, sigs_str)
|
||||
|
||||
if expected_result == "FALSE":
|
||||
try:
|
||||
Aggregate(pms)
|
||||
failures.append(f"Aggregate #{index}: {comment}")
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
actual = Aggregate(pms)
|
||||
if actual != bytes.fromhex(expected_aggsig):
|
||||
failures.append(f"Aggregate #{index}: {comment}")
|
||||
except ValueError:
|
||||
failures.append(f"Aggregate #{index}: {comment}")
|
||||
|
||||
return failures
|
||||
|
||||
|
||||
def run_incaggregate_tests() -> List[str]:
|
||||
"""Run IncAggregate test vectors. Returns list of failed test descriptions."""
|
||||
failures = []
|
||||
|
||||
with open(INCAGGREGATE_VECTORS, newline='', encoding='utf-8') as f:
|
||||
reader = csv.reader(f)
|
||||
next(reader)
|
||||
|
||||
for row in reader:
|
||||
(index, aggsig_str, pm_pks_str, pm_msgs_str,
|
||||
pms_pks_str, pms_msgs_str, pms_sigs_str,
|
||||
expected_result, expected_aggsig, comment) = row
|
||||
|
||||
aggsig = bytes.fromhex(aggsig_str) if aggsig_str else bytes()
|
||||
pm_aggd = parse_pm(pm_pks_str, pm_msgs_str)
|
||||
pms_to_agg = parse_pms(pms_pks_str, pms_msgs_str, pms_sigs_str)
|
||||
|
||||
if expected_result == "FALSE":
|
||||
try:
|
||||
IncAggregate(aggsig, pm_aggd, pms_to_agg)
|
||||
failures.append(f"IncAggregate #{index}: {comment}")
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
actual = IncAggregate(aggsig, pm_aggd, pms_to_agg)
|
||||
if actual != bytes.fromhex(expected_aggsig):
|
||||
failures.append(f"IncAggregate #{index}: {comment}")
|
||||
except ValueError:
|
||||
failures.append(f"IncAggregate #{index}: {comment}")
|
||||
|
||||
return failures
|
||||
|
||||
|
||||
def run_verify_tests() -> List[str]:
|
||||
"""Run VerifyAggregate test vectors. Returns list of failed test descriptions."""
|
||||
failures = []
|
||||
|
||||
with open(VERIFY_VECTORS, newline='', encoding='utf-8') as f:
|
||||
reader = csv.reader(f)
|
||||
next(reader)
|
||||
|
||||
for row in reader:
|
||||
index, aggsig_str, pks_str, msgs_str, expected_result, comment = row
|
||||
|
||||
aggsig = bytes.fromhex(aggsig_str)
|
||||
pm = parse_pm(pks_str, msgs_str)
|
||||
|
||||
try:
|
||||
result = VerifyAggregate(aggsig, pm)
|
||||
expected = (expected_result == "TRUE")
|
||||
if result != expected:
|
||||
failures.append(f"VerifyAggregate #{index}: {comment}")
|
||||
except ValueError:
|
||||
if expected_result == "TRUE":
|
||||
failures.append(f"VerifyAggregate #{index}: {comment}")
|
||||
|
||||
return failures
|
||||
|
||||
|
||||
def main():
|
||||
for filename in [AGGREGATE_VECTORS, INCAGGREGATE_VECTORS, VERIFY_VECTORS]:
|
||||
if not os.path.exists(filename):
|
||||
print(f"ERROR: Missing {filename}. Run gen_test_vectors.py first.")
|
||||
sys.exit(1)
|
||||
|
||||
failures = []
|
||||
failures.extend(run_aggregate_tests())
|
||||
failures.extend(run_incaggregate_tests())
|
||||
failures.extend(run_verify_tests())
|
||||
|
||||
if failures:
|
||||
print("FAILED:")
|
||||
for f in failures:
|
||||
print(f" {f}")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("All tests have passed.")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,16 @@
|
||||
index,pubkeys,messages,signatures,expected_result,expected_aggsig,comment
|
||||
0,,,,TRUE,0000000000000000000000000000000000000000000000000000000000000000,Empty signature list
|
||||
1,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,TRUE,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,Single signature
|
||||
2,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F;4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766,0202020202020202020202020202020202020202020202020202020202020202;0303030303030303030303030303030303030303030303030303030303030303,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F;C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9233428AEB77468852520B0256DE84562A29629194DAEAC45444C7711CD379E57,TRUE,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9F51B04478B464890B540F1BBE15E5E5965A348F2B3D09BD4021D9E1F67D9D774,Two signatures
|
||||
3,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F;4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766;531FE6068134503D2723133227C867AC8FA6C83C537E9A44C3C5BDBDCB1FE337,0202020202020202020202020202020202020202020202020202020202020202;0303030303030303030303030303030303030303030303030303030303030303;0404040404040404040404040404040404040404040404040404040404040404,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F;C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9233428AEB77468852520B0256DE84562A29629194DAEAC45444C7711CD379E57;F62B58B1908197B6D732F0564AD2AD5C6E438D24C65AF758DA9ACCCCCF5B3F923A17EA0CD56ED3A824AA14BC67839CED465BA5269700F600EDFC3DAAC8A6B069,TRUE,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9F62B58B1908197B6D732F0564AD2AD5C6E438D24C65AF758DA9ACCCCCF5B3F92B7A5E19F2F438EAE2D3D9630B4D69921A7E920CBF6E54585261B21D7E1395493,Three signatures
|
||||
4,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F;4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766;531FE6068134503D2723133227C867AC8FA6C83C537E9A44C3C5BDBDCB1FE337;462779AD4AAD39514614751A71085F2F10E1C7A593E4E030EFB5B8721CE55B0B;62C0A046DACCE86DDD0343C6D3C7C79C2208BA0D9C9CF24A6D046D21D21F90F7,0202020202020202020202020202020202020202020202020202020202020202;0303030303030303030303030303030303030303030303030303030303030303;0404040404040404040404040404040404040404040404040404040404040404;0505050505050505050505050505050505050505050505050505050505050505;0606060606060606060606060606060606060606060606060606060606060606,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F;C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9233428AEB77468852520B0256DE84562A29629194DAEAC45444C7711CD379E57;F62B58B1908197B6D732F0564AD2AD5C6E438D24C65AF758DA9ACCCCCF5B3F923A17EA0CD56ED3A824AA14BC67839CED465BA5269700F600EDFC3DAAC8A6B069;A3AFBDB45A6A34BF7C8C00F1B6D7E7D375B54540F13716C87B62E51E2F4F22FF3E57DF859581383FA53C564BC72EC8A60145C502E91B0B508A6F1BD7961FC45D;C1319F3743A9B8A5A30408FA90E96B3A8BB3FD4FF5B790935C465DDC68859B2935B87C950EB399CCCD956D5BE6327B164D4C4080671A6B2CB39FD6A755C5987E,TRUE,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9F62B58B1908197B6D732F0564AD2AD5C6E438D24C65AF758DA9ACCCCCF5B3F92A3AFBDB45A6A34BF7C8C00F1B6D7E7D375B54540F13716C87B62E51E2F4F22FFC1319F3743A9B8A5A30408FA90E96B3A8BB3FD4FF5B790935C465DDC68859B2917D482DF65A9338B797D020D0FC24439F80BBBAFAE0C01FE9C60E6BB6C1E9BFE,Five signatures
|
||||
5,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F;4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766,0202020202020202020202020202020202020202020202020202020202020202;0303030303030303030303030303030303030303030303030303030303030303,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA83B5F55690F0A13C12CBC1B569D10E3D919CE0E799D4AD29CEF1AE51DA64F9B57;C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0,TRUE,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9F51B04478B464890B540F1BBE15E5E5965A348F2B3D09BD4021D9E1F67D9D774,"Strange aggregation - invalid individual sigs, valid aggregate"
|
||||
6,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,,Signature s = n (at boundary)
|
||||
7,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364529,FALSE,,Signature s > n
|
||||
8,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,FALSE,,Signature s = 2^256 - 1
|
||||
9,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD07,0202020202020202020202020202020202020202020202020202020202020202,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,FALSE,,Public key too short
|
||||
10,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,020202020202020202020202020202020202020202020202020202020202020202,80B68E6A009D95B162880A6942C2308A04F6E75037EF10646F826FF4F658A9B139DE000C1E00C3B70E0490D6A034EB25090761400B08DE7A92390D5B3B2220B6,FALSE,,Message too long
|
||||
11,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C22,FALSE,,Signature too short
|
||||
12,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F00,FALSE,,Signature too long
|
||||
13,021B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,FALSE,,Public key too long
|
||||
14,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,02020202020202020202020202020202020202020202020202020202020202,BBE3DE7700230815FC246C1001266C4730A272B118B5651F2BFB656BA27930332DD2503A5B9CEDA204DF1636E0E578142211FFC98497B49C769A33989889B740,FALSE,,Message too short
|
||||
|
@@ -0,0 +1,13 @@
|
||||
index,aggsig,pm_aggd_pubkeys,pm_aggd_messages,pms_pubkeys,pms_messages,pms_signatures,expected_result,expected_aggsig,comment
|
||||
0,0000000000000000000000000000000000000000000000000000000000000000,,,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,TRUE,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,Add single signature to empty aggregate
|
||||
1,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766,0303030303030303030303030303030303030303030303030303030303030303,C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9233428AEB77468852520B0256DE84562A29629194DAEAC45444C7711CD379E57,TRUE,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9F51B04478B464890B540F1BBE15E5E5965A348F2B3D09BD4021D9E1F67D9D774,Add second signature to single-sig aggregate
|
||||
2,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766;531FE6068134503D2723133227C867AC8FA6C83C537E9A44C3C5BDBDCB1FE337,0303030303030303030303030303030303030303030303030303030303030303;0404040404040404040404040404040404040404040404040404040404040404,C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9233428AEB77468852520B0256DE84562A29629194DAEAC45444C7711CD379E57;F62B58B1908197B6D732F0564AD2AD5C6E438D24C65AF758DA9ACCCCCF5B3F923A17EA0CD56ED3A824AA14BC67839CED465BA5269700F600EDFC3DAAC8A6B069,TRUE,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9F62B58B1908197B6D732F0564AD2AD5C6E438D24C65AF758DA9ACCCCCF5B3F92B7A5E19F2F438EAE2D3D9630B4D69921A7E920CBF6E54585261B21D7E1395493,Add two signatures at once
|
||||
3,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,,,,TRUE,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,Add no new signatures (unchanged)
|
||||
4,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,,,,,,FALSE,,Aggregate signature wrong length
|
||||
5,,,,,,,FALSE,,Aggregate signature empty
|
||||
6,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,,,,,,FALSE,,Existing aggregate has s = n
|
||||
7,0000000000000000000000000000000000000000000000000000000000000000,,,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,,New signature has s = n
|
||||
8,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD07,0202020202020202020202020202020202020202020202020202020202020202,4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766,0303030303030303030303030303030303030303030303030303030303030303,C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9233428AEB77468852520B0256DE84562A29629194DAEAC45444C7711CD379E57,FALSE,,Existing public key too short
|
||||
9,80B68E6A009D95B162880A6942C2308A04F6E75037EF10646F826FF4F658A9B139DE000C1E00C3B70E0490D6A034EB25090761400B08DE7A92390D5B3B2220B6,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,020202020202020202020202020202020202020202020202020202020202020202,4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766,0303030303030303030303030303030303030303030303030303030303030303,C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9233428AEB77468852520B0256DE84562A29629194DAEAC45444C7711CD379E57,FALSE,,Existing message too long
|
||||
10,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,021B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766,0303030303030303030303030303030303030303030303030303030303030303,C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9233428AEB77468852520B0256DE84562A29629194DAEAC45444C7711CD379E57,FALSE,,Existing public key too long
|
||||
11,BBE3DE7700230815FC246C1001266C4730A272B118B5651F2BFB656BA27930332DD2503A5B9CEDA204DF1636E0E578142211FFC98497B49C769A33989889B740,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,02020202020202020202020202020202020202020202020202020202020202,4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766,0303030303030303030303030303030303030303030303030303030303030303,C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9233428AEB77468852520B0256DE84562A29629194DAEAC45444C7711CD379E57,FALSE,,Existing message too short
|
||||
|
@@ -0,0 +1,27 @@
|
||||
index,aggsig,pubkeys,messages,expected_result,comment
|
||||
0,0000000000000000000000000000000000000000000000000000000000000000,,,TRUE,Empty signature list
|
||||
1,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,TRUE,Single signature
|
||||
2,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8A3AFBDB45A6A34BF7C8C00F1B6D7E7D375B54540F13716C87B62E51E2F4F22FFAC87D631EE4A69E8D25F1977AFB86DD3A8FD3BEA9116F25A0CB523C25BCB5A41,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F;462779AD4AAD39514614751A71085F2F10E1C7A593E4E030EFB5B8721CE55B0B,0202020202020202020202020202020202020202020202020202020202020202;0505050505050505050505050505050505050505050505050505050505050505,TRUE,Two signatures
|
||||
3,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9F62B58B1908197B6D732F0564AD2AD5C6E438D24C65AF758DA9ACCCCCF5B3F92B7A5E19F2F438EAE2D3D9630B4D69921A7E920CBF6E54585261B21D7E1395493,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F;4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766;531FE6068134503D2723133227C867AC8FA6C83C537E9A44C3C5BDBDCB1FE337,0202020202020202020202020202020202020202020202020202020202020202;0303030303030303030303030303030303030303030303030303030303030303;0404040404040404040404040404040404040404040404040404040404040404,TRUE,Three signatures
|
||||
4,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9F62B58B1908197B6D732F0564AD2AD5C6E438D24C65AF758DA9ACCCCCF5B3F92A3AFBDB45A6A34BF7C8C00F1B6D7E7D375B54540F13716C87B62E51E2F4F22FFC1319F3743A9B8A5A30408FA90E96B3A8BB3FD4FF5B790935C465DDC68859B2917D482DF65A9338B797D020D0FC24439F80BBBAFAE0C01FE9C60E6BB6C1E9BFE,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F;4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766;531FE6068134503D2723133227C867AC8FA6C83C537E9A44C3C5BDBDCB1FE337;462779AD4AAD39514614751A71085F2F10E1C7A593E4E030EFB5B8721CE55B0B;62C0A046DACCE86DDD0343C6D3C7C79C2208BA0D9C9CF24A6D046D21D21F90F7,0202020202020202020202020202020202020202020202020202020202020202;0303030303030303030303030303030303030303030303030303030303030303;0404040404040404040404040404040404040404040404040404040404040404;0505050505050505050505050505050505050505050505050505050505050505;0606060606060606060606060606060606060606060606060606060606060606,TRUE,Five signatures
|
||||
5,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D,0202020202020202020202020202020202020202020202020202020202020202,FALSE,Public key not on curve
|
||||
6,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,0000000000000000000000000000000000000000000000000000000000000000,0202020202020202020202020202020202020202020202020202020202020202,FALSE,Public key is zero
|
||||
7,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,Public key >= field size
|
||||
8,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D0E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,R value not on curve
|
||||
9,00000000000000000000000000000000000000000000000000000000000000000E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,R value is zero
|
||||
10,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC930E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,R value >= field size
|
||||
11,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,Aggregate s = n
|
||||
12,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364529,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,Aggregate s > n
|
||||
13,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,Aggregate s = 2^256 - 1
|
||||
14,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,FALSE,Wrong message
|
||||
15,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766,0202020202020202020202020202020202020202020202020202020202020202,FALSE,Wrong public key
|
||||
16,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C2260,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,Tampered signature (bit flip)
|
||||
17,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8C9D9B1CCE8C0A99AA79F56185358CD82B7649D6132DAACB31612C7C9B14CE3A9F51B04478B464890B540F1BBE15E5E5965A348F2B3D09BD4021D9E1F67D9D774,4D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766;1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0303030303030303030303030303030303030303030303030303030303030303;0202020202020202020202020202020202020202020202020202020202020202,FALSE,Swapped order
|
||||
18,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,"s = n-1 (valid range, wrong sig)"
|
||||
19,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80000000000000000000000000000000000000000000000000000000000000000,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,"s = 0 (valid range, wrong sig)"
|
||||
20,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4A,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,Aggregate signature too short
|
||||
21,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F0000000000000000000000000000000000000000000000000000000000000000,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,Aggregate signature too long
|
||||
22,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD07,0202020202020202020202020202020202020202020202020202020202020202,FALSE,Public key too short
|
||||
23,80B68E6A009D95B162880A6942C2308A04F6E75037EF10646F826FF4F658A9B139DE000C1E00C3B70E0490D6A034EB25090761400B08DE7A92390D5B3B2220B6,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,020202020202020202020202020202020202020202020202020202020202020202,FALSE,Message too long
|
||||
24,B070AAFCEA439A4F6F1BBFC2EB66D29D24B0CAB74D6B745C3CFB009CC8FE4AA80E066C34819936549FF49B6FD4D41EDFC401A367B87DDD59FEE38177961C225F,021B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,0202020202020202020202020202020202020202020202020202020202020202,FALSE,Public key too long
|
||||
25,BBE3DE7700230815FC246C1001266C4730A272B118B5651F2BFB656BA27930332DD2503A5B9CEDA204DF1636E0E578142211FFC98497B49C769A33989889B740,1B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F,02020202020202020202020202020202020202020202020202020202020202,FALSE,Message too short
|
||||
|
Reference in new issue
Block a user