|
6 | 6 | <a href="https://deps.rs/repo/github/arkworks-rs/algebra"><img src="https://deps.rs/repo/github/arkworks-rs/algebra/status.svg"></a>
|
7 | 7 | </p>
|
8 | 8 |
|
9 |
| -This crate defines Elliptic Curve traits, curve models that follow these traits, and multi-scalar multiplications. |
| 9 | +`ark-ec` defines traits and algorithms for working with different kinds of additive groups, with a focus on groups arising from elliptic curves. It further provides concrete instantiations of these traits for various elliptic curve models, including popular families of pairing-friendly curves such as the BLS12 family of curves. |
10 | 10 | Implementations of particular curves using these curve models can be found in [`arkworks-rs/curves`](https://github.com/arkworks-rs/curves/README.md).
|
11 | 11 |
|
12 |
| -The available elliptic curve traits are: |
| 12 | +## Usage |
13 | 13 |
|
14 |
| -* [`AffineRepr`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs#L223) - Interface for elliptic curve points in the 'canonical form' for serialization. |
15 |
| -* [`CurveGroup`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs#L118) - Interface for elliptic curve points in a representation that is more efficient for most computation. |
16 |
| -* [`Pairing`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs#L41) - Pairing friendly elliptic curves (Contains the pairing function, and acts as a wrapper type on G1, G2, GT, and the relevant fields). |
17 |
| -* [`CurveCycle`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs#L319) - Trait representing a cycle of elliptic curves. |
18 |
| -* [`PairingFriendlyCycle`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs#L331) - Trait representing a cycle of pairing friendly elliptic curves. |
| 14 | +### The `Group` trait |
19 | 15 |
|
20 |
| -The elliptic curve models implemented are: |
| 16 | +Many cryptographic protocols use as core building-blocks prime-order groups. The [`Group`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs) trait is an abstraction that represents elements of such abelian prime-order groups. It provides methods for performing common operations on group elements: |
| 17 | + |
| 18 | +```rust |
| 19 | +use ark_ec::Group; |
| 20 | +use ark_ff::{PrimeField, Field}; |
| 21 | +// We'll use the BLS12-381 G1 curve for this example. |
| 22 | +// This group has a prime order `r`, and is associated with a prime field `Fr`. |
| 23 | +use ark_test_curves::bls12_381::{G1Projective as G, Fr as ScalarField}; |
| 24 | +use ark_std::{Zero, UniformRand, ops::Mul}; |
| 25 | + |
| 26 | +let mut rng = ark_std::test_rng(); |
| 27 | +// Let's sample uniformly random group elements: |
| 28 | +let a = G::rand(&mut rng); |
| 29 | +let b = G::rand(&mut rng); |
| 30 | + |
| 31 | +// We can add elements, ... |
| 32 | +let c = a + b; |
| 33 | +// ... subtract them, ... |
| 34 | +let d = a - b; |
| 35 | +// ... and double them. |
| 36 | +assert_eq!(c + d, a.double()); |
| 37 | +// We can also negate elements, ... |
| 38 | +let e = -a; |
| 39 | +// ... and check that negation satisfies the basic group law |
| 40 | +assert_eq!(e + a, G::zero()); |
| 41 | + |
| 42 | +// We can also multiply group elements by elements of the corresponding scalar field |
| 43 | +// (an act known as *scalar multiplication*) |
| 44 | +let scalar = ScalarField::rand(&mut rng); |
| 45 | +let e = c.mul(scalar); |
| 46 | +let f = e.mul(scalar.inverse().unwrap()); |
| 47 | +assert_eq!(f, c); |
| 48 | +``` |
| 49 | + |
| 50 | +## Scalar multiplication |
| 51 | + |
| 52 | +While the `Group` trait already produces scalar multiplication routines, in many cases one can take advantage of |
| 53 | +the group structure to perform scalar multiplication more efficiently. To allow such specialization, `ark-ec` provides |
| 54 | +the `ScalarMul` and `VariableBaseMSM` traits. The latter trait computes an "inner product" between a vector of scalars `s` and a vector of group elements `g`. That is, it computes `s.iter().zip(g).map(|(s, g)| g * s).sum()`. |
| 55 | + |
| 56 | +```rust |
| 57 | +use ark_ec::{Group, VariableBaseMSM}; |
| 58 | +use ark_ff::{PrimeField, Field}; |
| 59 | +// We'll use the BLS12-381 G1 curve for this example. |
| 60 | +// This group has a prime order `r`, and is associated with a prime field `Fr`. |
| 61 | +use ark_test_curves::bls12_381::{G1Projective as G, G1Affine as GAffine, Fr as ScalarField}; |
| 62 | +use ark_std::{Zero, UniformRand}; |
| 63 | + |
| 64 | +let mut rng = ark_std::test_rng(); |
| 65 | +// Let's sample uniformly random group elements: |
| 66 | +let a = GAffine::rand(&mut rng); |
| 67 | +let b = GAffine::rand(&mut rng); |
| 68 | + |
| 69 | +let s1 = ScalarField::rand(&mut rng); |
| 70 | +let s2 = ScalarField::rand(&mut rng); |
| 71 | + |
| 72 | +// Note that we're using the `GAffine` type here, as opposed to `G`. |
| 73 | +// This is because MSMs are more efficient when the group elements are in affine form. (See below for why.) |
| 74 | +// |
| 75 | +// The `VariableBaseMSM` trait allows specializing the input group element representation to allow |
| 76 | +// for more efficient implementations. |
| 77 | +let result = G::msm(&[a, b], &[s1, s2]); |
| 78 | +assert_eq!(result, a * s1 + b * s2); |
| 79 | +``` |
| 80 | + |
| 81 | +### Elliptic curve groups |
| 82 | + |
| 83 | +There are two traits that are important when working with elliptic curves |
| 84 | +over finite fields: [`CurveGroup`], and [`AffineRepr`]. Both traits |
| 85 | +represent elements of the same curve, but provide different underlying representations. |
| 86 | +In particular, the [`CurveGroup`] representation of a curve point is generally |
| 87 | +more efficient for arithmetic, but does not provide a unique representative |
| 88 | +for a curve point. An [`AffineRepr`] representation, on the other hand, *is* unique, |
| 89 | +but is slower for most arithmetic operations. Let's explore how and when to use |
| 90 | +these: |
| 91 | + |
| 92 | +```rust |
| 93 | +use ark_ec::{AffineRepr, Group, CurveGroup, VariableBaseMSM}; |
| 94 | +use ark_ff::{PrimeField, Field}; |
| 95 | +use ark_test_curves::bls12_381::{G1Projective as G, G1Affine as GAffine, Fr as ScalarField}; |
| 96 | +use ark_std::{Zero, UniformRand}; |
| 97 | + |
| 98 | +let mut rng = ark_std::test_rng(); |
| 99 | +// Let's generate an elliptic curve group element in the `CurveGroup` representation |
| 100 | +let a = G::rand(&mut rng); |
| 101 | +// We can convert it the `AffineRepr` representation... |
| 102 | +let a_aff = a.into_affine(); |
| 103 | +// ... and check that the two representations are equal. |
| 104 | +assert_eq!(a_aff, a); |
| 105 | +// We can also convert back to the `CurveGroup` representation: |
| 106 | +assert_eq!(a, a_aff.into_group()); |
| 107 | + |
| 108 | +// As a general rule, most group operations are slower when elements |
| 109 | +// are represented as `AffineRepr`. However, adding an `AffineRepr` |
| 110 | +// point to a `CurveGroup` one is usually slightly more efficient than |
| 111 | +// adding two `CurveGroup` points. |
| 112 | +let d = a + a_aff; |
| 113 | +assert_eq!(d, a.double()); |
| 114 | + |
| 115 | +// This efficiency also translates into more efficient scalar multiplication routines. |
| 116 | +let scalar = ScalarField::rand(&mut rng); |
| 117 | +let mul_result = a_aff * scalar; |
| 118 | +assert_eq!(a * scalar, mul_result); |
| 119 | + |
| 120 | +// Finally, while not recommended, users can directly construct group elements |
| 121 | +// from the x and y coordinates of the curve points. This is useful when implementing algorithms |
| 122 | +// like hash-to-curve. |
| 123 | +let a_x = a_aff.x; |
| 124 | +let a_y = a_aff.y; |
| 125 | +let is_at_infinity = a_aff.is_zero(); |
| 126 | +// This check ensures that `new_a` is indeed in the curve group, and in particular |
| 127 | +// is within the prime-order group. |
| 128 | +let new_a = GAffine::new(a_x, a_y); |
| 129 | +assert_eq!(a_aff, new_a); |
| 130 | +assert!(new_a.is_on_curve()); |
| 131 | +assert!(new_a.is_in_correct_subgroup_assuming_on_curve()); |
| 132 | +``` |
| 133 | + |
| 134 | +Besides the foregoing abstract interfaces for elliptic curve groups, `ark-ec` also provides |
| 135 | +the following concrete instantiations of common elliptic curve models: |
21 | 136 |
|
22 | 137 | * [*Short Weierstrass*](https://github.com/arkworks-rs/algebra/blob/master/ec/src/models/short_weierstrass.rs) curves. The `AffineRepr` in this case is in typical Short Weierstrass point representation, and the `CurveGroup` is using points in [Jacobian Coordinates](https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates).
|
23 | 138 | * [*Twisted Edwards*](https://github.com/arkworks-rs/algebra/blob/master/ec/src/models/twisted_edwards.rs) curves. The `AffineRepr` in this case is in standard Twisted Edwards curve representation, whereas the `CurveGroup` uses points in [Extended Twisted Edwards Coordinates](https://eprint.iacr.org/2008/522.pdf).
|
| 139 | + |
| 140 | +### Pairings |
| 141 | + |
| 142 | +[`Pairing`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/pairing.rs) is a trait that defines the interface for a pairing-friendly elliptic curve. Besides the general interface, we provide concrete instantiations of popular pairing-friendly families of curves, such as the [Barreto-Lynn-Scott](https://github.com/arkworks-rs/algebra/blob/master/ec/src/models/bls12/mod.rs) and [Barreto-Naehrig](https://github.com/arkworks-rs/algebra/blob/master/ec/src/models/bn/mod.rs) families. |
| 143 | + |
| 144 | +```rust |
| 145 | +use ark_ec::{pairing::Pairing, AffineRepr}; |
| 146 | +use ark_ff::Field; |
| 147 | +use ark_std::UniformRand; |
| 148 | + |
| 149 | +use ark_test_curves::bls12_381::{Bls12_381, G1Projective as G1, G2Projective as G2, Fq12 as Fq12}; |
| 150 | +use ark_test_curves::bls12_381::Fr as ScalarField; |
| 151 | + |
| 152 | +// The pairing engine is parameterized by the scalar field of the curve. |
| 153 | +let mut rng = ark_std::test_rng(); |
| 154 | +let s = ScalarField::rand(&mut rng); |
| 155 | +let a = G1::rand(&mut rng); |
| 156 | +let b = G2::rand(&mut rng); |
| 157 | + |
| 158 | +// We can compute the pairing of two points on the curve, either monolithically... |
| 159 | +let e1 = Bls12_381::pairing(a, b); |
| 160 | +// ... or in two steps. First, we compute the Miller loop... |
| 161 | +let ml_result = Bls12_381::miller_loop(a, b); |
| 162 | +// ... and then the final exponentiation. |
| 163 | +let e2 = Bls12_381::final_exponentiation(ml_result).unwrap(); |
| 164 | +assert_eq!(e1, e2); |
| 165 | +``` |
| 166 | + |
| 167 | +### Hash-to-group |
| 168 | + |
| 169 | +`ark-ec` also provides traits for hashing to elliptic curve groups. The [`HashToCurve`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/hashing/mod.rs) trait allows users to hash arbitrary byte strings to elliptic curve group elements, and allows using different hashing strategies. |
0 commit comments