mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-06 20:41:14 +00:00
Add on-by-default fast crate feature for gating basepoint tables (#251)
* Add on-by-default `fast` crate feature Disabling the feature reduces overall code size at the cost of performance, which is useful for e.g. embedded users. This feature transitively enables the `basepoint-tables` feature in `curve25519-dalek` where the basepoint tables are actually defined. * Consolidated a lot of verification code * Bump `curve25519-dalek`; use `precomputed-tables` feature The feature name changed in dalek-cryptography/curve25519-dalek#499 Co-authored-by: Michael Rosenberg <michael@mrosenberg.pub>
This commit is contained in:
parent
431e69959d
commit
f61e9dcf9b
4 changed files with 39 additions and 36 deletions
10
.github/workflows/rust.yml
vendored
10
.github/workflows/rust.yml
vendored
|
|
@ -26,13 +26,19 @@ jobs:
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
- run: rustup target add ${{ matrix.target }}
|
- run: rustup target add ${{ matrix.target }}
|
||||||
- run: ${{ matrix.deps }}
|
- run: ${{ matrix.deps }}
|
||||||
- run: cargo test --target ${{ matrix.target }} --no-default-features --lib
|
- run: cargo test --target ${{ matrix.target }} --no-default-features --lib --tests
|
||||||
- run: cargo test --target ${{ matrix.target }} --no-default-features --features alloc --lib
|
- run: cargo test --target ${{ matrix.target }} --no-default-features --features alloc --lib
|
||||||
|
- run: cargo test --target ${{ matrix.target }} --no-default-features --features fast --lib
|
||||||
|
- run: cargo test --target ${{ matrix.target }} --no-default-features --features rand_core --lib --tests
|
||||||
|
- run: cargo test --target ${{ matrix.target }} --no-default-features --features alloc,rand_core --lib --tests
|
||||||
|
- run: cargo test --target ${{ matrix.target }} --no-default-features --features fast,rand_core --lib --tests
|
||||||
|
- run: cargo test --target ${{ matrix.target }} --no-default-features --features alloc,fast,rand_core --lib --tests
|
||||||
- run: cargo test --target ${{ matrix.target }}
|
- run: cargo test --target ${{ matrix.target }}
|
||||||
- run: cargo test --target ${{ matrix.target }} --features batch
|
- run: cargo test --target ${{ matrix.target }} --features batch
|
||||||
- run: cargo test --target ${{ matrix.target }} --features "digest rand_core"
|
- run: cargo test --target ${{ matrix.target }} --features digest,rand_core
|
||||||
- run: cargo test --target ${{ matrix.target }} --features serde
|
- run: cargo test --target ${{ matrix.target }} --features serde
|
||||||
- run: cargo test --target ${{ matrix.target }} --features pem
|
- run: cargo test --target ${{ matrix.target }} --features pem
|
||||||
|
- run: cargo test --target ${{ matrix.target }} --all-features
|
||||||
|
|
||||||
build-simd:
|
build-simd:
|
||||||
name: Test simd backend (nightly)
|
name: Test simd backend (nightly)
|
||||||
|
|
|
||||||
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -240,7 +240,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "curve25519-dalek"
|
name = "curve25519-dalek"
|
||||||
version = "4.0.0-pre.5"
|
version = "4.0.0-pre.5"
|
||||||
source = "git+https://github.com/dalek-cryptography/curve25519-dalek.git#83f6b149d33c37b8997316cb7a87d8d247b75c3e"
|
source = "git+https://github.com/dalek-cryptography/curve25519-dalek.git#3effd73307a606e44469a425974f0b7b0eb85899"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"digest",
|
"digest",
|
||||||
|
|
|
||||||
|
|
@ -51,12 +51,13 @@ harness = false
|
||||||
required-features = ["rand_core"]
|
required-features = ["rand_core"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "zeroize"]
|
default = ["fast", "std", "zeroize"]
|
||||||
alloc = ["curve25519-dalek/alloc", "ed25519/alloc", "serde?/alloc", "zeroize/alloc"]
|
alloc = ["curve25519-dalek/alloc", "ed25519/alloc", "serde?/alloc", "zeroize/alloc"]
|
||||||
std = ["alloc", "ed25519/std", "serde?/std", "sha2/std"]
|
std = ["alloc", "ed25519/std", "serde?/std", "sha2/std"]
|
||||||
|
|
||||||
asm = ["sha2/asm"]
|
asm = ["sha2/asm"]
|
||||||
batch = ["alloc", "merlin", "rand_core"]
|
batch = ["alloc", "merlin", "rand_core"]
|
||||||
|
fast = ["curve25519-dalek/precomputed-tables"]
|
||||||
digest = []
|
digest = []
|
||||||
# This features turns off stricter checking for scalar malleability in signatures
|
# This features turns off stricter checking for scalar malleability in signatures
|
||||||
legacy_compatibility = []
|
legacy_compatibility = []
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,8 @@ impl VerifyingKey {
|
||||||
VerifyingKey(compressed, point)
|
VerifyingKey(compressed, point)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A helper function that computes H(R || A || M) as well as its prehashed version
|
// A helper function that computes H(R || A || M). If `context.is_some()`, this does the
|
||||||
|
// prehashed variant of the computation using its contents.
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn compute_challenge(
|
fn compute_challenge(
|
||||||
context: Option<&[u8]>,
|
context: Option<&[u8]>,
|
||||||
|
|
@ -191,6 +192,22 @@ impl VerifyingKey {
|
||||||
Scalar::from_hash(h)
|
Scalar::from_hash(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function for verification. Computes the _expected_ R component of the signature. The
|
||||||
|
// caller compares this to the real R component. If `context.is_some()`, this does the
|
||||||
|
// prehashed variant of the computation using its contents.
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn recompute_r(
|
||||||
|
&self,
|
||||||
|
context: Option<&[u8]>,
|
||||||
|
signature: &InternalSignature,
|
||||||
|
M: &[u8],
|
||||||
|
) -> EdwardsPoint {
|
||||||
|
let k = Self::compute_challenge(context, &signature.R, &self.0, M);
|
||||||
|
let minus_A: EdwardsPoint = -self.1;
|
||||||
|
// Recall the (non-batched) verification equation: -[k]A + [s]B = R
|
||||||
|
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s)
|
||||||
|
}
|
||||||
|
|
||||||
/// Verify a `signature` on a `prehashed_message` using the Ed25519ph algorithm.
|
/// Verify a `signature` on a `prehashed_message` using the Ed25519ph algorithm.
|
||||||
///
|
///
|
||||||
/// # Inputs
|
/// # Inputs
|
||||||
|
|
@ -226,17 +243,10 @@ impl VerifyingKey {
|
||||||
"The context must not be longer than 255 octets."
|
"The context must not be longer than 255 octets."
|
||||||
);
|
);
|
||||||
|
|
||||||
let minus_A: EdwardsPoint = -self.1;
|
let message = prehashed_message.finalize();
|
||||||
let k = Self::compute_challenge(
|
let expected_R = self.recompute_r(Some(ctx), &signature, &message);
|
||||||
Some(ctx),
|
|
||||||
&signature.R,
|
|
||||||
&self.0,
|
|
||||||
prehashed_message.finalize().as_slice(),
|
|
||||||
);
|
|
||||||
let R: EdwardsPoint =
|
|
||||||
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
|
||||||
|
|
||||||
if R.compress() == signature.R {
|
if expected_R.compress() == signature.R {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(InternalError::Verify.into())
|
Err(InternalError::Verify.into())
|
||||||
|
|
@ -323,12 +333,8 @@ impl VerifyingKey {
|
||||||
return Err(InternalError::Verify.into());
|
return Err(InternalError::Verify.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let minus_A: EdwardsPoint = -self.1;
|
let expected_R = self.recompute_r(None, &signature, message);
|
||||||
let k = Self::compute_challenge(None, &signature.R, &self.0, message);
|
if expected_R == signature_R {
|
||||||
let R: EdwardsPoint =
|
|
||||||
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
|
||||||
|
|
||||||
if R == signature_R {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(InternalError::Verify.into())
|
Err(InternalError::Verify.into())
|
||||||
|
|
@ -381,16 +387,10 @@ impl VerifyingKey {
|
||||||
return Err(InternalError::Verify.into());
|
return Err(InternalError::Verify.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let minus_A: EdwardsPoint = -self.1;
|
let message = prehashed_message.finalize();
|
||||||
let k = Self::compute_challenge(
|
let expected_R = self.recompute_r(Some(ctx), &signature, &message);
|
||||||
Some(ctx),
|
|
||||||
&signature.R,
|
|
||||||
&self.0,
|
|
||||||
prehashed_message.finalize().as_slice(),
|
|
||||||
);
|
|
||||||
let R = EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
|
||||||
|
|
||||||
if R == signature_R {
|
if expected_R == signature_R {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(InternalError::Verify.into())
|
Err(InternalError::Verify.into())
|
||||||
|
|
@ -408,12 +408,8 @@ impl Verifier<ed25519::Signature> for VerifyingKey {
|
||||||
fn verify(&self, message: &[u8], signature: &ed25519::Signature) -> Result<(), SignatureError> {
|
fn verify(&self, message: &[u8], signature: &ed25519::Signature) -> Result<(), SignatureError> {
|
||||||
let signature = InternalSignature::try_from(signature)?;
|
let signature = InternalSignature::try_from(signature)?;
|
||||||
|
|
||||||
let minus_A: EdwardsPoint = -self.1;
|
let expected_R = self.recompute_r(None, &signature, message);
|
||||||
let k = Self::compute_challenge(None, &signature.R, &self.0, message);
|
if expected_R.compress() == signature.R {
|
||||||
let R: EdwardsPoint =
|
|
||||||
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
|
||||||
|
|
||||||
if R.compress() == signature.R {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(InternalError::Verify.into())
|
Err(InternalError::Verify.into())
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue