From 8f24b8b6a4fc278a88652978e0c3409234407c80 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 31 Mar 2026 20:52:54 -0600 Subject: [PATCH] [WIP] Transition from `subtle` to `ctutils` Companion PR to RustCrypto/traits#2351 --- Cargo.lock | 33 ++++---- Cargo.toml | 2 + primeorder/Cargo.toml | 1 + primeorder/src/affine.rs | 117 +++++++++++++++-------------- primeorder/src/lib.rs | 11 ++- primeorder/src/osswu.rs | 26 +++---- primeorder/src/point_arithmetic.rs | 9 ++- primeorder/src/projective.rs | 72 ++++++++++-------- 8 files changed, 150 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84a09363b..6f17d4239 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -516,12 +516,12 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elliptic-curve" version = "0.14.0-rc.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e84043d573efd4ac9d2d125817979a379204bf7e328b25a4a30487e8d100e618" +source = "git+https://github.com/RustCrypto/traits?branch=elliptic-curve%2Ftransition-from-subtle-to-ctutils#3871ec46210b8409e193ca7f77421e84a439570a" dependencies = [ "base16ct", "crypto-bigint", "crypto-common", + "ctutils", "digest", "hex-literal", "hkdf", @@ -667,28 +667,29 @@ checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" [[package]] name = "hkdf" -version = "0.13.0-rc.5" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbb55385998ae66b8d2d5143c05c94b9025ab863966f0c94ce7a5fde30105092" +checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018" dependencies = [ "hmac", ] [[package]] name = "hmac" -version = "0.13.0-rc.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60017b071c523c9e5a55dd1253582bff6150c5e96a7e8511e419de1ab5ee97f9" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" dependencies = [ "digest", ] [[package]] name = "hybrid-array" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8655f91cd07f2b9d0c24137bd650fe69617773435ee5ec83022377777ce65ef1" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" dependencies = [ + "ctutils", "subtle", "typenum", "zeroize", @@ -1028,6 +1029,7 @@ version = "0.14.0-rc.8" dependencies = [ "elliptic-curve", "serdect", + "subtle", ] [[package]] @@ -1209,9 +1211,9 @@ dependencies = [ [[package]] name = "rustcrypto-ff" -version = "0.14.0-rc.0" +version = "0.14.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5db129183b2c139d7d87d08be57cba626c715789db17aec65c8866bfd767d1f" +checksum = "fd2a8adb347447693cd2ba0d218c4b66c62da9b0a5672b17b981e4291ec65ff6" dependencies = [ "bitvec", "rand_core 0.10.0", @@ -1236,9 +1238,9 @@ dependencies = [ [[package]] name = "rustcrypto-group" -version = "0.14.0-rc.0" +version = "0.14.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c4b1463f274a3ff6fb2f44da43e576cb9424367bd96f185ead87b52fe00523" +checksum = "369f9b61aa45933c062c9f6b5c3c50ab710687eca83dd3802653b140b43f85ed" dependencies = [ "rand_core 0.10.0", "rustcrypto-ff", @@ -1287,16 +1289,15 @@ dependencies = [ [[package]] name = "sec1" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46b9a5ab87780a3189a1d704766579517a04ad59de653b7aad7d38e8a15f7dc" +checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d" dependencies = [ "base16ct", "ctutils", "der", "hybrid-array", "serdect", - "subtle", "zeroize", ] @@ -1488,7 +1489,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.3.4", "once_cell", "rustix", "windows-sys", diff --git a/Cargo.toml b/Cargo.toml index 879ffdb4d..4f36452f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,3 +26,5 @@ ed448-goldilocks = { path = "ed448-goldilocks" } hash2curve = { path = "hash2curve" } primefield = { path = "primefield" } primeorder = { path = "primeorder" } + +elliptic-curve = { git = "https://github.com/RustCrypto/traits", branch = "elliptic-curve/transition-from-subtle-to-ctutils" } diff --git a/primeorder/Cargo.toml b/primeorder/Cargo.toml index f9a04ec0f..d6baee50c 100644 --- a/primeorder/Cargo.toml +++ b/primeorder/Cargo.toml @@ -19,6 +19,7 @@ rust-version = "1.85" [dependencies] elliptic-curve = { version = "0.14.0-rc.29", default-features = false, features = ["arithmetic", "sec1"] } +subtle = { version = "2.6", default-features = false } # optional dependencies serdect = { version = "0.4", optional = true, default-features = false } diff --git a/primeorder/src/affine.rs b/primeorder/src/affine.rs index 7fd99e13a..2814df3fb 100644 --- a/primeorder/src/affine.rs +++ b/primeorder/src/affine.rs @@ -10,7 +10,7 @@ use core::{ use elliptic_curve::{ Error, FieldBytes, FieldBytesEncoding, FieldBytesSize, Generate, PublicKey, Result, Scalar, array::ArraySize, - ctutils::{self, CtGt as _, CtSelect as _}, + ctutils::{Choice, CtAssign, CtAssignSlice, CtEq, CtEqSlice, CtGt, CtOption, CtSelect}, ff::{Field, PrimeField}, group::{GroupEncoding, prime::PrimeCurveAffine}, point::{AffineCoordinates, DecompactPoint, DecompressPoint, Double, NonIdentity}, @@ -19,10 +19,8 @@ use elliptic_curve::{ self, CompressedPoint, FromSec1Point, ModulusSize, Sec1Point, ToCompactSec1Point, ToSec1Point, UncompressedPointSize, }, - subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}, zeroize::DefaultIsZeroes, }; - #[cfg(feature = "serde")] use serdect::serde::{Deserialize, Serialize, de, ser}; @@ -73,7 +71,7 @@ where Self { x: self.x, - y: C::FieldElement::conditional_select(&self.y, &neg_self.y, choice.into()), + y: C::FieldElement::ct_select(&self.y, &neg_self.y, choice.into()), infinity: self.infinity, } } @@ -108,13 +106,15 @@ where type FieldRepr = FieldBytes; fn from_coordinates(x: &Self::FieldRepr, y: &Self::FieldRepr) -> CtOption { - C::FieldElement::from_repr(*y).and_then(|y| { - C::FieldElement::from_repr(*x).and_then(|x| { - let lhs = y * &y; - let rhs = x * &x * &x + &(C::EQUATION_A * &x) + &C::EQUATION_B; - CtOption::new(Self { x, y, infinity: 0 }, lhs.ct_eq(&rhs)) + C::FieldElement::from_repr(*y) + .and_then(|y| { + C::FieldElement::from_repr(*x).and_then(|x| { + let lhs = y * &y; + let rhs = x * &x * &x + &(C::EQUATION_A * &x) + &C::EQUATION_B; + subtle::CtOption::new(Self { x, y, infinity: 0 }, lhs.ct_eq(&rhs).into()) + }) }) - }) + .into() } fn x(&self) -> FieldBytes { @@ -126,29 +126,28 @@ where } fn x_is_odd(&self) -> Choice { - self.x.is_odd() + self.x.is_odd().into() } fn y_is_odd(&self) -> Choice { - self.y.is_odd() + self.y.is_odd().into() } } -impl ConditionallySelectable for AffinePoint +impl CtAssign for AffinePoint where C: PrimeCurveParams, { - #[inline(always)] - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - Self { - x: C::FieldElement::conditional_select(&a.x, &b.x, choice), - y: C::FieldElement::conditional_select(&a.y, &b.y, choice), - infinity: u8::conditional_select(&a.infinity, &b.infinity, choice), - } + #[inline] + fn ct_assign(&mut self, other: &Self, choice: Choice) { + self.x.ct_assign(&other.x, choice); + self.y.ct_assign(&other.y, choice); + self.infinity.ct_assign(&other.infinity, choice); } } +impl CtAssignSlice for AffinePoint {} -impl ConstantTimeEq for AffinePoint +impl CtEq for AffinePoint where C: PrimeCurveParams, { @@ -156,22 +155,35 @@ where self.x.ct_eq(&other.x) & self.y.ct_eq(&other.y) & self.infinity.ct_eq(&other.infinity) } } +impl CtEqSlice for AffinePoint {} -impl ctutils::CtEq for AffinePoint +impl CtSelect for AffinePoint where C: PrimeCurveParams, { - fn ct_eq(&self, other: &Self) -> ctutils::Choice { - ConstantTimeEq::ct_eq(self, other).into() + #[inline] + fn ct_select(&self, other: &Self, choice: Choice) -> Self { + let mut ret = *self; + ret.ct_assign(other, choice); + ret } } -impl ctutils::CtSelect for AffinePoint +impl subtle::ConstantTimeEq for AffinePoint where C: PrimeCurveParams, { - fn ct_select(&self, other: &Self, choice: ctutils::Choice) -> Self { - ConditionallySelectable::conditional_select(self, other, choice.into()) + fn ct_eq(&self, other: &Self) -> subtle::Choice { + CtEq::ct_eq(self, other).into() + } +} + +impl subtle::ConditionallySelectable for AffinePoint +where + C: PrimeCurveParams, +{ + fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self { + CtSelect::ct_select(a, b, choice.into()) } } @@ -192,20 +204,17 @@ where FieldBytes: Copy, { fn decompress(x_bytes: &FieldBytes, y_is_odd: Choice) -> CtOption { - C::FieldElement::from_repr(*x_bytes).and_then(|x| { - let alpha = x * &x * &x + &(C::EQUATION_A * &x) + &C::EQUATION_B; - let beta = alpha.sqrt(); - - beta.map(|beta| { - let y = C::FieldElement::conditional_select( - &-beta, - &beta, - beta.is_odd().ct_eq(&y_is_odd), - ); - - Self { x, y, infinity: 0 } + C::FieldElement::from_repr(*x_bytes) + .and_then(|x| { + let alpha = x * &x * &x + &(C::EQUATION_A * &x) + &C::EQUATION_B; + let beta = alpha.sqrt(); + + beta.map(|beta| { + let y = (-beta).ct_select(&beta, beta.is_odd().ct_eq(&y_is_odd.into())); + Self { x, y, infinity: 0 } + }) }) - }) + .into() } } @@ -215,7 +224,7 @@ where FieldBytes: Copy, { fn decompact(x_bytes: &FieldBytes) -> CtOption { - Self::decompress(x_bytes, Choice::from(0)).map(|point| point.to_compact()) + Self::decompress(x_bytes, Choice::FALSE).map(|point| point.to_compact()) } } @@ -234,9 +243,9 @@ where /// # Returns /// /// `None` value if `encoded_point` is not on the secp384r1 curve. - fn from_sec1_point(encoded_point: &Sec1Point) -> ctutils::CtOption { + fn from_sec1_point(encoded_point: &Sec1Point) -> CtOption { match encoded_point.coordinates() { - sec1::Coordinates::Identity => ctutils::CtOption::some(Self::IDENTITY), + sec1::Coordinates::Identity => CtOption::some(Self::IDENTITY), sec1::Coordinates::Compact { x } => Self::decompact(x).into(), sec1::Coordinates::Compressed { x, y_is_odd } => { Self::decompress(x, Choice::from(y_is_odd as u8)).into() @@ -326,21 +335,20 @@ where type Repr = CompressedPoint; /// NOTE: not constant-time with respect to identity point - fn from_bytes(bytes: &Self::Repr) -> CtOption { + fn from_bytes(bytes: &Self::Repr) -> subtle::CtOption { Sec1Point::::from_bytes(bytes) - .map(ctutils::CtOption::some) + .map(CtOption::some) .unwrap_or_else(|_| { // SEC1 identity encoding is technically 1-byte 0x00, but the // `GroupEncoding` API requires a fixed-width `Repr` - let is_identity = - ctutils::CtEq::ct_eq(bytes.as_slice(), Self::Repr::default().as_slice()); - ctutils::CtOption::new(Sec1Point::::identity(), is_identity) + let is_identity = CtEq::ct_eq(bytes.as_slice(), Self::Repr::default().as_slice()); + CtOption::new(Sec1Point::::identity(), is_identity) }) .and_then(|point| Self::from_sec1_point(&point)) .into() } - fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption { + fn from_bytes_unchecked(bytes: &Self::Repr) -> subtle::CtOption { // No unchecked conversion possible for compressed points Self::from_bytes(bytes) } @@ -383,8 +391,8 @@ where Self::GENERATOR } - fn is_identity(&self) -> Choice { - self.is_identity() + fn is_identity(&self) -> subtle::Choice { + self.is_identity().into() } fn to_curve(&self) -> ProjectivePoint { @@ -400,7 +408,7 @@ where as ArraySize>::ArrayType: Copy, { /// Serialize this value as a SEC1 compact [`Sec1Point`] - fn to_compact_encoded_point(&self) -> ctutils::CtOption> { + fn to_compact_encoded_point(&self) -> CtOption> { let point = self.to_compact(); let mut bytes = CompressedPoint::::default(); @@ -408,9 +416,8 @@ where bytes[1..].copy_from_slice(&point.x.to_repr()); let encoded = Sec1Point::::from_bytes(bytes); - let is_some = - ctutils::CtEq::ct_eq(point.y.to_repr().as_slice(), self.y.to_repr().as_slice()); - ctutils::CtOption::new(encoded.unwrap_or_default(), is_some) + let is_some = CtEq::ct_eq(point.y.to_repr().as_slice(), self.y.to_repr().as_slice()); + CtOption::new(encoded.unwrap_or_default(), is_some) } } diff --git a/primeorder/src/lib.rs b/primeorder/src/lib.rs index ee296cfc3..43ea3a67f 100644 --- a/primeorder/src/lib.rs +++ b/primeorder/src/lib.rs @@ -27,7 +27,11 @@ pub use elliptic_curve::{ point::Double, }; -use elliptic_curve::{CurveArithmetic, Generate, ops::Invert, subtle::CtOption}; +use elliptic_curve::{ + CurveArithmetic, Generate, + ctutils::{CtAssign, CtEq, CtOption, CtSelect}, + ops::Invert, +}; /// Parameters for elliptic curves of prime order which can be described by the /// short Weierstrass equation. @@ -38,7 +42,10 @@ pub trait PrimeCurveParams: + CurveArithmetic> { /// Base field element type. - type FieldElement: Generate + type FieldElement: CtAssign + + CtEq + + CtSelect + + Generate + Invert> + PrimeField> + Retrieve; diff --git a/primeorder/src/osswu.rs b/primeorder/src/osswu.rs index 16352a8d3..81e2cad65 100644 --- a/primeorder/src/osswu.rs +++ b/primeorder/src/osswu.rs @@ -2,8 +2,10 @@ //! //! -use elliptic_curve::Field; -use elliptic_curve::subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; +use elliptic_curve::{ + Field, + ctutils::{Choice, CtEq, CtSelect}, +}; use crate::{AffinePoint, PrimeCurveParams}; @@ -48,7 +50,7 @@ pub trait Sgn0 { /// The optimized simplified Shallue-van de Woestijne-Ulas method /// for mapping elliptic curve scalars to affine points. -pub trait OsswuMap: Field + Sgn0 { +pub trait OsswuMap: Field + CtEq + CtSelect + Sgn0 { /// The OSSWU parameters for mapping the field to affine points. /// For Weierstrass curves having A==0 or B==0, the parameters /// should be for isogeny where A≠0 and B≠0. @@ -73,9 +75,9 @@ pub trait OsswuMap: Field + Sgn0 { // 8. tv3 = tv3 * v let tv3 = tv3 * v; // 9. isQR = tv3 == u - let is_qr = tv3.ct_eq(&u); + let is_qr = CtEq::ct_eq(&tv3, &u); // 10. y = CMOV(y2, y1, isQR) - let y = ConditionallySelectable::conditional_select(&y2, &y1, is_qr); + let y = y2.ct_select(&y1, is_qr); // 11. return (isQR, y) (is_qr, y) } @@ -97,11 +99,9 @@ pub trait OsswuMap: Field + Sgn0 { // 6. tv3 = B * tv3 let tv3 = Self::PARAMS.map_b * tv3; // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) - let tv4 = ConditionallySelectable::conditional_select( - &Self::PARAMS.z, - &-tv2, - !Field::is_zero(&tv2), - ); + let tv4 = Self::PARAMS + .z + .ct_select(&-tv2, (!Field::is_zero(&tv2)).into()); // 8. tv4 = A * tv4 let tv4 = Self::PARAMS.map_a * tv4; // 9. tv2 = tv3^2 @@ -129,13 +129,13 @@ pub trait OsswuMap: Field + Sgn0 { // 20. y = y * y1 let y = y * y1; // 21. x = CMOV(x, tv3, is_gx1_square) - let x = ConditionallySelectable::conditional_select(&x, &tv3, is_gx1_square); + let x = CtSelect::ct_select(&x, &tv3, is_gx1_square); // 22. y = CMOV(y, y1, is_gx1_square) - let y = ConditionallySelectable::conditional_select(&y, &y1, is_gx1_square); + let y = CtSelect::ct_select(&y, &y1, is_gx1_square); // 23. e1 = sgn0(u) == sgn0(y) let e1 = self.sgn0().ct_eq(&y.sgn0()); // 24. y = CMOV(-y, y, e1) - let y = ConditionallySelectable::conditional_select(&-y, &y, e1); + let y = CtSelect::ct_select(&-y, &y, e1); // 25. x = x / tv4 let x = x * tv4.invert().unwrap(); // 26. return (x, y) diff --git a/primeorder/src/point_arithmetic.rs b/primeorder/src/point_arithmetic.rs index 73c1ed917..6a4798072 100644 --- a/primeorder/src/point_arithmetic.rs +++ b/primeorder/src/point_arithmetic.rs @@ -3,9 +3,10 @@ //! Support for formulas specialized to the short Weierstrass equation's //! 𝒂-coefficient. -use elliptic_curve::{Field, subtle::ConditionallySelectable}; +use elliptic_curve::Field; use crate::{AffinePoint, PrimeCurveParams, ProjectivePoint}; +use elliptic_curve::ctutils::CtAssign; mod sealed { use crate::{AffinePoint, PrimeCurveParams, ProjectivePoint}; @@ -160,7 +161,7 @@ impl PointArithmetic for EquationAIsGeneric { y: y3, z: z3, }; - ret.conditional_assign(lhs, rhs.is_identity()); + ret.ct_assign(lhs, rhs.is_identity()); ret } @@ -283,7 +284,7 @@ impl PointArithmetic for EquationAIsMinusThree { y: (yy_p_bzz3 * yy_m_bzz3) + (xx3_m_zz3 * bxz3_part), // 29, 30, 31 z: (yy_m_bzz3 * yz_pairs) + (xy_pairs * xx3_m_zz3), // 34, 35, 36 }; - ret.conditional_assign(lhs, rhs.is_identity()); + ret.ct_assign(lhs, rhs.is_identity()); ret } @@ -425,7 +426,7 @@ impl PointArithmetic for EquationAIsZero { y: y3, z: z3, }; - ret.conditional_assign(lhs, rhs.is_identity()); + ret.ct_assign(lhs, rhs.is_identity()); ret } diff --git a/primeorder/src/projective.rs b/primeorder/src/projective.rs index 2e402b983..d03af9416 100644 --- a/primeorder/src/projective.rs +++ b/primeorder/src/projective.rs @@ -14,7 +14,7 @@ use elliptic_curve::{ Result, Scalar, array::ArraySize, bigint::{ArrayEncoding, ByteArray}, - ctutils, + ctutils::{Choice, CtAssign, CtAssignSlice, CtEq, CtEqSlice, CtOption, CtSelect}, group::{ Group, GroupEncoding, cofactor::CofactorGroup, @@ -26,13 +26,11 @@ use elliptic_curve::{ sec1::{ CompressedPoint, FromSec1Point, ModulusSize, Sec1Point, ToSec1Point, UncompressedPointSize, }, - subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}, zeroize::DefaultIsZeroes, }; #[cfg(feature = "alloc")] use alloc::vec::Vec; - #[cfg(feature = "serde")] use serdect::serde::{Deserialize, Serialize, de, ser}; @@ -118,21 +116,20 @@ where } } -impl ConditionallySelectable for ProjectivePoint +impl CtAssign for ProjectivePoint where C: PrimeCurveParams, { - #[inline(always)] - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - Self { - x: C::FieldElement::conditional_select(&a.x, &b.x, choice), - y: C::FieldElement::conditional_select(&a.y, &b.y, choice), - z: C::FieldElement::conditional_select(&a.z, &b.z, choice), - } + #[inline] + fn ct_assign(&mut self, other: &Self, choice: Choice) { + self.x.ct_assign(&other.x, choice); + self.y.ct_assign(&other.y, choice); + self.z.ct_assign(&other.z, choice); } } +impl CtAssignSlice for ProjectivePoint {} -impl ConstantTimeEq for ProjectivePoint +impl CtEq for ProjectivePoint where C: PrimeCurveParams, { @@ -143,22 +140,35 @@ where x_eq & y_eq } } +impl CtEqSlice for ProjectivePoint {} + +impl CtSelect for ProjectivePoint +where + C: PrimeCurveParams, +{ + #[inline] + fn ct_select(&self, other: &Self, choice: Choice) -> Self { + let mut ret = *self; + ret.ct_assign(other, choice); + ret + } +} -impl ctutils::CtEq for ProjectivePoint +impl subtle::ConstantTimeEq for ProjectivePoint where C: PrimeCurveParams, { - fn ct_eq(&self, other: &Self) -> ctutils::Choice { - ConstantTimeEq::ct_eq(self, other).into() + fn ct_eq(&self, other: &Self) -> subtle::Choice { + CtEq::ct_eq(self, other).into() } } -impl ctutils::CtSelect for ProjectivePoint +impl subtle::ConditionallySelectable for ProjectivePoint where C: PrimeCurveParams, { - fn ct_select(&self, other: &Self, choice: ctutils::Choice) -> Self { - ConditionallySelectable::conditional_select(self, other, choice.into()) + fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self { + CtSelect::ct_select(a, b, choice.into()) } } @@ -191,7 +201,7 @@ where y: p.y, z: C::FieldElement::ONE, }; - Self::conditional_select(&projective, &Self::IDENTITY, p.is_identity()) + Self::ct_select(&projective, &Self::IDENTITY, p.is_identity()) } } @@ -238,7 +248,7 @@ where FieldBytesSize: ModulusSize, CompressedPoint: Copy, { - fn from_sec1_point(p: &Sec1Point) -> ctutils::CtOption { + fn from_sec1_point(p: &Sec1Point) -> CtOption { AffinePoint::::from_sec1_point(p).map(Self::from) } } @@ -275,12 +285,12 @@ where *self } - fn into_subgroup(self) -> CtOption { - CtOption::new(self, Choice::from(1)) + fn into_subgroup(self) -> subtle::CtOption { + CtOption::new(self, Choice::TRUE).into() } - fn is_torsion_free(&self) -> Choice { - Choice::from(1) + fn is_torsion_free(&self) -> subtle::Choice { + Choice::TRUE.into() } } @@ -323,8 +333,8 @@ where Self::GENERATOR } - fn is_identity(&self) -> Choice { - self.ct_eq(&Self::IDENTITY) + fn is_identity(&self) -> subtle::Choice { + self.ct_eq(&Self::IDENTITY).into() } fn double(&self) -> Self { @@ -343,11 +353,11 @@ where { type Repr = CompressedPoint; - fn from_bytes(bytes: &Self::Repr) -> CtOption { + fn from_bytes(bytes: &Self::Repr) -> subtle::CtOption { as GroupEncoding>::from_bytes(bytes).map(Into::into) } - fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption { + fn from_bytes_unchecked(bytes: &Self::Repr) -> subtle::CtOption { // No unchecked conversion possible for compressed points Self::from_bytes(bytes) } @@ -435,7 +445,7 @@ where // Even a single zero value will fail inversion for the entire batch. // Put a dummy value (above `FieldElement::ONE`) so inversion succeeds // and treat that case specially later-on. - zs.as_mut()[i].conditional_assign(&points[i].z, !points[i].z.ct_eq(&C::FieldElement::ZERO)); + zs.as_mut()[i].ct_assign(&points[i].z, !points[i].z.ct_eq(&C::FieldElement::ZERO)); } // This is safe to unwrap since we assured that all elements are non-zero @@ -445,7 +455,7 @@ where for i in 0..out.len() { // If the `z` coordinate is non-zero, we can use it to invert; // otherwise it defaults to the `IDENTITY` value. - out[i] = C::AffinePoint::conditional_select( + out[i] = C::AffinePoint::ct_select( &points[i].to_affine_internal(zs_inverses.as_ref()[i]), &C::AffinePoint::IDENTITY, points[i].z.ct_eq(&C::FieldElement::ZERO), @@ -536,7 +546,7 @@ impl LookupTable { let mut t = ProjectivePoint::IDENTITY; for i in 1..16 { - t.conditional_assign( + t.ct_assign( &self.0[i], Choice::from(((slot as usize ^ i).wrapping_sub(1) >> 8) as u8 & 1), );