Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add parameters of Ed25519 and support twisted Edwards curves #317

Open
wants to merge 37 commits into
base: main
Choose a base branch
from

Conversation

querolita
Copy link
Member

This is related to o1-labs/o1js#1283

@querolita querolita changed the title Add parameters of Ed25519 twisted Edwards curve Add parameters of Ed25519 and support twisted Edwards curves Dec 11, 2024
Copy link
Member

@Trivo25 Trivo25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove the .DS_Store file?

@querolita
Copy link
Member Author

Most of the diff is recompiling the bindings to make CI happy

@querolita
Copy link
Member Author

The files that this PR is directly modifying are:
crypto/elliptic-curve-examples.ts
crypto/elliptic-curve.ts
crypto/elliptic-curve.unit-test.ts

Copy link
Member Author

@querolita querolita left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left some comments for reviewers


// Twisted Edwards curve tests

const Ed25519 = createCurveTwisted(TwistedCurveParams.Ed25519);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your preferred convention? CurveTwisted or TwistedCurve? Asking because in affine I believe I have read both.

if (z === 0n) {
// degenerate case
return twistedZero;
} else if (z === 1n && g.x === 0n && g.y === 1n) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I didn't treat this case separately, the following else if would place a false in the infinity parameter and then unit tests would complain because they used to find assertions of (0,1,false) != (0,1,true). But note that this is a branch that does not exist in the affine counterpart, and it is assuming that the "only" infinity point is exactly (0,1,1).

const Field = createField(p);
const Scalar = createField(order);
const one = { ...generator, infinity: false };
const Endo = undefined; // for Ed25519
Copy link
Member Author

@querolita querolita Jan 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how to generalize this for now. When we use this interface for something different than edwards25519, maybe this parameter should change.

Copy link
Member

@Trivo25 Trivo25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first pass looks good so far! will give it another more detailed one later!

@querolita
Copy link
Member Author

TODO: subgroup check

// x/z
let x = mod(g.x * zinv, p);
// y/z
let y = mod(g.y * zinv, p);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would enforce that if x === 0n and y === 1n, then we have the point at infinity. It happens when y = z.
Any point in projective coordinates that is in the representive class of (0 : 1) should be treated the point at infinity.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't that be already taken into account in the normalized case that z=1, then if x=0 and y=1 the point {0,1} would be returned

Copy link
Member

@dannywillems dannywillems left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return Endo;
},

from(g: { x: bigint; y: bigint }): GroupTwisted {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you want to enforce to have x and y given as canonical values? (i.e. smaller than the order of the base field?). I would be highly in favor of this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess no, and then perform the operations modulo the order and check that it holds (like, {x: 0, y: 1+p} is the identity instead of failing). But I am open to other alternatives, whatever is the standard.

assert(
isOnCurve(pointOrder8) && isInSubgroup(pointOrder8),
isOnCurve(pointOrder8) && !isInSubgroup(pointOrder8),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

'point on curve not in subgroup'
);
assert(equal(scale(pointOrder8, 8n), zero), 'point has order 8');
assert(
isOnCurve(pointOrder4) && !isInSubgroup(pointOrder4),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

'point on curve not in subgroup'
);
assert(
isOnCurve(pointOrder2) && !isInSubgroup(pointOrder2),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants