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
10
.github/workflows/rust.yml
vendored
10
.github/workflows/rust.yml
vendored
@ -26,13 +26,19 @@ jobs:
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: rustup target add ${{ matrix.target }}
|
||||
- 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 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 }} --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 pem
|
||||
- run: cargo test --target ${{ matrix.target }} --all-features
|
||||
|
||||
build-simd:
|
||||
name: Test simd backend (nightly)
|
||||
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -240,7 +240,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
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 = [
|
||||
"cfg-if",
|
||||
"digest",
|
||||
|
@ -51,12 +51,13 @@ harness = false
|
||||
required-features = ["rand_core"]
|
||||
|
||||
[features]
|
||||
default = ["std", "zeroize"]
|
||||
default = ["fast", "std", "zeroize"]
|
||||
alloc = ["curve25519-dalek/alloc", "ed25519/alloc", "serde?/alloc", "zeroize/alloc"]
|
||||
std = ["alloc", "ed25519/std", "serde?/std", "sha2/std"]
|
||||
|
||||
asm = ["sha2/asm"]
|
||||
batch = ["alloc", "merlin", "rand_core"]
|
||||
fast = ["curve25519-dalek/precomputed-tables"]
|
||||
digest = []
|
||||
# This features turns off stricter checking for scalar malleability in signatures
|
||||
legacy_compatibility = []
|
||||
|
@ -169,7 +169,8 @@ impl VerifyingKey {
|
||||
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)]
|
||||
fn compute_challenge(
|
||||
context: Option<&[u8]>,
|
||||
@ -191,6 +192,22 @@ impl VerifyingKey {
|
||||
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.
|
||||
///
|
||||
/// # Inputs
|
||||
@ -226,17 +243,10 @@ impl VerifyingKey {
|
||||
"The context must not be longer than 255 octets."
|
||||
);
|
||||
|
||||
let minus_A: EdwardsPoint = -self.1;
|
||||
let k = Self::compute_challenge(
|
||||
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);
|
||||
let message = prehashed_message.finalize();
|
||||
let expected_R = self.recompute_r(Some(ctx), &signature, &message);
|
||||
|
||||
if R.compress() == signature.R {
|
||||
if expected_R.compress() == signature.R {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(InternalError::Verify.into())
|
||||
@ -323,12 +333,8 @@ impl VerifyingKey {
|
||||
return Err(InternalError::Verify.into());
|
||||
}
|
||||
|
||||
let minus_A: EdwardsPoint = -self.1;
|
||||
let k = Self::compute_challenge(None, &signature.R, &self.0, message);
|
||||
let R: EdwardsPoint =
|
||||
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
||||
|
||||
if R == signature_R {
|
||||
let expected_R = self.recompute_r(None, &signature, message);
|
||||
if expected_R == signature_R {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(InternalError::Verify.into())
|
||||
@ -381,16 +387,10 @@ impl VerifyingKey {
|
||||
return Err(InternalError::Verify.into());
|
||||
}
|
||||
|
||||
let minus_A: EdwardsPoint = -self.1;
|
||||
let k = Self::compute_challenge(
|
||||
Some(ctx),
|
||||
&signature.R,
|
||||
&self.0,
|
||||
prehashed_message.finalize().as_slice(),
|
||||
);
|
||||
let R = EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
||||
let message = prehashed_message.finalize();
|
||||
let expected_R = self.recompute_r(Some(ctx), &signature, &message);
|
||||
|
||||
if R == signature_R {
|
||||
if expected_R == signature_R {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(InternalError::Verify.into())
|
||||
@ -408,12 +408,8 @@ impl Verifier<ed25519::Signature> for VerifyingKey {
|
||||
fn verify(&self, message: &[u8], signature: &ed25519::Signature) -> Result<(), SignatureError> {
|
||||
let signature = InternalSignature::try_from(signature)?;
|
||||
|
||||
let minus_A: EdwardsPoint = -self.1;
|
||||
let k = Self::compute_challenge(None, &signature.R, &self.0, message);
|
||||
let R: EdwardsPoint =
|
||||
EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(minus_A), &signature.s);
|
||||
|
||||
if R.compress() == signature.R {
|
||||
let expected_R = self.recompute_r(None, &signature, message);
|
||||
if expected_R.compress() == signature.R {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(InternalError::Verify.into())
|
||||
|
Loading…
x
Reference in New Issue
Block a user