Skip to content

Commit 8e54e61

Browse files
Updated the OpenVM book and example code for twisted Edwards curves
1 parent 61b7093 commit 8e54e61

File tree

4 files changed

+123
-14
lines changed

4 files changed

+123
-14
lines changed

book/src/custom-extensions/ecc.md

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,20 @@ The OpenVM Elliptic Curve Cryptography Extension provides support for elliptic c
1515
- `WeierstrassPoint` trait:
1616
It represents an affine point on a Weierstrass elliptic curve and it extends `Group`.
1717

18-
- `Coordinate` type is the type of the coordinates of the point, and it implements `IntMod`.
19-
- `x()`, `y()` are used to get the affine coordinates
18+
- `Coordinate` type is the type of the coordinates of the point, and it implements `Field`.
19+
- `x()`, `y()` are used to get the affine coordinates.
2020
- `from_xy` is a constructor for the point, which checks if the point is either identity or on the affine curve.
2121
- The point supports elliptic curve operations through intrinsic functions `add_ne_nonidentity` and `double_nonidentity`.
2222
- `decompress`: Sometimes an elliptic curve point is compressed and represented by its `x` coordinate and the odd/even parity of the `y` coordinate. `decompress` is used to decompress the point back to `(x, y)`.
2323

24+
- `TwistedEdwardsPoint` trait:
25+
It represents an affine point on a twisted Edwards elliptic curve and it extends `Group`.
26+
27+
- `Coordinate` type is the type of the coordinates of the point, and it implements `Field`.
28+
- `x()`, `y()` are used to get the affine coordinates.
29+
- `from_xy` is a constructor for the point, which checks if the point is on the affine curve.
30+
- The point supports elliptic curve addition through the `add_impl` method.
31+
2432
- `msm`: for multi-scalar multiplication.
2533

2634
- `ecdsa`: for doing ECDSA signature verification and public key recovery from signature.
@@ -29,37 +37,45 @@ The OpenVM Elliptic Curve Cryptography Extension provides support for elliptic c
2937

3038
For elliptic curve cryptography, the `openvm-ecc-guest` crate provides macros similar to those in [`openvm-algebra-guest`](./algebra.md):
3139

32-
1. **Declare**: Use `sw_declare!` to define elliptic curves over the previously declared moduli. For example:
40+
1. **Declare**: Use `sw_declare!` or `te_declare!` to define weierstrass or twisted edwards elliptic curves, respectively,over the previously declared moduli. For example:
3341

3442
```rust
3543
sw_declare! {
3644
Bls12_381G1Affine { mod_type = Bls12_381Fp, b = BLS12_381_B },
3745
P256Affine { mod_type = P256Coord, a = P256_A, b = P256_B },
3846
}
47+
te_declare! {
48+
Edwards25519 { mod_type = Edwards25519Coord, a = CURVE_A, d = CURVE_D },
49+
}
3950
```
51+
This creates `Bls12_381G1Affine` and `P256Affine` structs which implement the `Group` and `WeierstrassPoint` traits, and the `Edwards25519` struct which implements the `Group` and `TwistedEdwardsPoint` traits. The underlying memory layout of the structs uses the memory layout of the `Bls12_381Fp`, `P256Coord`, and `Edwards25519Coord` structs, respectively.
4052

41-
Each declared curve must specify the `mod_type` (implementing `IntMod`) and a constant `b` for the Weierstrass curve equation \\(y^2 = x^3 + ax + b\\). `a` is optional and defaults to 0 for short Weierstrass curves.
42-
This creates `Bls12_381G1Affine` and `P256Affine` structs which implement the `Group` and `WeierstrassPoint` traits. The underlying memory layout of the structs uses the memory layout of the `Bls12_381Fp` and `P256Coord` structs, respectively.
53+
Each declared curve must specify the `mod_type` (implementing `Field`) and a constant `b` for the Weierstrass curve equation \\(y^2 = x^3 + ax + b\\) or `a` and `d` for the twisted Edwards curve equation \\(ax^2 + y^2 = 1 + dx^2y^2\\). For short Weierstrass curves, `a` is optional and defaults to 0.
4354

4455
2. **Init**: Called once, it enumerates these curves and allows the compiler to produce optimized instructions:
4556

4657
```rust
4758
sw_init! {
4859
Bls12_381G1Affine, P256Affine,
4960
}
61+
te_init! {
62+
Edwards25519,
63+
}
5064
```
5165

5266
3. **Setup**: Similar to the moduli and complex extensions, runtime setup instructions ensure that the correct curve parameters are being used, guaranteeing secure operation.
5367

5468
**Summary**:
5569

56-
- `sw_declare!`: Declares elliptic curve structures.
57-
- `sw_init!`: Initializes them once, linking them to the underlying moduli.
58-
- `setup_sw_<i>()`/`setup_all_curves()`: Secures runtime correctness.
70+
- `sw_declare!`: Declares short Weierstrass elliptic curve structures.
71+
- `te_declare!`: Declares twisted Edwards elliptic curve structures.
72+
- `sw_init!`: Initializes the short Weierstrass elliptic curves once, linking them to the underlying moduli.
73+
- `te_init!`: Initializes the twisted Edwards elliptic curves once, linking it to the underlying moduli.
74+
- `setup_sw_<i>()`/`setup_all_sw_curves()`/`setup_te_<i>()`/`setup_all_te_curves()`: Secures runtime correctness.
5975

60-
To use elliptic curve operations on a struct defined with `sw_declare!`, it is expected that the struct for the curve's coordinate field was defined using `moduli_declare!`. In particular, the coordinate field needs to be initialized and set up as described in the [algebra extension](./algebra.md) chapter.
76+
To use elliptic curve operations on a struct defined with `sw_declare!` or `te_declare!`, it is expected that the struct for the curve's coordinate field was defined using `moduli_declare!`. In particular, the coordinate field needs to be initialized and set up as described in the [algebra extension](./algebra.md) chapter.
6177

62-
For the basic operations provided by the `WeierstrassPoint` trait, the scalar field is not needed. For the ECDSA functions in the `ecdsa` module, the scalar field must also be declared, initialized, and set up.
78+
For the basic operations provided by the `WeierstrassPoint` or `TwistedEdwardsPoint` traits, the scalar field is not needed. For the ECDSA functions in the `ecdsa` module, the scalar field must also be declared, initialized, and set up.
6379

6480
## Example program
6581

