use less clone and builtin modinv
This commit is contained in:
parent
0b9ae82c17
commit
880c34ce03
145
src/lib.rs
145
src/lib.rs
@ -16,19 +16,19 @@ struct CurveFp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct Point {
|
struct Point<'a> {
|
||||||
x: BigUint,
|
x: BigUint,
|
||||||
y: BigUint,
|
y: BigUint,
|
||||||
curve: CurveFp,
|
curve: &'a CurveFp,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 椭圆曲线上的点(雅可比坐标)
|
/// 椭圆曲线上的点(雅可比坐标)
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct JacobianPoint {
|
struct JacobianPoint<'a> {
|
||||||
x: BigUint, // X 坐标
|
x: BigUint, // X 坐标
|
||||||
y: BigUint, // Y 坐标
|
y: BigUint, // Y 坐标
|
||||||
z: BigUint, // Z 坐标
|
z: BigUint, // Z 坐标
|
||||||
curve: CurveFp, // 椭圆曲线的参数
|
curve: &'a CurveFp, // 椭圆曲线的参数
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the SM2 Curve
|
// Initialize the SM2 Curve
|
||||||
@ -68,105 +68,35 @@ fn sm2p256v1() -> CurveFp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the greatest common divisor (GCD) of two `BigUint` numbers.
|
fn point_addition<'a>(p1: &'a Point<'a>, p2: &'a Point<'a>) -> Point<'a> {
|
||||||
///
|
// 如果 p1 是零点,返回一个新构造的 p2 点,而不是克隆
|
||||||
/// The function uses the Euclidean algorithm to compute the GCD. The algorithm is based on
|
|
||||||
/// the principle that the greatest common divisor of two numbers does not change if the larger
|
|
||||||
/// number is replaced by its difference with the smaller number.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `a` - The first `BigUint` number.
|
|
||||||
/// * `b` - The second `BigUint` number.
|
|
||||||
///
|
|
||||||
/// # Returns
|
|
||||||
///
|
|
||||||
/// * `BigUint` - The greatest common divisor of `a` and `b`.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// let a = BigUint::from(60u32);
|
|
||||||
/// let b = BigUint::from(48u32);
|
|
||||||
/// let result = gcd(a, b);
|
|
||||||
/// assert_eq!(result, BigUint::from(12u32));
|
|
||||||
/// ```
|
|
||||||
fn gcd(a: &BigUint, b: &BigUint) -> BigUint {
|
|
||||||
let mut c = a.clone();
|
|
||||||
let mut d = b.clone();
|
|
||||||
while !a.is_zero() {
|
|
||||||
let temp = c.clone();
|
|
||||||
c = d % c;
|
|
||||||
d = temp;
|
|
||||||
}
|
|
||||||
d
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the modular inverse of `a` under modulo `m`.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `a` - A reference to a BigUint representing the number to find the modular inverse of.
|
|
||||||
/// * `p` - A reference to a BigUint representing the modulus.
|
|
||||||
///
|
|
||||||
/// # Return1
|
|
||||||
///
|
|
||||||
/// * A BigUint representing the modular inverse of `a` modulo `p`.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// This function will panic if the modular inverse does not exist (i.e., if `a` and `p` are not coprime).
|
|
||||||
fn mod_inverse(a: &BigUint, m: &BigUint) -> BigUint {
|
|
||||||
let (mut t, mut new_t) = (BigUint::zero(), BigUint::one());
|
|
||||||
let (mut r, mut new_r) = (m.clone(), a.clone());
|
|
||||||
|
|
||||||
while !new_r.is_zero() {
|
|
||||||
let quotient = &r / &new_r;
|
|
||||||
|
|
||||||
let temp_t = new_t.clone();
|
|
||||||
new_t = if t < (quotient.clone() * &temp_t) {
|
|
||||||
// BigUint can't be negative,
|
|
||||||
// so we use mod to handle the case where t < quotient * temp_t
|
|
||||||
(&t + m - &(quotient.clone() * &temp_t) % m) % m
|
|
||||||
} else {
|
|
||||||
&t - &(quotient.clone() * &temp_t)
|
|
||||||
};
|
|
||||||
|
|
||||||
let temp_r = new_r.clone();
|
|
||||||
new_r = &r - &(quotient.clone() * &temp_r);
|
|
||||||
r = temp_r;
|
|
||||||
t = temp_t;
|
|
||||||
}
|
|
||||||
|
|
||||||
if r > BigUint::one() {
|
|
||||||
panic!("Modular inverse does not exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
if t < BigUint::zero() {
|
|
||||||
t += m;
|
|
||||||
}
|
|
||||||
|
|
||||||
t
|
|
||||||
}
|
|
||||||
|
|
||||||
fn point_addition(p1: &Point, p2: &Point) -> Point {
|
|
||||||
if p1.x.is_zero() && p1.y.is_zero() {
|
if p1.x.is_zero() && p1.y.is_zero() {
|
||||||
return p2.clone();
|
return Point {
|
||||||
|
x: p2.x.clone(),
|
||||||
|
y: p2.y.clone(),
|
||||||
|
curve: p2.curve, // 如果 curve 是引用,保持引用即可
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果 p2 是零点,返回一个新构造的 p1 点,而不是克隆
|
||||||
if p2.x.is_zero() && p2.y.is_zero() {
|
if p2.x.is_zero() && p2.y.is_zero() {
|
||||||
return p1.clone();
|
return Point {
|
||||||
|
x: p1.x.clone(),
|
||||||
|
y: p1.y.clone(),
|
||||||
|
curve: p1.curve, // 如果 curve 是引用,保持引用即可
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
from_jacobian(jacobian_add(to_jacobian(p1), to_jacobian(p2)))
|
from_jacobian(jacobian_add(to_jacobian(p1), to_jacobian(p2)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 将仿射坐标转换为雅可比坐标 (X, Y, Z)
|
/// 将仿射坐标转换为雅可比坐标 (X, Y, Z)
|
||||||
fn to_jacobian(p: &Point) -> JacobianPoint {
|
fn to_jacobian<'a>(p: &'a Point) -> JacobianPoint<'a> {
|
||||||
JacobianPoint {
|
JacobianPoint {
|
||||||
x: p.x.clone(),
|
x: p.x.clone(),
|
||||||
y: p.y.clone(),
|
y: p.y.clone(),
|
||||||
z: BigUint::one(), // Z = 1 表示仿射坐标
|
z: BigUint::one(), // Z = 1 表示仿射坐标
|
||||||
curve: sm2p256v1(),
|
curve: p.curve,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,13 +106,13 @@ fn from_jacobian(p: JacobianPoint) -> Point {
|
|||||||
return Point {
|
return Point {
|
||||||
x: BigUint::zero(),
|
x: BigUint::zero(),
|
||||||
y: BigUint::zero(),
|
y: BigUint::zero(),
|
||||||
curve: sm2p256v1(),
|
curve: p.curve,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let p_mod = &p.curve.p;
|
let p_mod = &p.curve.p;
|
||||||
|
|
||||||
// 计算 Z 的模反
|
// 计算 Z 的模反
|
||||||
let z_inv = mod_inverse(&p.z, p_mod);
|
let z_inv = p.z.modinv(p_mod).expect("modinv failed");
|
||||||
let z_inv2 = (&z_inv * &z_inv) % p_mod; // Z_inv^2
|
let z_inv2 = (&z_inv * &z_inv) % p_mod; // Z_inv^2
|
||||||
let z_inv3 = (&z_inv2 * &z_inv) % p_mod; // Z_inv^3
|
let z_inv3 = (&z_inv2 * &z_inv) % p_mod; // Z_inv^3
|
||||||
|
|
||||||
@ -193,12 +123,12 @@ fn from_jacobian(p: JacobianPoint) -> Point {
|
|||||||
Point {
|
Point {
|
||||||
x: x_affine,
|
x: x_affine,
|
||||||
y: y_affine,
|
y: y_affine,
|
||||||
curve: sm2p256v1(),
|
curve: p.curve,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 雅可比坐标下的点加法
|
/// 雅可比坐标下的点加法
|
||||||
fn jacobian_add(p1: JacobianPoint, p2: JacobianPoint) -> JacobianPoint {
|
fn jacobian_add<'a>(p1: JacobianPoint<'a>, p2: JacobianPoint<'a>) -> JacobianPoint<'a> {
|
||||||
if p1.z.is_zero() {
|
if p1.z.is_zero() {
|
||||||
return p2.clone();
|
return p2.clone();
|
||||||
}
|
}
|
||||||
@ -245,21 +175,20 @@ fn jacobian_add(p1: JacobianPoint, p2: JacobianPoint) -> JacobianPoint {
|
|||||||
x: x3,
|
x: x3,
|
||||||
y: y3,
|
y: y3,
|
||||||
z: z3,
|
z: z3,
|
||||||
curve: sm2p256v1(),
|
curve: p1.curve,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 雅可比坐标下的点倍运算
|
/// 雅可比坐标下的点倍运算
|
||||||
fn jacobian_double(p: JacobianPoint) -> JacobianPoint {
|
fn jacobian_double(p: JacobianPoint) -> JacobianPoint {
|
||||||
let curve = &p.curve;
|
let p_mod = &p.curve.p;
|
||||||
let p_mod = &curve.p;
|
|
||||||
|
|
||||||
if p.y.is_zero() {
|
if p.y.is_zero() {
|
||||||
return JacobianPoint {
|
return JacobianPoint {
|
||||||
x: BigUint::zero(),
|
x: BigUint::zero(),
|
||||||
y: BigUint::zero(),
|
y: BigUint::zero(),
|
||||||
z: BigUint::zero(),
|
z: BigUint::zero(),
|
||||||
curve: curve.clone(),
|
curve: p.curve,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +199,7 @@ fn jacobian_double(p: JacobianPoint) -> JacobianPoint {
|
|||||||
// M = 3 * X^2 + a * Z^4
|
// M = 3 * X^2 + a * Z^4
|
||||||
let z2 = (&p.z * &p.z) % p_mod;
|
let z2 = (&p.z * &p.z) % p_mod;
|
||||||
let z4 = (&z2 * &z2) % p_mod;
|
let z4 = (&z2 * &z2) % p_mod;
|
||||||
let m = ((&p.x * &p.x * BigUint::from(3u32)) + &curve.a * &z4) % p_mod;
|
let m = ((&p.x * &p.x * BigUint::from(3u32)) + &p.curve.a * &z4) % p_mod;
|
||||||
|
|
||||||
// X3 = M^2 - 2 * S
|
// X3 = M^2 - 2 * S
|
||||||
let x3 = (&m * &m + p_mod - &s * BigUint::from(2u32)) % p_mod;
|
let x3 = (&m * &m + p_mod - &s * BigUint::from(2u32)) % p_mod;
|
||||||
@ -286,16 +215,16 @@ fn jacobian_double(p: JacobianPoint) -> JacobianPoint {
|
|||||||
x: x3,
|
x: x3,
|
||||||
y: y3,
|
y: y3,
|
||||||
z: z3,
|
z: z3,
|
||||||
curve: curve.clone(),
|
curve: p.curve,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn point_multiplication(p: &Point, n: &BigUint) -> Point {
|
fn point_multiplication<'a>(p: &'a Point<'a>, n: &BigUint) -> Point<'a> {
|
||||||
let mut result = JacobianPoint {
|
let mut result = JacobianPoint {
|
||||||
x: BigUint::zero(),
|
x: BigUint::zero(),
|
||||||
y: BigUint::one(), // 无穷远点的雅可比坐标表示
|
y: BigUint::one(), // 无穷远点的雅可比坐标表示
|
||||||
z: BigUint::zero(),
|
z: BigUint::zero(),
|
||||||
curve: p.curve.clone(),
|
curve: p.curve,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 将输入点从仿射坐标转换为雅可比坐标
|
// 将输入点从仿射坐标转换为雅可比坐标
|
||||||
@ -336,13 +265,13 @@ fn add(p1: (BigUint, BigUint), p2: (BigUint, BigUint)) -> (BigUint, BigUint) {
|
|||||||
let point1 = Point {
|
let point1 = Point {
|
||||||
x: x1,
|
x: x1,
|
||||||
y: y1,
|
y: y1,
|
||||||
curve: sm2p256v1(),
|
curve: &curve,
|
||||||
};
|
};
|
||||||
|
|
||||||
let point2 = Point {
|
let point2 = Point {
|
||||||
x: x2,
|
x: x2,
|
||||||
y: y2,
|
y: y2,
|
||||||
curve: sm2p256v1(),
|
curve: &curve,
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = point_addition(&point1, &point2);
|
let result = point_addition(&point1, &point2);
|
||||||
@ -367,7 +296,7 @@ fn multiply(point: (BigUint, BigUint), mut n: BigUint) -> (BigUint, BigUint) {
|
|||||||
let point = Point {
|
let point = Point {
|
||||||
x: point.0,
|
x: point.0,
|
||||||
y: point.1,
|
y: point.1,
|
||||||
curve,
|
curve: &curve,
|
||||||
};
|
};
|
||||||
// Perform point multiplication
|
// Perform point multiplication
|
||||||
let result = point_multiplication(&point, &n);
|
let result = point_multiplication(&point, &n);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user