Skip to content

Commit

Permalink
BN254 - Hash-to-Curve (SVDW method) (#190)
Browse files Browse the repository at this point in the history
* Hash to BN254-Snarks

* Test SVDW code path with old v7 vectors for BLS12-381

* add benches
  • Loading branch information
mratsim authored Apr 26, 2022
1 parent 062ae56 commit e9e7a18
Show file tree
Hide file tree
Showing 30 changed files with 1,164 additions and 228 deletions.
93 changes: 78 additions & 15 deletions benchmarks/bench_hash_to_curve.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import
../constantine/math/config/curves,
../constantine/math/extension_fields,
../constantine/math/io/[io_bigints, io_ec],
../constantine/math/elliptic/[
ec_shortweierstrass_affine,
ec_shortweierstrass_projective],
../constantine/math/ec_shortweierstrass,
../constantine/hash_to_curve/hash_to_curve,
../constantine/hashes,
# Helpers
Expand All @@ -39,9 +37,9 @@ proc bench_BLS12_381_hash_to_G1(iters: int) =
const dst = "BLS_SIG_BLS12381G1-SHA256-SSWU-RO_POP_"
let msg = "Mr F was here"

var P: ECP_ShortW_Prj[Fp[BLS12_381], G1]
var P: ECP_ShortW_Jac[Fp[BLS12_381], G1]

bench("Hash to G1 (Draft #11)", BLS12_381, iters):
bench("Hash to G1 (SSWU method - Draft #14)", BLS12_381, iters):
sha256.hashToCurve(
k = 128,
output = P,
Expand All @@ -54,9 +52,9 @@ proc bench_BLS12_381_hash_to_G2(iters: int) =
const dst = "BLS_SIG_BLS12381G2-SHA256-SSWU-RO_POP_"
let msg = "Mr F was here"

var P: ECP_ShortW_Prj[Fp2[BLS12_381], G2]
var P: ECP_ShortW_Jac[Fp2[BLS12_381], G2]

bench("Hash to G2 (Draft #11)", BLS12_381, iters):
bench("Hash to G2 (SSWU method - Draft #14)", BLS12_381, iters):
sha256.hashToCurve(
k = 128,
output = P,
Expand All @@ -65,11 +63,72 @@ proc bench_BLS12_381_hash_to_G2(iters: int) =
domainSepTag = dst
)

proc bench_BLS12_381_G1_proj_aff_conversion(iters: int) =
proc bench_BLS12_381_hash_to_G1_SVDW(iters: int) =
const dst = "BLS_SIG_BLS12381G1-SHA256-SVDW-RO_POP_"
let msg = "Mr F was here"

var P: ECP_ShortW_Jac[Fp[BLS12_381], G1]

bench("Hash to G1 (SVDW method)", BLS12_381, iters):
sha256.hashToCurve_svdw(
k = 128,
output = P,
augmentation = "",
message = msg,
domainSepTag = dst
)

proc bench_BLS12_381_hash_to_G2_SVDW(iters: int) =
const dst = "BLS_SIG_BLS12381G2-SHA256-SVDW-RO_POP_"
let msg = "Mr F was here"

var P: ECP_ShortW_Jac[Fp2[BLS12_381], G2]

bench("Hash to G2 (SVDW method)", BLS12_381, iters):
sha256.hashToCurve_svdw(
k = 128,
output = P,
augmentation = "",
message = msg,
domainSepTag = dst
)

proc bench_BN254_Snarks_hash_to_G1(iters: int) =
const dst = "BLS_SIG_BN254SNARKSG1-SHA256-SVDW-RO_POP_"
let msg = "Mr F was here"

var P: ECP_ShortW_Jac[Fp[BN254_Snarks], G1]

bench("Hash to G1 (SVDW method)", BN254_Snarks, iters):
sha256.hashToCurve(
k = 128,
output = P,
augmentation = "",
message = msg,
domainSepTag = dst
)

proc bench_BN254_Snarks_hash_to_G2(iters: int) =
const dst = "BLS_SIG_BN254SNARKSG2-SHA256-SVDW-RO_POP_"
let msg = "Mr F was here"

var P: ECP_ShortW_Jac[Fp2[BN254_Snarks], G2]

bench("Hash to G2 (SVDW method)", BN254_Snarks, iters):
sha256.hashToCurve(
k = 128,
output = P,
augmentation = "",
message = msg,
domainSepTag = dst
)


proc bench_BLS12_381_G1_jac_aff_conversion(iters: int) =
const dst = "BLS_SIG_BLS12381G1-SHA256-SSWU-RO_POP_"
let msg = "Mr F was here"

var P: ECP_ShortW_Prj[Fp[BLS12_381], G1]
var P: ECP_ShortW_Jac[Fp[BLS12_381], G1]
var Paff: ECP_ShortW_Aff[Fp[BLS12_381], G1]

sha256.hashToCurve(
Expand All @@ -80,14 +139,14 @@ proc bench_BLS12_381_G1_proj_aff_conversion(iters: int) =
domainSepTag = dst
)

bench("G1 Proj->Affine conversion (for pairing)", BLS12_381, iters):
bench("G1 Jac->Affine conversion (for pairing)", BLS12_381, iters):
Paff.affine(P)

proc bench_BLS12_381_G2_proj_aff_conversion(iters: int) =
proc bench_BLS12_381_G2_jac_aff_conversion(iters: int) =
const dst = "BLS_SIG_BLS12381G2-SHA256-SSWU-RO_POP_"
let msg = "Mr F was here"

var P: ECP_ShortW_Prj[Fp2[BLS12_381], G2]
var P: ECP_ShortW_Jac[Fp2[BLS12_381], G2]
var Paff: ECP_ShortW_Aff[Fp2[BLS12_381], G2]

sha256.hashToCurve(
Expand All @@ -98,7 +157,7 @@ proc bench_BLS12_381_G2_proj_aff_conversion(iters: int) =
domainSepTag = dst
)

bench("G2 Proj->Affine conversion (for pairing)", BLS12_381, iters):
bench("G2 Jac->Affine conversion (for pairing)", BLS12_381, iters):
Paff.affine(P)

const Iters = 1000
Expand All @@ -107,8 +166,12 @@ proc main() =
separator()
bench_BLS12_381_hash_to_G1(Iters)
bench_BLS12_381_hash_to_G2(Iters)
bench_BLS12_381_G1_proj_aff_conversion(Iters)
bench_BLS12_381_G2_proj_aff_conversion(Iters)
bench_BLS12_381_hash_to_G1_SVDW(Iters)
bench_BLS12_381_hash_to_G2_SVDW(Iters)
bench_BN254_Snarks_hash_to_G1(Iters)
bench_BN254_Snarks_hash_to_G2(Iters)
bench_BLS12_381_G1_jac_aff_conversion(Iters)
bench_BLS12_381_G2_jac_aff_conversion(Iters)
separator()

main()
Expand Down
1 change: 1 addition & 0 deletions benchmarks/bench_summary_bls12_381.nim
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ proc main() =
finalExpBLS12Bench(curve, Iters)
pairingBLS12Bench(curve, Iters)
separator()
hashToCurveBLS12381G1Bench(Iters)
hashToCurveBLS12381G2Bench(Iters)
separator()

Expand Down
3 changes: 3 additions & 0 deletions benchmarks/bench_summary_bn254_snarks.nim
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ proc main() =
finalExpBNBench(curve, Iters)
pairingBNBench(curve, Iters)
separator()
hashToCurveBN254SnarksG1Bench(Iters)
hashToCurveBN254SnarksG2Bench(Iters)
separator()

main()
notes()
56 changes: 54 additions & 2 deletions benchmarks/bench_summary_template.nim
Original file line number Diff line number Diff line change
Expand Up @@ -212,15 +212,67 @@ proc pairingBNBench*(C: static Curve, iters: int) =
bench("Pairing BN", C, iters):
f.pairing_bn(P, Q)

proc hashToCurveBLS12_381G2Bench*(iters: int) =
proc hashToCurveBLS12381G1Bench*(iters: int) =
# Hardcode BLS12_381
# otherwise concept symbol
# 'CryptoHash' resolution issue
const dst = "BLS_SIG_BLS12381G1-SHA256-SSWU-RO_POP_"
let msg = "Mr F was here"
var P: ECP_ShortW_Prj[Fp[BLS12_381], G1]

bench("Hash to G1 (SSWU - Draft #14)", BLS12_381, iters):
sha256.hashToCurve(
k = 128,
output = P,
augmentation = "",
message = msg,
domainSepTag = dst
)

proc hashToCurveBLS12381G2Bench*(iters: int) =
# Hardcode BLS12_381
# otherwise concept symbol
# 'CryptoHash' resolution issue
const dst = "BLS_SIG_BLS12381G2-SHA256-SSWU-RO_POP_"
let msg = "Mr F was here"
var P: ECP_ShortW_Prj[Fp2[BLS12_381], G2]

bench("Hash to G2 (Draft #11)", BLS12_381, iters):
bench("Hash to G2 (SSWU - Draft #14)", BLS12_381, iters):
sha256.hashToCurve(
k = 128,
output = P,
augmentation = "",
message = msg,
domainSepTag = dst
)


proc hashToCurveBN254SnarksG1Bench*(iters: int) =
# Hardcode BN254_Snarks
# otherwise concept symbol
# 'CryptoHash' resolution issue
const dst = "BLS_SIG_BN254SNARKSG1-SHA256-SVDW-RO_POP_"
let msg = "Mr F was here"
var P: ECP_ShortW_Prj[Fp[BN254_Snarks], G1]

bench("Hash to G1 (SVDW - Draft #14)", BN254_Snarks, iters):
sha256.hashToCurve(
k = 128,
output = P,
augmentation = "",
message = msg,
domainSepTag = dst
)

proc hashToCurveBN254SnarksG2Bench*(iters: int) =
# Hardcode BN254_Snarks
# otherwise concept symbol
# 'CryptoHash' resolution issue
const dst = "BLS_SIG_BN254SNARKSG2-SHA256-SVDW-RO_POP_"
let msg = "Mr F was here"
var P: ECP_ShortW_Prj[Fp2[BN254_Snarks], G2]

bench("Hash to G2 (SVDW - Draft #14)", BN254_Snarks, iters):
sha256.hashToCurve(
k = 128,
output = P,
Expand Down
16 changes: 9 additions & 7 deletions constantine.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,6 @@ const testDesc: seq[tuple[path: string, useGMP: bool]] = @[
("tests/math/t_pairing_bls12_381_optate.nim", false),
("tests/math/t_pairing_bls12_381_multi.nim", false),

# Hashing to elliptic curves
# ----------------------------------------------------------
("tests/math/t_hash_to_field.nim", false),
("tests/math/t_hash_to_curve.nim", false),

# Prime order fields
# ----------------------------------------------------------
("tests/math/t_fr.nim", false),
Expand All @@ -188,6 +183,12 @@ const testDesc: seq[tuple[path: string, useGMP: bool]] = @[
# ----------------------------------------------------------
("tests/t_hash_sha256_vs_openssl.nim", true), # skip OpenSSL tests on Windows

# Hashing to elliptic curves
# ----------------------------------------------------------
("tests/t_hash_to_field.nim", false),
("tests/t_hash_to_curve_random.nim", false),
("tests/t_hash_to_curve.nim", false),

# Ciphers
# ----------------------------------------------------------
("tests/t_cipher_chacha20.nim", false),
Expand Down Expand Up @@ -216,8 +217,9 @@ const skipSanitizers = [
"tests/math/t_ec_sage_bn254_snarks.nim",
"tests/math/t_ec_sage_bls12_377.nim",
"tests/math/t_ec_sage_bls12_381.nim",
"tests/math/t_hash_to_field.nim",
"tests/math/t_hash_to_curve.nim"
"tests/t_hash_to_field.nim",
"tests/t_hash_to_curve.nim",
"tests/t_hash_to_curve_random.nim"
]

when defined(windows):
Expand Down
40 changes: 20 additions & 20 deletions constantine/hash_to_curve/h2c_isogeny_maps.nim
Original file line number Diff line number Diff line change
Expand Up @@ -92,39 +92,39 @@ func h2c_isogeny_map[F](

# xd^e with e in [1, N], for example [xd, xd², xd³]
const maxdegree = max([
h2cIsomapPoly(F.C, G, xnum).len,
h2cIsomapPoly(F.C, G, xden).len,
h2cIsomapPoly(F.C, G, ynum).len,
h2cIsomapPoly(F.C, G, yden).len,
h2cIsomapPoly(F.C, sswu, G, xnum).len,
h2cIsomapPoly(F.C, sswu, G, xden).len,
h2cIsomapPoly(F.C, sswu, G, ynum).len,
h2cIsomapPoly(F.C, sswu, G, yden).len,
])
var xd_pow{.noInit.}: array[maxdegree, F]
xd_pow[0] = xd
xd_pow[1].square(xd_pow[0])
for i in 2 ..< xd_pow.len:
xd_pow[i].prod(xd_pow[i-1], xd_pow[0])

const xnLen = h2cIsomapPoly(F.C, G, xnum).len
const ynLen = h2cIsomapPoly(F.C, G, ynum).len
const xnLen = h2cIsomapPoly(F.C, sswu, G, xnum).len
const ynLen = h2cIsomapPoly(F.C, sswu, G, ynum).len

rxn.poly_eval_horner_scaled(
xn, xd_pow,
h2cIsomapPoly(F.C, G, xnum),
h2cIsomapPoly(F.C, sswu, G, xnum),
xnLen
)
rxd.poly_eval_horner_scaled(
xn, xd_pow,
h2cIsomapPoly(F.C, G, xden),
h2cIsomapPoly(F.C, sswu, G, xden),
xnLen
)

ryn.poly_eval_horner_scaled(
xn, xd_pow,
h2cIsomapPoly(F.C, G, ynum),
h2cIsomapPoly(F.C, sswu, G, ynum),
ynLen
)
ryd.poly_eval_horner_scaled(
xn, xd_pow,
h2cIsomapPoly(F.C, G, yden),
h2cIsomapPoly(F.C, sswu, G, yden),
ynLen
)

Expand Down Expand Up @@ -224,10 +224,10 @@ func h2c_isogeny_map*[F; G: static Subgroup](

# Z²^e with e in [1, N], for example [Z², Z⁴, Z⁶]
const maxdegree = max([
h2cIsomapPoly(F.C, G, xnum).len,
h2cIsomapPoly(F.C, G, xden).len,
h2cIsomapPoly(F.C, G, ynum).len,
h2cIsomapPoly(F.C, G, yden).len,
h2cIsomapPoly(F.C, sswu, G, xnum).len,
h2cIsomapPoly(F.C, sswu, G, xden).len,
h2cIsomapPoly(F.C, sswu, G, ynum).len,
h2cIsomapPoly(F.C, sswu, G, yden).len,
])
var ZZpow{.noInit.}: array[maxdegree, F]
ZZpow[0].square(P.z)
Expand All @@ -241,28 +241,28 @@ func h2c_isogeny_map*[F; G: static Subgroup](
else:
ZZpow[i].prod(ZZpow[(i-1) shr 1], ZZpow[((i-1) shr 1) + 1])

const xnLen = h2cIsomapPoly(F.C, G, xnum).len
const ynLen = h2cIsomapPoly(F.C, G, ynum).len
const xnLen = h2cIsomapPoly(F.C, sswu, G, xnum).len
const ynLen = h2cIsomapPoly(F.C, sswu, G, ynum).len

xn.poly_eval_horner_scaled(
P.x, ZZpow,
h2cIsomapPoly(F.C, G, xnum),
h2cIsomapPoly(F.C, sswu, G, xnum),
xnLen
)
xd.poly_eval_horner_scaled(
P.x, ZZpow,
h2cIsomapPoly(F.C, G, xden),
h2cIsomapPoly(F.C, sswu, G, xden),
xnLen
)

yn.poly_eval_horner_scaled(
P.x, ZZpow,
h2cIsomapPoly(F.C, G, ynum),
h2cIsomapPoly(F.C, sswu, G, ynum),
ynLen
)
yd.poly_eval_horner_scaled(
P.x, ZZpow,
h2cIsomapPoly(F.C, G, yden),
h2cIsomapPoly(F.C, sswu, G, yden),
ynLen
)

Expand Down
Loading

0 comments on commit e9e7a18

Please sign in to comment.