@@ -98,8 +114,22 @@ supported_modulus = ["1157920892373161954235709850086879078532699846656405640394
98114
[[app_vm_config.ecc.supported_curves]]
99115
modulus = "115792089237316195423570985008687907853269984665640564039457584007908834671663"
100116
scalar = "115792089237316195423570985008687907852837564279074904382605163141518161494337"
117+
118+
[app_vm_config.ecc.supported_curves.coeffs]
119+
type = "SwCurve"
101120
a = "0"
102121
b = "7"
122+
123+
[[app_vm_config.ecc.supported_curves]]
124+
modulus = "57896044618658097711785492504343953926634992332820282019728792003956564819949"
125+
scalar = "7237005577332262213973186563042994240857116359379907606001950938285454250989"
126+
127+
[app_vm_config.ecc.supported_curves.coeffs]
128+
type = "TeCurve"
129+
a = "57896044618658097711785492504343953926634992332820282019728792003956564819948"
130+
d = "37095705934669439343138083508754565189542113879843219016388785533085940283555"
103131
```
104132

105133
The `supported_modulus` parameter is a list of moduli that the guest program will use. The `ecc.supported_curves` parameter is a list of supported curves that the guest program will use. They must be provided in decimal format in the `.toml` file. For multiple curves create multiple `[[app_vm_config.ecc.supported_curves]]` sections.
134+
135+
The `type` field must be `SwCurve` for short Weierstrass curves and `TeCurve` for twisted Edwards curves.

examples/ecc/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ openvm-platform = { path = "../../crates/toolchain/platform" }
1212
openvm-algebra-guest = { path = "../../extensions/algebra/guest" }
1313
openvm-ecc-guest = { path = "../../extensions/ecc/guest", features = ["k256"] }
1414
hex-literal = { version = "0.4.1", default-features = false }
15+
serde = { version = "1.0", default-features = false, features = [ "derive" ] }
1516

1617
[features]
1718
default = []

examples/ecc/openvm.toml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,17 @@ supported_modulus = ["1157920892373161954235709850086879078532699846656405640394
77
[[app_vm_config.ecc.supported_curves]]
88
modulus = "115792089237316195423570985008687907853269984665640564039457584007908834671663"
99
scalar = "115792089237316195423570985008687907852837564279074904382605163141518161494337"
10-
coeffs = { SwCurve = { a = "0", b = "7" } }
10+
11+
[app_vm_config.ecc.supported_curves.coeffs]
12+
type = "SwCurve"
13+
a = "0"
14+
b = "7"
15+
16+
[[app_vm_config.ecc.supported_curves]]
17+
modulus = "57896044618658097711785492504343953926634992332820282019728792003956564819949"
18+
scalar = "7237005577332262213973186563042994240857116359379907606001950938285454250989"
19+
20+
[app_vm_config.ecc.supported_curves.coeffs]
21+
type = "TeCurve"
22+
a = "57896044618658097711785492504343953926634992332820282019728792003956564819948"
23+
d = "37095705934669439343138083508754565189542113879843219016388785533085940283555"

examples/ecc/src/main.rs

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,64 @@
33

44
// ANCHOR: imports
55
use hex_literal::hex;
6-
use openvm_algebra_guest::IntMod;
6+
use openvm_algebra_guest::{Field, IntMod};
77
use openvm_ecc_guest::{
8+
edwards::TwistedEdwardsPoint,
89
k256::{Secp256k1Coord, Secp256k1Point},
910
weierstrass::WeierstrassPoint,
11+
Group,
1012
};
1113
// ANCHOR_END: imports
14+
openvm_algebra_guest::moduli_setup::moduli_declare! {
15+
// The Secp256k1 modulus and scalar field modulus are already declared in the k256 module
16+
Edwards25519Coord { modulus = "57896044618658097711785492504343953926634992332820282019728792003956564819949" },
17+
}
1218

1319
// ANCHOR: init
1420
openvm_algebra_guest::moduli_setup::moduli_init! {
1521
"0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F",
16-
"0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141"
22+
"0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141",
23+
"57896044618658097711785492504343953926634992332820282019728792003956564819949",
24+
}
25+
26+
// have to implement Field for Edwards25519Coord because moduli_declare! only implements IntMod
27+
impl Field for Edwards25519Coord {
28+
const ZERO: Self = <Self as IntMod>::ZERO;
29+
const ONE: Self = <Self as IntMod>::ONE;
30+
31+
type SelfRef<'a> = &'a Self;
32+
33+
fn double_assign(&mut self) {
34+
IntMod::double_assign(self);
35+
}
36+
37+
fn square_assign(&mut self) {
38+
IntMod::square_assign(self);
39+
}
40+
}
41+
42+
// a = 57896044618658097711785492504343953926634992332820282019728792003956564819948
43+
// d = 37095705934669439343138083508754565189542113879843219016388785533085940283555
44+
// encoded in little endian, 32 limbs of 8 bits each
45+
const CURVE_A: Edwards25519Coord = Edwards25519Coord::from_const_bytes([
46+
236, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
47+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127,
48+
]);
49+
const CURVE_D: Edwards25519Coord = Edwards25519Coord::from_const_bytes([
50+
163, 120, 89, 19, 202, 77, 235, 117, 171, 216, 65, 65, 77, 10, 112, 0, 152, 232, 121, 119, 121,
51+
64, 199, 140, 115, 254, 111, 43, 238, 108, 3, 82,
52+
]);
53+
54+
openvm_ecc_guest::te_setup::te_declare! {
55+
Edwards25519Point {
56+
mod_type = Edwards25519Coord,
57+
a = CURVE_A,
58+
d = CURVE_D
59+
}
60+
}
61+
62+
openvm_ecc_guest::te_setup::te_init! {
63+
Edwards25519Point,
1764
}
1865

1966
openvm_ecc_guest::sw_setup::sw_init! {
@@ -26,7 +73,9 @@ openvm::entry!(main);
2673

2774
pub fn main() {
2875
setup_all_moduli();
29-
setup_all_curves();
76+
setup_all_sw_curves();
77+
setup_all_te_curves();
78+
3079
let x1 = Secp256k1Coord::from_u32(1);
3180
let y1 = Secp256k1Coord::from_le_bytes(&hex!(
3281
"EEA7767E580D75BC6FDD7F58D2A84C2614FB22586068DB63B346C6E60AF21842"
@@ -40,5 +89,21 @@ pub fn main() {
4089
let p2 = Secp256k1Point::from_xy_nonidentity(x2, y2).unwrap();
4190

4291
let _p3 = &p1 + &p2;
92+
93+
let x1 = Edwards25519Coord::from_le_bytes(&hex!(
94+
"216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
95+
));
96+
let y1 = Edwards25519Coord::from_le_bytes(&hex!(
97+
"6666666666666666666666666666666666666666666666666666666666666658"
98+
));
99+
let p1 = Edwards25519Point::from_xy(x1, y1).unwrap();
100+
101+
let x2 = Edwards25519Coord::from_u32(2);
102+
let y2 = Edwards25519Coord::from_le_bytes(&hex!(
103+
"1A43BF127BDDC4D71FF910403C11DDB5BA2BCDD2815393924657EF111E712631"
104+
));
105+
let p2 = Edwards25519Point::from_xy(x2, y2).unwrap();
106+
107+
let _p3 = &p1 + &p2;
43108
}
44109
// ANCHOR_END: main

0 commit comments

Comments
 (0)