-
Notifications
You must be signed in to change notification settings - Fork 0
/
curve25519.rs
107 lines (94 loc) · 2.64 KB
/
curve25519.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use hacspec_lib::*;
public_nat_mod!(
type_name: FieldElement,
type_of_canvas: FieldCanvas,
bit_size_of_field: 256,
modulo_value: "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed"
);
public_nat_mod!(
type_name: Scalar,
type_of_canvas: ScalarCanvas,
bit_size_of_field: 256,
modulo_value: "8000000000000000000000000000000000000000000000000000000000000000"
);
type Point = (FieldElement, FieldElement);
bytes!(SerializedPoint, 32);
bytes!(SerializedScalar, 32);
fn mask_scalar(s: SerializedScalar) -> SerializedScalar {
let mut k = s;
k[0] = k[0] & U8(248u8);
k[31] = k[31] & U8(127u8);
k[31] = k[31] | U8(64u8);
k
}
fn decode_scalar(s: SerializedScalar) -> Scalar {
let k = mask_scalar(s);
Scalar::from_byte_seq_le(k)
}
fn decode_point(u: SerializedPoint) -> Point {
let mut u_ = u;
u_[31] = u_[31] & U8(127u8);
(
FieldElement::from_byte_seq_le(u_),
FieldElement::from_literal(1u128),
)
}
fn encode_point(p: Point) -> SerializedPoint {
let (x, y) = p;
let b = x * y.inv();
SerializedPoint::new().update_start(&b.to_byte_seq_le())
}
fn point_add_and_double(q: Point, np: (Point, Point)) -> (Point, Point) {
let (nq, nqp1) = np;
let (x_1, _z_1) = q;
let (x_2, z_2) = nq;
let (x_3, z_3) = nqp1;
let a = x_2 + z_2;
let aa = a.pow(2u128);
let b = x_2 - z_2;
let bb = b * b;
let e = aa - bb;
let c = x_3 + z_3;
let d = x_3 - z_3;
let da = d * a;
let cb = c * b;
let x_3 = (da + cb).pow(2u128);
let z_3 = x_1 * ((da - cb).pow(2u128));
let x_2 = aa * bb;
let e121665 = FieldElement::from_literal(121_665u128);
let z_2 = e * (aa + (e121665 * e));
((x_2, z_2), (x_3, z_3))
}
fn swap(x: (Point, Point)) -> (Point, Point) {
let (x0, x1) = x;
(x1, x0)
}
fn montgomery_ladder(k: Scalar, init: Point) -> Point {
let inf = (
FieldElement::from_literal(1u128),
FieldElement::from_literal(0u128),
);
let mut acc: (Point, Point) = (inf, init);
for i in 0..256 {
if k.bit(255 - i) {
acc = swap(acc);
acc = point_add_and_double(init, acc);
acc = swap(acc);
} else {
acc = point_add_and_double(init, acc);
}
}
let (out, _) = acc;
out
}
pub fn scalarmult(s: SerializedScalar, p: SerializedPoint) -> SerializedPoint {
let s_ = decode_scalar(s);
let p_ = decode_point(p);
let r = montgomery_ladder(s_, p_);
encode_point(r)
}
pub fn secret_to_public(s: SerializedScalar) -> SerializedPoint {
let mut base = SerializedPoint::new();
base[0] = U8(0x09u8);
scalarmult(s, base)
}