Compare commits

..

No commits in common. "116fd34fc912614acf4dd8c90fafc28ae58d23f5" and "082adec86ba63ed7016b7c6cf246a5245cd3e5d6" have entirely different histories.

9 changed files with 91 additions and 491 deletions

BIN
.DS_Store vendored

Binary file not shown.

393
Cargo.lock generated
View file

@ -2,62 +2,27 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 version = 4
[[package]]
name = "anyhow"
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.5.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "bitflags"
version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.4" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "cmov"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de0758edba32d61d1fd9f4d69491b47604b91ee2f7e6b33de7e54ca4ebe55dc3"
[[package]]
name = "cpubits"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ef0c543070d296ea414df2dd7625d1b24866ce206709d8a4a424f28377f5861"
[[package]] [[package]]
name = "crypto-bigint" name = "crypto-bigint"
version = "0.7.1" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fde2467e74147f492aebb834985186b2c74761927b8b9b3bd303bcb2e72199d" checksum = "96272c2ff28b807e09250b180ad1fb7889a3258f7455759b5c3c58b719467130"
dependencies = [ dependencies = [
"cpubits",
"ctutils",
"getrandom",
"num-traits", "num-traits",
"rand_core", "rand_core",
] "subtle",
[[package]]
name = "ctutils"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1005a6d4446f5120ef475ad3d2af2b30c49c2c9c6904258e3bb30219bebed5e4"
dependencies = [
"cmov",
] ]
[[package]] [[package]]
@ -68,100 +33,22 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "foldhash"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.4.2" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"r-efi", "wasi",
"rand_core",
"wasip2",
"wasip3",
] ]
[[package]]
name = "hashbrown"
version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"foldhash",
]
[[package]]
name = "hashbrown"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "id-arena"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
[[package]]
name = "indexmap"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
[[package]]
name = "itoa"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "leb128fmt"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.186" version = "0.2.176"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
[[package]]
name = "log"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "memchr"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]] [[package]]
name = "num-traits" name = "num-traits"
@ -172,271 +59,29 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "prettyplease"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]] [[package]]
name = "rand_core" name = "rand_core"
version = "0.10.0" version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "semver"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [ dependencies = [
"serde_core", "getrandom",
] ]
[[package]] [[package]]
name = "serde_core" name = "subtle"
version = "1.0.228" version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
dependencies = [
"serde_derive",
]
[[package]] [[package]]
name = "serde_derive" name = "wasi"
version = "1.0.228" version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
dependencies = [
"itoa",
"memchr",
"serde",
"serde_core",
"zmij",
]
[[package]]
name = "syn"
version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "wasip2"
version = "1.0.3+wasi-0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
dependencies = [
"wit-bindgen 0.57.1",
]
[[package]]
name = "wasip3"
version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
dependencies = [
"wit-bindgen 0.51.0",
]
[[package]]
name = "wasm-encoder"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
dependencies = [
"leb128fmt",
"wasmparser",
]
[[package]]
name = "wasm-metadata"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
dependencies = [
"anyhow",
"indexmap",
"wasm-encoder",
"wasmparser",
]
[[package]]
name = "wasmparser"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
dependencies = [
"bitflags",
"hashbrown 0.15.5",
"indexmap",
"semver",
]
[[package]]
name = "wit-bindgen"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
dependencies = [
"wit-bindgen-rust-macro",
]
[[package]]
name = "wit-bindgen"
version = "0.57.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
[[package]]
name = "wit-bindgen-core"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
dependencies = [
"anyhow",
"heck",
"wit-parser",
]
[[package]]
name = "wit-bindgen-rust"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
dependencies = [
"anyhow",
"heck",
"indexmap",
"prettyplease",
"syn",
"wasm-metadata",
"wit-bindgen-core",
"wit-component",
]
[[package]]
name = "wit-bindgen-rust-macro"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
dependencies = [
"anyhow",
"prettyplease",
"proc-macro2",
"quote",
"syn",
"wit-bindgen-core",
"wit-bindgen-rust",
]
[[package]]
name = "wit-component"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
dependencies = [
"anyhow",
"bitflags",
"indexmap",
"log",
"serde",
"serde_derive",
"serde_json",
"wasm-encoder",
"wasm-metadata",
"wasmparser",
"wit-parser",
]
[[package]]
name = "wit-parser"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
dependencies = [
"anyhow",
"id-arena",
"indexmap",
"log",
"semver",
"serde",
"serde_derive",
"serde_json",
"unicode-xid",
"wasmparser",
]
[[package]] [[package]]
name = "zeroize" name = "zeroize"
version = "1.8.2" version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
[[package]]
name = "zmij"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"

