-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update to new Scalar
API
#120
Changes from 2 commits
60a28b9
f3206ee
4239863
924d4ad
511a028
6a319cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,7 @@ | |
//! and Adam Langley in [RFC7748](https://tools.ietf.org/html/rfc7748). | ||
|
||
use curve25519_dalek::{ | ||
edwards::EdwardsPoint, montgomery::MontgomeryPoint, scalar::Scalar, traits::IsIdentity, | ||
edwards::EdwardsPoint, montgomery::MontgomeryPoint, scalar::clamp_integer, traits::IsIdentity, | ||
}; | ||
|
||
use rand_core::CryptoRng; | ||
|
@@ -75,13 +75,13 @@ impl AsRef<[u8]> for PublicKey { | |
/// secret is used at most once. | ||
#[cfg_attr(feature = "zeroize", derive(Zeroize))] | ||
#[cfg_attr(feature = "zeroize", zeroize(drop))] | ||
pub struct EphemeralSecret(pub(crate) Scalar); | ||
pub struct EphemeralSecret(pub(crate) [u8; 32]); | ||
|
||
impl EphemeralSecret { | ||
/// Perform a Diffie-Hellman key agreement between `self` and | ||
/// `their_public` key to produce a [`SharedSecret`]. | ||
pub fn diffie_hellman(self, their_public: &PublicKey) -> SharedSecret { | ||
SharedSecret(self.0 * their_public.0) | ||
SharedSecret(their_public.0.mul_clamped(self.0)) | ||
} | ||
|
||
/// Generate a new [`EphemeralSecret`] with the supplied RNG. | ||
|
@@ -95,11 +95,10 @@ impl EphemeralSecret { | |
|
||
/// Generate a new [`EphemeralSecret`] with the supplied RNG. | ||
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self { | ||
// Generate random bytes. The secret key is the clamping of this. | ||
let mut bytes = [0u8; 32]; | ||
|
||
csprng.fill_bytes(&mut bytes); | ||
|
||
EphemeralSecret(Scalar::from_bits_clamped(bytes)) | ||
EphemeralSecret(clamp_integer(bytes)) | ||
} | ||
|
||
/// Generate a new [`EphemeralSecret`]. | ||
|
@@ -112,7 +111,7 @@ impl EphemeralSecret { | |
impl<'a> From<&'a EphemeralSecret> for PublicKey { | ||
/// Given an x25519 [`EphemeralSecret`] key, compute its corresponding [`PublicKey`]. | ||
fn from(secret: &'a EphemeralSecret) -> PublicKey { | ||
PublicKey(EdwardsPoint::mul_base(&secret.0).to_montgomery()) | ||
PublicKey(EdwardsPoint::mul_base_clamped(secret.0).to_montgomery()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same reasoning here, and in the multiple copies of this below |
||
} | ||
} | ||
|
||
|
@@ -138,14 +137,14 @@ impl<'a> From<&'a EphemeralSecret> for PublicKey { | |
#[cfg_attr(feature = "zeroize", derive(Zeroize))] | ||
#[cfg_attr(feature = "zeroize", zeroize(drop))] | ||
#[derive(Clone)] | ||
pub struct ReusableSecret(pub(crate) Scalar); | ||
pub struct ReusableSecret(pub(crate) [u8; 32]); | ||
|
||
#[cfg(feature = "reusable_secrets")] | ||
impl ReusableSecret { | ||
/// Perform a Diffie-Hellman key agreement between `self` and | ||
/// `their_public` key to produce a [`SharedSecret`]. | ||
pub fn diffie_hellman(&self, their_public: &PublicKey) -> SharedSecret { | ||
SharedSecret(self.0 * their_public.0) | ||
SharedSecret(their_public.0.mul_clamped(self.0)) | ||
} | ||
|
||
/// Generate a new [`ReusableSecret`] with the supplied RNG. | ||
|
@@ -159,11 +158,10 @@ impl ReusableSecret { | |
|
||
/// Generate a new [`ReusableSecret`] with the supplied RNG. | ||
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self { | ||
// Generate random bytes. The secret key is the clamping of this. | ||
let mut bytes = [0u8; 32]; | ||
|
||
csprng.fill_bytes(&mut bytes); | ||
|
||
ReusableSecret(Scalar::from_bits_clamped(bytes)) | ||
ReusableSecret(clamp_integer(bytes)) | ||
} | ||
|
||
/// Generate a new [`ReusableSecret`]. | ||
|
@@ -177,7 +175,7 @@ impl ReusableSecret { | |
impl<'a> From<&'a ReusableSecret> for PublicKey { | ||
/// Given an x25519 [`ReusableSecret`] key, compute its corresponding [`PublicKey`]. | ||
fn from(secret: &'a ReusableSecret) -> PublicKey { | ||
PublicKey(EdwardsPoint::mul_base(&secret.0).to_montgomery()) | ||
PublicKey(EdwardsPoint::mul_base_clamped(secret.0).to_montgomery()) | ||
} | ||
} | ||
|
||
|
@@ -199,15 +197,13 @@ impl<'a> From<&'a ReusableSecret> for PublicKey { | |
#[cfg_attr(feature = "zeroize", derive(Zeroize))] | ||
#[cfg_attr(feature = "zeroize", zeroize(drop))] | ||
#[derive(Clone)] | ||
pub struct StaticSecret( | ||
#[cfg_attr(feature = "serde", serde(with = "AllowUnreducedScalarBytes"))] pub(crate) Scalar, | ||
); | ||
pub struct StaticSecret([u8; 32]); | ||
rozbb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
impl StaticSecret { | ||
/// Perform a Diffie-Hellman key agreement between `self` and | ||
/// `their_public` key to produce a `SharedSecret`. | ||
pub fn diffie_hellman(&self, their_public: &PublicKey) -> SharedSecret { | ||
SharedSecret(self.0 * their_public.0) | ||
SharedSecret(their_public.0.mul_clamped(self.0)) | ||
} | ||
|
||
/// Generate a new [`StaticSecret`] with the supplied RNG. | ||
|
@@ -221,11 +217,10 @@ impl StaticSecret { | |
|
||
/// Generate a new [`StaticSecret`] with the supplied RNG. | ||
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self { | ||
// Generate random bytes. The secret key is the clamping of this. | ||
let mut bytes = [0u8; 32]; | ||
|
||
csprng.fill_bytes(&mut bytes); | ||
|
||
StaticSecret(Scalar::from_bits_clamped(bytes)) | ||
StaticSecret(clamp_integer(bytes)) | ||
} | ||
|
||
/// Generate a new [`StaticSecret`]. | ||
|
@@ -237,27 +232,27 @@ impl StaticSecret { | |
/// Extract this key's bytes for serialization. | ||
#[inline] | ||
pub fn to_bytes(&self) -> [u8; 32] { | ||
self.0.to_bytes() | ||
self.0 | ||
rozbb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
/// View this key as a byte array. | ||
#[inline] | ||
pub fn as_bytes(&self) -> &[u8; 32] { | ||
self.0.as_bytes() | ||
&self.0 | ||
} | ||
} | ||
|
||
impl From<[u8; 32]> for StaticSecret { | ||
/// Load a secret key from a byte array. | ||
fn from(bytes: [u8; 32]) -> StaticSecret { | ||
StaticSecret(Scalar::from_bits_clamped(bytes)) | ||
StaticSecret(clamp_integer(bytes)) | ||
} | ||
} | ||
|
||
impl<'a> From<&'a StaticSecret> for PublicKey { | ||
/// Given an x25519 [`StaticSecret`] key, compute its corresponding [`PublicKey`]. | ||
fn from(secret: &'a StaticSecret) -> PublicKey { | ||
PublicKey(EdwardsPoint::mul_base(&secret.0).to_montgomery()) | ||
PublicKey(EdwardsPoint::mul_base_clamped(secret.0).to_montgomery()) | ||
} | ||
} | ||
|
||
|
@@ -368,7 +363,7 @@ impl AsRef<[u8]> for SharedSecret { | |
/// assert_eq!(alice_shared, bob_shared); | ||
/// ``` | ||
pub fn x25519(k: [u8; 32], u: [u8; 32]) -> [u8; 32] { | ||
(Scalar::from_bits_clamped(k) * MontgomeryPoint(u)).to_bytes() | ||
MontgomeryPoint(u).mul_clamped(k).to_bytes() | ||
} | ||
|
||
/// The X25519 basepoint, for use with the bare, byte-oriented x25519 | ||
|
@@ -377,17 +372,3 @@ pub fn x25519(k: [u8; 32], u: [u8; 32]) -> [u8; 32] { | |
pub const X25519_BASEPOINT_BYTES: [u8; 32] = [ | ||
9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
]; | ||
|
||
/// Derived serialization methods will not work on a StaticSecret because x25519 requires | ||
/// non-canonical scalars which are rejected by curve25519-dalek. Thus we provide a way to convert | ||
/// the bytes directly to a scalar using Serde's remote derive functionality. | ||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] | ||
#[cfg_attr(feature = "serde", serde(remote = "Scalar"))] | ||
struct AllowUnreducedScalarBytes( | ||
#[cfg_attr(feature = "serde", serde(getter = "Scalar::to_bytes"))] [u8; 32], | ||
); | ||
impl From<AllowUnreducedScalarBytes> for Scalar { | ||
fn from(bytes: AllowUnreducedScalarBytes) -> Scalar { | ||
Scalar::from_bits_clamped(bytes.0) | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can remove this because (de)serialization of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is equivalent because, in the old code,
self.0
was the result ofScalar::from_bits_clamped
, which was unreduced.