mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-05 20:30:57 +00:00
Merge branch 'feature/github-actions' into main
This commit is contained in:
commit
ad461f4f0f
5 changed files with 208 additions and 4 deletions
131
.github/workflows/rust.yml
vendored
Normal file
131
.github/workflows/rust.yml
vendored
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
name: Rust
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ '*' ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main, develop ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-u32:
|
||||||
|
name: Test u32 backend
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: --no-default-features --features "std u32_backend"
|
||||||
|
|
||||||
|
test-u64:
|
||||||
|
name: Test u64 backend
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: --no-default-features --features "std u64_backend"
|
||||||
|
|
||||||
|
test-simd:
|
||||||
|
name: Test simd backend (nightly)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: nightly
|
||||||
|
override: true
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: --no-default-features --features "std nightly simd_backend"
|
||||||
|
|
||||||
|
test-defaults-serde:
|
||||||
|
name: Test default feature selection and serde
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: --features "serde"
|
||||||
|
|
||||||
|
test-alloc-u32:
|
||||||
|
name: Test no_std+alloc with u32 backend
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: --lib --no-default-features --features "alloc u32_backend"
|
||||||
|
|
||||||
|
test-batch-deterministic:
|
||||||
|
name: Test deterministic batch verification
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: --features "batch_deterministic"
|
||||||
|
|
||||||
|
msrv:
|
||||||
|
name: Current MSRV is 1.41
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: 1.41
|
||||||
|
override: true
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: build
|
||||||
|
|
||||||
|
bench:
|
||||||
|
name: Check that benchmarks compile
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: bench
|
||||||
|
# This filter selects no benchmarks, so we don't run any, only build them.
|
||||||
|
args: --features "batch" "DONTRUNBENCHMARKS"
|
||||||
|
|
@ -30,7 +30,7 @@ rand_core = { version = "0.5", default-features = false, optional = true }
|
||||||
serde_crate = { package = "serde", version = "1.0", default-features = false, optional = true }
|
serde_crate = { package = "serde", version = "1.0", default-features = false, optional = true }
|
||||||
serde_bytes = { version = "0.11", optional = true }
|
serde_bytes = { version = "0.11", optional = true }
|
||||||
sha2 = { version = "0.9", default-features = false }
|
sha2 = { version = "0.9", default-features = false }
|
||||||
zeroize = { version = "1", default-features = false }
|
zeroize = { version = "~1.3", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex = "^0.4"
|
hex = "^0.4"
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ However, if you require this, please see the documentation for the
|
||||||
`verify_strict()` function, which does the full checks for the group elements.
|
`verify_strict()` function, which does the full checks for the group elements.
|
||||||
This functionality is available by default.
|
This functionality is available by default.
|
||||||
|
|
||||||
If for some reason—although we strongely advise you not to—you need to conform
|
If for some reason—although we strongly advise you not to—you need to conform
|
||||||
to the original specification of ed25519 signatures as in the excerpt from the
|
to the original specification of ed25519 signatures as in the excerpt from the
|
||||||
paper above, you can disable scalar malleability checking via
|
paper above, you can disable scalar malleability checking via
|
||||||
`--features='legacy_compatibility'`. **WE STRONGLY ADVISE AGAINST THIS.**
|
`--features='legacy_compatibility'`. **WE STRONGLY ADVISE AGAINST THIS.**
|
||||||
|
|
|
||||||
|
|
@ -235,8 +235,7 @@
|
||||||
#![warn(future_incompatible)]
|
#![warn(future_incompatible)]
|
||||||
#![deny(missing_docs)] // refuse to compile if documentation is missing
|
#![deny(missing_docs)] // refuse to compile if documentation is missing
|
||||||
|
|
||||||
#![cfg(not(test))]
|
#![cfg_attr(not(test), forbid(unsafe_code))]
|
||||||
#![forbid(unsafe_code)]
|
|
||||||
|
|
||||||
#[cfg(any(feature = "std", test))]
|
#[cfg(any(feature = "std", test))]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,10 @@ use sha2::Sha512;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod vectors {
|
mod vectors {
|
||||||
|
use curve25519_dalek::{edwards::EdwardsPoint, scalar::Scalar};
|
||||||
use ed25519::signature::Signature as _;
|
use ed25519::signature::Signature as _;
|
||||||
|
use sha2::{digest::Digest, Sha512};
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::io::BufRead;
|
use std::io::BufRead;
|
||||||
|
|
@ -112,6 +115,77 @@ mod vectors {
|
||||||
assert!(keypair.verify_prehashed(prehash_for_verifying, None, &sig2).is_ok(),
|
assert!(keypair.verify_prehashed(prehash_for_verifying, None, &sig2).is_ok(),
|
||||||
"Could not verify ed25519ph signature!");
|
"Could not verify ed25519ph signature!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Taken from curve25519_dalek::constants::EIGHT_TORSION[4]
|
||||||
|
const EIGHT_TORSION_4: [u8; 32] = [
|
||||||
|
236, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127,
|
||||||
|
];
|
||||||
|
|
||||||
|
fn compute_hram(message: &[u8], pub_key: &EdwardsPoint, signature_r: &EdwardsPoint) -> Scalar {
|
||||||
|
let k_bytes = Sha512::default()
|
||||||
|
.chain(&signature_r.compress().as_bytes())
|
||||||
|
.chain(&pub_key.compress().as_bytes()[..])
|
||||||
|
.chain(&message);
|
||||||
|
let mut k_output = [0u8; 64];
|
||||||
|
k_output.copy_from_slice(k_bytes.finalize().as_slice());
|
||||||
|
Scalar::from_bytes_mod_order_wide(&k_output)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_signature(r: &EdwardsPoint, s: &Scalar) -> Vec<u8> {
|
||||||
|
[&r.compress().as_bytes()[..], &s.as_bytes()[..]].concat()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn repudiation() {
|
||||||
|
use curve25519_dalek::traits::IsIdentity;
|
||||||
|
use std::ops::Neg;
|
||||||
|
|
||||||
|
let message1 = b"Send 100 USD to Alice";
|
||||||
|
let message2 = b"Send 100000 USD to Alice";
|
||||||
|
|
||||||
|
// Pick a random Scalar
|
||||||
|
fn non_null_scalar() -> Scalar {
|
||||||
|
let mut rng = rand::rngs::OsRng;
|
||||||
|
let mut s_candidate = Scalar::random(&mut rng);
|
||||||
|
while s_candidate == Scalar::zero() {
|
||||||
|
s_candidate = Scalar::random(&mut rng);
|
||||||
|
}
|
||||||
|
s_candidate
|
||||||
|
}
|
||||||
|
let mut s: Scalar = non_null_scalar();
|
||||||
|
|
||||||
|
fn pick_r_and_pubkey(s: Scalar) -> (EdwardsPoint, EdwardsPoint) {
|
||||||
|
let r0 = s * curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
|
||||||
|
// Pick a torsion point of order 2
|
||||||
|
let pub_key = curve25519_dalek::edwards::CompressedEdwardsY(EIGHT_TORSION_4)
|
||||||
|
.decompress()
|
||||||
|
.unwrap();
|
||||||
|
let r = r0 + pub_key.neg();
|
||||||
|
(r, pub_key)
|
||||||
|
}
|
||||||
|
|
||||||
|
let (mut r, mut pub_key) = pick_r_and_pubkey(s);
|
||||||
|
|
||||||
|
while !(pub_key.neg() + compute_hram(message1, &pub_key, &r) * pub_key).is_identity()
|
||||||
|
|| !(pub_key.neg() + compute_hram(message2, &pub_key, &r) * pub_key).is_identity()
|
||||||
|
{
|
||||||
|
s = non_null_scalar();
|
||||||
|
let key = pick_r_and_pubkey(s);
|
||||||
|
r = key.0;
|
||||||
|
pub_key = key.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let signature = serialize_signature(&r, &s);
|
||||||
|
let pk = PublicKey::from_bytes(&pub_key.compress().as_bytes()[..]).unwrap();
|
||||||
|
let sig = Signature::try_from(&signature[..]).unwrap();
|
||||||
|
// The same signature verifies for both messages
|
||||||
|
assert!(pk.verify(message1, &sig).is_ok() && pk.verify(message2, &sig).is_ok());
|
||||||
|
// But not with a strict signature: verify_strict refuses small order keys
|
||||||
|
assert!(
|
||||||
|
pk.verify_strict(message1, &sig).is_err() || pk.verify_strict(message2, &sig).is_err()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue