-
Notifications
You must be signed in to change notification settings - Fork 101
Use Scott's subgroup membership tests for G1
and G2
of BLS12-381.
#74
Use Scott's subgroup membership tests for G1
and G2
of BLS12-381.
#74
Conversation
bls12_381/src/curves/mod.rs
Outdated
|
||
pub struct Parameters; | ||
pub struct Parameters0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm why this rename?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because Parameters
is also used for the SWModelParameters
struct... See below in this file
type G1Parameters = self::g1::Parameters
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe instead of importing crate::*
, we can use crate::Parameters
wherever necessary? That way we don't have to rename anything.
bls12_381/src/curves/g1.rs
Outdated
@@ -51,3 +80,11 @@ pub const G1_GENERATOR_X: Fq = field_new!(Fq, "368541675371338701678108831518307 | |||
/// 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 | |||
#[rustfmt::skip] | |||
pub const G1_GENERATOR_Y: Fq = field_new!(Fq, "1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569"); | |||
|
|||
pub const BETA: Fq = field_new!(Fq,"793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have a script to calculate this value? Or maybe a comment that can let us check it?
bls12_381/src/curves/g1.rs
Outdated
|
||
pub const BETA: Fq = field_new!(Fq,"793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"); | ||
|
||
pub fn sigma(p: &GroupAffine<Parameters>) -> GroupAffine<Parameters> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some documentation for this would be great =)
bls12_381/src/curves/g1.rs
Outdated
if Parameters0::X_IS_NEGATIVE { | ||
x_times_p = -x_times_p; | ||
} | ||
if (-*p + x_times_p).is_zero() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (-*p + x_times_p).is_zero() { | |
if (x_times_p - p).is_zero() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not working, and neither x_times_p - *p
. The only way I found is to write x_times_p + (-*p)
... Any suggestion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was because x_times_p was GroupAffine
. The following code should work:
if (-*p + x_times_p).is_zero() { | |
if x_times_p.add_mixed(-*p).is_zero() { |
bls12_381/src/curves/g2.rs
Outdated
fn is_in_correct_subgroup_assuming_on_curve(point: &GroupAffine<Parameters>) -> bool { | ||
// check that [p]P = [X]P | ||
let mut x_times_point: GroupAffine<_> = | ||
point.mul(BigInteger([Parameters0::X[0], 0, 0, 0])).into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm if you'd like, we can add a mul_limbs
(or some other name) method similar to this one on GroupProjective
: https://docs.rs/ark-ec/0.3.0/ark_ec/trait.ProjectiveCurve.html#method.mul. That way you can directly use point.mul_limbs(Parameters::X)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, you can also just use the existing point.mul_bits(BitIteratorBE::without_leading_zeros(Parameters::X))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the mul_bits
function is private and so I was not able to use it...
bls12_381/src/curves/g1.rs
Outdated
} else { | ||
let sigma_p = sigma(p); | ||
let mut x_times_p: GroupAffine<_> = | ||
p.mul(BigInteger([Parameters0::X[0], 0, 0, 0])).into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p.mul(BigInteger([Parameters0::X[0], 0, 0, 0])).into(); | |
p.mul_bits(BitIteratorBE::without_leading_zeros(Parameters::X).into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the mul_bits
function is private and so I was not able to use it...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be much cleaner like that, I agree :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I'll make a PR to expose that API, but for the time being we can use the existing code. If you can leave a TODO then i'll refactor to use that later.
bls12_381/src/curves/g1.rs
Outdated
let mut x_times_p: GroupAffine<_> = | ||
p.mul(BigInteger([Parameters0::X[0], 0, 0, 0])).into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's avoid the inversion here:
let mut x_times_p: GroupAffine<_> = | |
p.mul(BigInteger([Parameters0::X[0], 0, 0, 0])).into(); | |
let mut x_times_p = p.mul(BigInteger([Parameters0::X[0], 0, 0, 0])); |
bls12_381/src/curves/g1.rs
Outdated
let mut x2_times_p: GroupAffine<_> = x_times_p | ||
.mul(BigInteger([Parameters0::X[0], 0, 0, 0])) | ||
.into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let mut x2_times_p: GroupAffine<_> = x_times_p | |
.mul(BigInteger([Parameters0::X[0], 0, 0, 0])) | |
.into(); | |
let mut x2_times_p = x_times_p.mul(BigInteger([Parameters0::X[0], 0, 0, 0])); |
bls12_381/src/curves/g1.rs
Outdated
if Parameters0::X_IS_NEGATIVE { | ||
x2_times_p = -x2_times_p; | ||
} | ||
(x2_times_p + sigma_p).is_zero() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(x2_times_p + sigma_p).is_zero() | |
x2_times_p.add_mixed(sigma_p).is_zero() |
bls12_381/src/curves/g2.rs
Outdated
let mut x_times_point: GroupAffine<_> = | ||
point.mul(BigInteger([Parameters0::X[0], 0, 0, 0])).into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let mut x_times_point: GroupAffine<_> = | |
point.mul(BigInteger([Parameters0::X[0], 0, 0, 0])).into(); | |
let mut x_times_point = | |
point.mul(BigInteger([Parameters0::X[0], 0, 0, 0])); |
bls12_381/src/curves/g2.rs
Outdated
// psi(x,y) = (x^p * PSI_X, y^p * PSI_Y) is the Frobenius composed | ||
// with the quadratic twist and its inverse | ||
pub const PSI_X:Fq2 = field_new!( | ||
Fq2, | ||
FQ_ZERO, | ||
field_new!( | ||
Fq, | ||
"4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437" | ||
) | ||
); | ||
pub const PSI_Y: Fq2 = field_new!( | ||
Fq2, | ||
field_new!( | ||
Fq, | ||
"2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"), | ||
field_new!( | ||
Fq, | ||
"1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257") | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some documentation on how these constants are derived would be great.
bls12_381/src/curves/g2.rs
Outdated
Fq, | ||
"1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257") | ||
); | ||
pub fn psi(p: &GroupAffine<Parameters>) -> GroupAffine<Parameters> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto here.
bls12_381/src/curves/g2.rs
Outdated
if Parameters0::X_IS_NEGATIVE { | ||
x_times_point = -x_times_point; | ||
} | ||
let p_times_point = psi(point); | ||
(-x_times_point + p_times_point).is_zero() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if Parameters0::X_IS_NEGATIVE { | |
x_times_point = -x_times_point; | |
} | |
let p_times_point = psi(point); | |
(-x_times_point + p_times_point).is_zero() | |
// The check is `p_times_point - x_times_point == 0`? | |
// If `x` is negative, then the LHS becomes `p_times_point + x_times_point`. | |
// If `x` is positive, then it remains `p_times_point - x_times_point`. | |
// So, we negate if `x` is positive, and add the result. | |
if !Parameters0::X_IS_NEGATIVE { | |
x_times_point = -x_times_point; | |
} | |
let p_times_point = psi(point); | |
x_times_point.add_mixed(p_times_point).is_zero() |
Left another round of reviews, focusing on adding some more documentation (eg: links to descriptions of the algorithms in papers or blogposts etc) and on not doing unnecessary affine operations. Thanks for your patience @simonmasson! |
Thank you for all the comments/suggestions! I add some changes, let me know if something else is needed. |
bls12_381/src/curves/g2.rs
Outdated
pub fn psi(p: &GroupAffine<Parameters>) -> GroupAffine<Parameters> { | ||
// Psi is an endomorphism of the curve defined with the sextic | ||
// twists and the frobenius endomorphism on the G1 curve | ||
// (x,y) -> (x^p / (u+1)**((p-1)//3), y^p / (u+1)**((p-1)//2)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an intended distinction between ^
and **
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. I will change ^
into **
here :-)
I will need to double check the paper. Based on the paper, it seems that the following is not expected:
Rather, it is expected:
where for BLS-12, And, if beta is the cubic root of unity, then:
|
Let me correct my previous post. For the beta we are finding,
Both are satisfied. Because |
I added some documents and renamed some method names. Let me ping @Pratyush to do a final pass. |
There is some offline discussion with Simon. I will update this PR soon to reflect the discussion. |
G1
and G2
of BLS12-381.
So it seems there was an error in Scott preprint for G2 membership test proof. However, the result is still correct (more on that here: https://eprint.iacr.org/2022/352.pdf). |
I think one todo is to add additional comment to reference to the new paper for the proof. It is a relief that the original method still works. (not common) |
Description
Implementation of the fast subgroup check for G1 and G2 using the Scott algorithm from eprint 2021/1130.
The Scott's implementation (eprint 2021/1130) is slightly faster than Bowe's implementation:
closes: #XXXX
Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.
Pending
section inCHANGELOG.md
Files changed
in the Github PR explorer