View file

@ -4,11 +4,11 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
crypto-bigint = { version = "0.7.1", features = ["getrandom"] } crypto-bigint = { version = "0.6.1" }
zeroize = { version = "1.8.2", optional = true } zeroize = { version = "1.8.2", optional = true }
[features] [features]
rand = ["crypto-bigint/rand_core"] rand = ["crypto-bigint/rand"]
edwards = [] edwards = []
zeroize = ["dep:zeroize"] zeroize = ["dep:zeroize"]

View file

@ -1,22 +1,22 @@
use crate::traits::{Curve, Point}; use crate::traits::{Curve, Point};
use crypto_bigint::{AddMod, BitOps, ConstZero, Integer, InvertMod, MulMod, NonZero, SubMod, U448}; use crypto_bigint::{AddMod, ConstZero, Integer, InvMod, MulMod, NonZero, SubMod, U448};
use std::ops::Div; use std::ops::Div;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct EdwardsCurve<N> pub struct EdwardsCurve<N>
where where
N: AddMod<Output = N> + SubMod<Output = N> + MulMod<Output = N> + InvertMod<Output = N> + Copy, N: AddMod<Output = N> + SubMod<Output = N> + MulMod<Output = N> + InvMod<Output = N> + Copy,
{ {
pub d: N, pub d: N,
pub p: NonZero<N>, pub p: N,
generator_x: N, generator_x: N,
generator_y: N, generator_y: N,
} }
/// The edwards curve Ed448-Goldilocks /// The edwards curve Ed448-Goldilocks
pub const ED448_MOD: NonZero<U448> = NonZero::<U448>::new_unwrap(U448::ONE pub const ED448_MOD: U448 = U448::ONE
.sub_mod(&U448::ONE.shl(224), &NonZero::<U448>::new_unwrap(U448::MAX)) .sub_mod(&U448::ONE.shl(224), &U448::MAX)
.sub_mod(&U448::ONE, &NonZero::<U448>::new_unwrap(U448::MAX))); .sub_mod(&U448::ONE, &U448::MAX);
pub const ED448_GOLDILOCKS: EdwardsCurve<U448> = EdwardsCurve::new( pub const ED448_GOLDILOCKS: EdwardsCurve<U448> = EdwardsCurve::new(
U448::ZERO.sub_mod(&U448::from_u16(39081), &ED448_MOD), U448::ZERO.sub_mod(&U448::from_u16(39081), &ED448_MOD),
ED448_MOD, ED448_MOD,
@ -43,13 +43,13 @@ where
N: AddMod<Output = N> N: AddMod<Output = N>
+ SubMod<Output = N> + SubMod<Output = N>
+ MulMod<Output = N> + MulMod<Output = N>
+ InvertMod<Output = N> + InvMod<Output = N>
+ Copy + Copy
+ ConstZero + ConstZero
+ crypto_bigint::CtEq + crypto_bigint::subtle::ConstantTimeEq
+ From<u8>, + From<u8>,
{ {
pub const fn new(d: N, p: NonZero<N>, x: N, y: N) -> EdwardsCurve<N> { pub const fn new(d: N, p: N, x: N, y: N) -> EdwardsCurve<N> {
EdwardsCurve { EdwardsCurve {
d, d,
p, p,
@ -64,12 +64,11 @@ where
N: AddMod<Output = N> N: AddMod<Output = N>
+ SubMod<Output = N> + SubMod<Output = N>
+ MulMod<Output = N> + MulMod<Output = N>
+ InvertMod<Output = N> + InvMod<Output = N>
+ Integer + Integer
+ Copy + Copy
+ ConstZero + ConstZero
+ Div<Output = N> + Div<Output = N>,
+ BitOps + std::convert::From<u8>,
{ {
fn point(self, x: N) -> EdwardsPoint<N> { fn point(self, x: N) -> EdwardsPoint<N> {
EdwardsPoint { EdwardsPoint {
@ -93,7 +92,7 @@ where
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct EdwardsPoint<N> pub struct EdwardsPoint<N>
where where
N: AddMod<Output = N> + SubMod<Output = N> + MulMod<Output = N> + InvertMod<Output = N> + Copy, N: AddMod<Output = N> + SubMod<Output = N> + MulMod<Output = N> + InvMod<Output = N> + Copy,
{ {
x: N, x: N,
y: N, y: N,
@ -106,18 +105,17 @@ where
N: AddMod<Output = N> N: AddMod<Output = N>
+ SubMod<Output = N> + SubMod<Output = N>
+ MulMod<Output = N> + MulMod<Output = N>
+ InvertMod<Output = N> + InvMod<Output = N>
+ Copy + Copy
+ crypto_bigint::CtEq + crypto_bigint::subtle::ConstantTimeEq
+ From<u8> + From<u8>
+ Integer + Integer
+ Div<Output = N> + Div<Output = N>,
+ BitOps,
{ {
fn get_x(self) -> N { fn get_x(self) -> N {
self.x.mul_mod( self.x.mul_mod(
&self.z.invert_mod(&self.curve.p).unwrap(), &self.z.inv_mod(&self.curve.p).unwrap(),
&self.curve.p, &NonZero::new(self.curve.p).unwrap(),
) )
} }
@ -199,14 +197,14 @@ where
N: AddMod<Output = N> N: AddMod<Output = N>
+ SubMod<Output = N> + SubMod<Output = N>
+ MulMod<Output = N> + MulMod<Output = N>
+ InvertMod<Output = N> + InvMod<Output = N>
+ Copy + Copy
+ ConstZero + ConstZero
+ crypto_bigint::CtEq, + crypto_bigint::subtle::ConstantTimeEq,
{ {
pub fn get_y(self) -> N { pub fn get_y(self) -> N {
self.y self.y
.mul_mod(&self.z.invert_mod(&self.curve.p).unwrap(), &self.curve.p) .mul_mod(&self.z.inv_mod(&self.curve.p).unwrap(), &self.curve.p)
} }
} }
@ -214,7 +212,7 @@ ladder_impl!(EdwardsPoint, swap_edwards);
fn swap_edwards<N>(a: &mut EdwardsPoint<N>, b: &mut EdwardsPoint<N>, c: u8, max: N) fn swap_edwards<N>(a: &mut EdwardsPoint<N>, b: &mut EdwardsPoint<N>, c: u8, max: N)
where where
N: AddMod<Output = N> + SubMod<Output = N> + MulMod<Output = N> + InvertMod<Output = N> + Copy + Integer + std::ops::Div<Output = N> + From<u8>, N: AddMod + SubMod + MulMod + InvMod<Output = N> + Copy + Integer + std::ops::Div<Output = N>,
{ {
let m = max * N::from(c); let m = max * N::from(c);

View file

@ -6,10 +6,13 @@ pub mod edwards;
pub mod montgomery; pub mod montgomery;
pub mod traits; pub mod traits;
pub use crypto_bigint::{Encoding, NonZero, U256}; use crypto_bigint::subtle::{Choice, ConstantTimeEq};
pub use crypto_bigint::{ConstChoice, Encoding, NonZero, U256};
#[cfg(feature = "rand")]
use crypto_bigint::{rand_core::OsRng, Random};
use crate::traits::{Curve, Point}; use crate::traits::{Curve, Point};
use crypto_bigint::{Choice, CtEq, EncodedUint, Random};
pub(crate) use montgomery::*; pub(crate) use montgomery::*;
#[derive(Debug, Clone, Copy, Eq, PartialEq)] #[derive(Debug, Clone, Copy, Eq, PartialEq)]
@ -26,13 +29,13 @@ impl From<&Secret> for Public {
impl From<[u8; 32]> for Public { impl From<[u8; 32]> for Public {
fn from(bytes: [u8; 32]) -> Public { fn from(bytes: [u8; 32]) -> Public {
Public(U256::from_le_bytes(EncodedUint::from(bytes))) Public(U256::from_le_bytes(bytes))
} }
} }
impl Public { impl Public {
pub fn as_bytes(&self) -> [u8; 32] { pub fn as_bytes(&self) -> [u8; 32] {
self.0.to_le_bytes().into() self.0.to_le_bytes()
} }
} }
@ -43,14 +46,14 @@ pub struct Secret(U256);
impl Secret { impl Secret {
#[cfg(feature = "rand")] #[cfg(feature = "rand")]
pub fn random() -> Secret { pub fn random() -> Secret {
Secret::from(U256::random()) Secret::from(U256::random(&mut OsRng))
} }
pub fn diffie_hellman(&self, public: &Public) -> SharedSecret { pub fn diffie_hellman(&self, public: &Public) -> SharedSecret {
let point = CURVE_25519.point(public.0); let point = CURVE_25519.point(public.0);
let p = point * self.0; let p = point * self.0;
SharedSecret(p.get_x().to_le_bytes().into()) SharedSecret(p.get_x().to_le_bytes())
} }
} }
@ -69,7 +72,7 @@ impl SharedSecret {
} }
} }
impl CtEq for SharedSecret { impl ConstantTimeEq for SharedSecret {
fn ct_eq(&self, other: &Self) -> Choice { fn ct_eq(&self, other: &Self) -> Choice {
self.0.ct_eq(&other.0) self.0.ct_eq(&other.0)
} }
@ -84,7 +87,7 @@ mod tests {
fn random_secret() { fn random_secret() {
let secret = Secret::random(); let secret = Secret::random();
assert!(secret.0 < CURVE_25519.p.get()); assert!(secret.0 < CURVE_25519.p);
} }
#[test] #[test]
@ -106,7 +109,7 @@ mod tests {
let x_k = let x_k =
U256::from_be_hex("0933dc6ed7122bdf2a5f1b0516e218b743868769778787cfa1ac0ae2dfa89891"); U256::from_be_hex("0933dc6ed7122bdf2a5f1b0516e218b743868769778787cfa1ac0ae2dfa89891");
assert_eq!(x.0, <[u8; 32]>::from(x_k.to_le_bytes())); assert_eq!(x.0, x_k.to_le_bytes());
} }
#[test] #[test]
@ -122,9 +125,6 @@ mod tests {
let sa = a.diffie_hellman(&pb); let sa = a.diffie_hellman(&pb);
let sb = b.diffie_hellman(&pa); let sb = b.diffie_hellman(&pa);
assert!( assert!(bool::from(sa.ct_eq(&sb)));
bool::from(sa.ct_eq(&sb)),
"Didn't compute same shared secret"
);
} }
} }

View file

@ -1,17 +1,15 @@
#[macro_export] #[macro_export]
macro_rules! ladder_impl { macro_rules! ladder_impl {
($point:ident, $swap_fn:ident) => { ($point:ident, $swap_fn:ident) => {
impl<N: BitOps> $point<N> impl<N> $point<N>
where where
N: AddMod<Output = N> N: AddMod
+ SubMod<Output = N> + SubMod
+ MulMod<Output = N> + MulMod<Output = N>
+ InvertMod<Output = N> + InvMod<Output = N>
+ Copy + Copy
+ Integer + Integer
+ Div<Output = N>, + Div<Output = N>,
N: std::convert::From<u8>,
{ {
pub fn ladder(&self, rhs: &N) -> $point<N> { pub fn ladder(&self, rhs: &N) -> $point<N> {
let mut x_0 = *self; let mut x_0 = *self;

View file

@ -1,7 +1,6 @@
use crate::traits::{Curve, Point}; use crate::traits::{Curve, Point};
use crypto_bigint::{AddMod, EncodedUint, Encoding, InvertMod, NonZero, SubMod, U256}; use crypto_bigint::{AddMod, Encoding, NonZero, SubMod, U256};
use crypto_bigint::{BitOps, Uint}; use crypto_bigint::{Integer, InvMod, MulMod};
use crypto_bigint::{Integer, MulMod};
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::ops::{BitXor, Div, Mul}; use std::ops::{BitXor, Div, Mul};
@ -9,23 +8,18 @@ use std::ops::{BitXor, Div, Mul};
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct MontgomeryCurve<N> pub struct MontgomeryCurve<N>
where where
N: AddMod + SubMod + MulMod + InvertMod + Integer + Copy, N: AddMod + SubMod + MulMod + InvMod + Integer + Copy,
{ {
pub a: N, pub a: N,
pub b: N, pub b: N,
pub p: NonZero<N>, pub p: N,
} }
impl<N> MontgomeryCurve<N> impl<N> MontgomeryCurve<N>
where where
N: AddMod<Output = N> N: AddMod + SubMod + MulMod + InvMod + Copy + Integer,
+ SubMod<Output = N>
+ MulMod<Output = N>
+ InvertMod<Output = N>
+ Copy
+ Integer,
{ {
pub const fn new(a: N, b: N, p: NonZero<N>) -> MontgomeryCurve<N> { pub const fn new(a: N, b: N, p: N) -> MontgomeryCurve<N> {
MontgomeryCurve { a, b, p } MontgomeryCurve { a, b, p }
} }
@ -42,15 +36,7 @@ where
impl<N> Curve<MontgomeryPoint<N>, N> for MontgomeryCurve<N> impl<N> Curve<MontgomeryPoint<N>, N> for MontgomeryCurve<N>
where where
N: AddMod<Output = N> N: AddMod + SubMod + MulMod + InvMod<Output = N> + Copy + Integer + Div<Output = N>,
+ SubMod<Output = N>
+ MulMod<Output = N>
+ InvertMod<Output = N>
+ Copy
+ Integer
+ Div<Output = N>
+ std::convert::From<u8>
+ BitOps,
{ {
/// Get the point at an x-coordinate with parameters from this curve. /// Get the point at an x-coordinate with parameters from this curve.
fn point(self, x: N) -> MontgomeryPoint<N> { fn point(self, x: N) -> MontgomeryPoint<N> {
@ -67,27 +53,20 @@ where
} }
pub fn clamp_u256(x: U256) -> U256 { pub fn clamp_u256(x: U256) -> U256 {
let mut bytes: [u8; 32] = x.to_le_bytes().into(); let mut bytes: [u8; 32] = x.to_le_bytes();
// clamp value // clamp value
bytes[0] &= 248; bytes[0] &= 248;
bytes[31] &= 127; bytes[31] &= 127;
bytes[31] |= 64; bytes[31] |= 64;
U256::from_le_bytes(EncodedUint::from(bytes)) U256::from_le_bytes(bytes)
} }
#[derive(Copy, Debug, Clone)] #[derive(Copy, Debug, Clone)]
pub struct MontgomeryPoint<N> pub struct MontgomeryPoint<N>
where where
N: AddMod<Output = N> N: AddMod + SubMod + Div<Output = N> + MulMod<Output = N> + InvMod<Output = N> + Copy + Integer,
+ SubMod<Output = N>
+ Div<Output = N>
+ MulMod<Output = N>
+ InvertMod<Output = N>
+ Copy
+ Integer
+ From<u8>,
{ {
pub x: N, pub x: N,
pub z: N, pub z: N,
@ -97,23 +76,24 @@ where
impl<N> Point<N> for MontgomeryPoint<N> impl<N> Point<N> for MontgomeryPoint<N>
where where
N: AddMod<Output = N> N: AddMod
+ SubMod<Output = N> + SubMod
+ Div<Output = N> + Div<Output = N>
+ MulMod<Output = N> + MulMod<Output = N>
+ InvertMod<Output = N> + InvMod<Output = N>
+ Copy + Copy
+ Integer + Integer
+ From<u8> + From<u8>,
+ BitOps,
{ {
fn get_x(self) -> N { fn get_x(self) -> N {
self.x self.x.mul_mod(
.mul_mod(&self.z.invert_mod(&self.curve.p).unwrap(), &self.curve.p) &self.z.inv_mod(&self.curve.p).unwrap(),
&NonZero::new(self.curve.p).unwrap(),
)
} }
fn add(&self, rhs: &Self, neg: &Self) -> Self { fn add(&self, rhs: &Self, neg: &Self) -> Self {
let p = &self.curve.p; let p = &NonZero::new(self.curve.p).unwrap();
let mut v_0 = self.x.add_mod(&self.z, p); // 1: V_0 = X_P + Z_P let mut v_0 = self.x.add_mod(&self.z, p); // 1: V_0 = X_P + Z_P
let mut v_1 = rhs.x.sub_mod(&rhs.z, p); // 2: V_1 = X_Q - Z_Q let mut v_1 = rhs.x.sub_mod(&rhs.z, p); // 2: V_1 = X_Q - Z_Q
@ -140,7 +120,7 @@ where
} }
fn double(&self) -> MontgomeryPoint<N> { fn double(&self) -> MontgomeryPoint<N> {
let p = &self.curve.p; let p = &NonZero::new(self.curve.p).unwrap();
let mut v_1 = self.x.add_mod(&self.z, p); let mut v_1 = self.x.add_mod(&self.z, p);
v_1 = v_1.mul_mod(&v_1, p); v_1 = v_1.mul_mod(&v_1, p);
@ -182,16 +162,7 @@ ladder_impl!(MontgomeryPoint, swap_montgomery);
fn swap_montgomery<N>(a: &mut MontgomeryPoint<N>, b: &mut MontgomeryPoint<N>, c: u8, max: N) fn swap_montgomery<N>(a: &mut MontgomeryPoint<N>, b: &mut MontgomeryPoint<N>, c: u8, max: N)
where where
N: BitXor N: BitXor + Copy + Mul<Output = N> + From<u8> + Div<Output = N> + Integer + InvMod<Output = N>,
+ Copy
+ Mul<Output = N>
+ From<u8>
+ Div<Output = N>
+ Integer
+ InvertMod<Output = N>
+ AddMod<Output = N>
+ MulMod<Output = N>
+ SubMod<Output = N>,
{ {
let m = max * N::from(c); let m = max * N::from(c);
@ -207,15 +178,14 @@ where
impl<N> Display for MontgomeryPoint<N> impl<N> Display for MontgomeryPoint<N>
where where
N: AddMod<Output = N> N: AddMod
+ SubMod<Output = N> + SubMod
+ MulMod<Output = N> + MulMod
+ InvertMod<Output = N> + InvMod<Output = N>
+ Copy + Copy
+ Integer + Integer
+ Display + Display
+ Div<Output = N> + std::ops::Div<Output = N>,
+ From<u8>,
{ {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("({} : {})", self.x, self.z)) f.write_fmt(format_args!("({} : {})", self.x, self.z))
@ -224,15 +194,7 @@ where
impl<N> Mul<N> for MontgomeryPoint<N> impl<N> Mul<N> for MontgomeryPoint<N>
where where
N: AddMod<Output = N> N: AddMod + SubMod + MulMod + InvMod<Output = N> + Copy + Integer + std::ops::Div<Output = N>,
+ SubMod<Output = N>
+ MulMod<Output = N>
+ InvertMod<Output = N>
+ Copy
+ Integer
+ Div<Output = N>
+ std::convert::From<u8>
+ BitOps,
{ {
type Output = MontgomeryPoint<N>; type Output = MontgomeryPoint<N>;
@ -249,10 +211,7 @@ where
pub const CURVE_25519: MontgomeryCurve<U256> = MontgomeryCurve::new( pub const CURVE_25519: MontgomeryCurve<U256> = MontgomeryCurve::new(
U256::from_u32(486662u32), U256::from_u32(486662u32),
U256::ONE, U256::ONE,
NonZero::<Uint<4>>::new_unwrap(U256::ONE.shl(255).sub_mod( U256::ONE.shl(255).sub_mod(&U256::from_u8(19), &U256::MAX),
&U256::from_u8(19),
&NonZero::<Uint<4>>::new_unwrap(U256::MAX),
)),
); );
#[cfg(test)] #[cfg(test)]

View file

@ -1,9 +1,9 @@
use crypto_bigint::{AddMod, InvertMod, MulMod, SubMod}; use crypto_bigint::{AddMod, InvMod, MulMod, SubMod};
pub trait Curve<T, N> pub trait Curve<T, N>
where where
T: Point<N>, T: Point<N>,
N: AddMod<Output = N> + SubMod<Output = N> + MulMod<Output = N> + InvertMod<Output = N> + Copy, N: AddMod<Output = N> + SubMod<Output = N> + MulMod<Output = N> + InvMod<Output = N> + Copy,
{ {
fn point(self, x: N) -> T; fn point(self, x: N) -> T;
fn generator(self) -> T; fn generator(self) -> T;
@ -11,7 +11,7 @@ where
pub trait Point<N> pub trait Point<N>
where where
N: AddMod<Output = N> + SubMod<Output = N> + MulMod<Output = N> + InvertMod<Output = N> + Copy, N: AddMod + SubMod + MulMod + InvMod + Copy,
{ {
fn get_x(self) -> N; fn get_x(self) -> N;

View file

@ -1,4 +1,4 @@
use crypto_bigint::CtEq; use crypto_bigint::subtle::ConstantTimeEq;
use diffie_hellman::{Public, Secret}; use diffie_hellman::{Public, Secret};
#[test] #[test]