Compare commits
50 Commits
Author | SHA1 | Date |
---|---|---|
|
55dc5504ef | |
|
03543411df | |
|
180f76c33b | |
|
00dfdebcab | |
|
5f1f6ec186 | |
|
8e2971ee2d | |
|
578f86f5f0 | |
|
43245bb32f | |
|
21868fdcf8 | |
|
cc93deb133 | |
|
ea3047d939 | |
|
b56a31866f | |
|
4769fbe900 | |
|
09333f6407 | |
|
7927fbfb0a | |
|
0f0e2cff33 | |
|
6b1d1db752 | |
|
c9aeb16549 | |
|
4360ff8595 | |
|
ecf327eff0 | |
|
21cb1cb743 | |
|
a323173e23 | |
|
149da3a4ad | |
|
b38b214cde | |
|
28ecb3657f | |
|
fd109ebe91 | |
|
82b3d61c08 | |
|
5154a9955a | |
|
483c7cf302 | |
|
2daceab266 | |
|
010d2565ac | |
|
d2b7b8f8ab | |
|
2227dc8be6 | |
|
03bfd3e6d0 | |
|
58bc531c87 | |
|
86bf80a88c | |
|
545469b961 | |
|
415caf4817 | |
|
268cfc5c37 | |
|
bdbbe825fa | |
|
78f712d28b | |
|
9ab1897b2b | |
|
1619c1ff68 | |
|
8fbfadcf0d | |
|
ceee1c1d87 | |
|
d980b3b6a0 | |
|
67f60d69d0 | |
|
7d72a6d8c0 | |
|
18e12e7406 | |
|
06fddf3fb1 |
|
@ -0,0 +1,20 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
timezone: America/New_York
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
- dconnolly
|
||||
assignees:
|
||||
- dconnolly
|
||||
- package-ecosystem: cargo
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
timezone: America/New_York
|
||||
open-pull-requests-limit: 10
|
||||
assignees:
|
||||
- dconnolly
|
|
@ -11,78 +11,65 @@ on:
|
|||
jobs:
|
||||
|
||||
test:
|
||||
name: Test on ${{ matrix.os }}
|
||||
name: Build & Test (+nightly) / ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
- uses: actions/checkout@v3.0.2
|
||||
- uses: actions-rs/toolchain@v1.0.7
|
||||
with:
|
||||
toolchain: stable
|
||||
toolchain: nightly
|
||||
override: true
|
||||
- name: cargo fetch
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fetch
|
||||
- name: Run tests
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --verbose --all
|
||||
- name: Build
|
||||
- name: Build (+nightly)
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --verbose --release
|
||||
- name: Test (+nightly)
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --verbose --all-features
|
||||
|
||||
doctest-nightly:
|
||||
name: Run doctests via nightly
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
# Because we use nightly features for building docs,
|
||||
# using --all-features will fail without nightly toolchain.
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --all-features
|
||||
|
||||
coverage:
|
||||
name: Code Coverage
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
override: true
|
||||
- name: Run cargo-tarpaulin
|
||||
uses: actions-rs/tarpaulin@v0.1
|
||||
with:
|
||||
version: '0.12.3'
|
||||
timeout: 300
|
||||
- name: Upload coverage report to Codecov
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
clippy:
|
||||
name: Clippy
|
||||
name: Clippy (+nightly)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
- uses: actions/checkout@v3.0.2
|
||||
- uses: actions-rs/toolchain@v1.0.7
|
||||
with:
|
||||
toolchain: stable
|
||||
toolchain: nightly
|
||||
components: clippy
|
||||
override: true
|
||||
- name: Run clippy
|
||||
uses: actions-rs/clippy-check@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --all-features --all-targets -- -D warnings
|
||||
|
||||
coverage:
|
||||
name: Code Coverage (+nightly)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3.0.2
|
||||
- uses: actions-rs/toolchain@v1.0.7
|
||||
with:
|
||||
toolchain: nightly
|
||||
components: llvm-tools-preview
|
||||
override: true
|
||||
- name: Install rustfilt, cargo-llvm-cov cargo commands
|
||||
run: |
|
||||
cargo install rustfilt
|
||||
cargo install cargo-llvm-cov --version 0.1.0-alpha.3
|
||||
- name: Generate code coverage
|
||||
run: cargo llvm-cov --all-features --lcov > lcov.info
|
||||
- name: Upload coverage report to Codecov
|
||||
uses: codecov/codecov-action@v3.1.0
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ristretto255-dh"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
authors = ["Deirdre Connolly <durumcrustulum@gmail.com>"]
|
||||
edition = "2018"
|
||||
readme = "README.md"
|
||||
|
@ -19,15 +19,15 @@ exclude = [
|
|||
features = ["nightly"]
|
||||
|
||||
[dependencies]
|
||||
curve25519-dalek = { version = "2.0.0", features = ["serde"] }
|
||||
curve25519-dalek = { version = "3.0.0", features = ["serde"] }
|
||||
rand_core = "0.5.1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
zeroize = "1.1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
bincode = "1.2.1"
|
||||
proptest = "0.9"
|
||||
proptest-derive = "0.1.0"
|
||||
proptest = "1.0"
|
||||
proptest-derive = "0.3.0"
|
||||
|
||||
[features]
|
||||
nightly = []
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
coverage:
|
||||
range: "50...100"
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
informational: true
|
||||
patch:
|
||||
default:
|
||||
informational: true
|
||||
|
||||
parsers:
|
||||
gcov:
|
||||
branch_detection:
|
||||
conditional: yes
|
||||
loop: yes
|
||||
method: yes
|
||||
macro: yes
|
||||
|
||||
# comment:
|
||||
# layout: "diff"
|
||||
# # if true: only post the comment if coverage changes
|
||||
# require_changes: true
|
||||
|
||||
# This turns off the extra comment; the coverage %'s are still
|
||||
# reported on the main PR page as check results
|
||||
# comment: false
|
||||
|
||||
# github_checks:
|
||||
# annotations: false
|
72
src/lib.rs
72
src/lib.rs
|
@ -1,5 +1,4 @@
|
|||
#![cfg_attr(feature = "nightly", feature(external_doc))]
|
||||
#![cfg_attr(feature = "nightly", doc(include = "../README.md"))]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
|
@ -12,14 +11,13 @@ use rand_core::{CryptoRng, RngCore};
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(test)]
|
||||
use proptest::{arbitrary::Arbitrary, array, prelude::*};
|
||||
use proptest::{arbitrary::Arbitrary, array, collection, prelude::*};
|
||||
|
||||
/// A Diffie-Hellman secret key used to derive a shared secret when
|
||||
/// combined with a public key, that only exists for a short time.
|
||||
#[cfg_attr(test, derive(Debug))]
|
||||
pub struct EphemeralSecret(pub(crate) Scalar);
|
||||
|
||||
#[cfg(test)]
|
||||
impl From<[u8; 32]> for EphemeralSecret {
|
||||
fn from(bytes: [u8; 32]) -> EphemeralSecret {
|
||||
match Scalar::from_canonical_bytes(bytes) {
|
||||
|
@ -29,6 +27,12 @@ impl From<[u8; 32]> for EphemeralSecret {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 64]> for EphemeralSecret {
|
||||
fn from(bytes: [u8; 64]) -> EphemeralSecret {
|
||||
Self(Scalar::from_bytes_mod_order_wide(&bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl EphemeralSecret {
|
||||
/// Generate a `EphemeralSecret` using a new scalar mod the group
|
||||
/// order.
|
||||
|
@ -103,13 +107,9 @@ impl Arbitrary for PublicKey {
|
|||
|
||||
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
|
||||
array::uniform32(any::<u8>())
|
||||
.prop_filter_map(
|
||||
"Decompressible Ristretto point",
|
||||
|b| match PublicKey::try_from(b) {
|
||||
Ok(public_key) => Some(public_key),
|
||||
Err(_) => None,
|
||||
},
|
||||
)
|
||||
.prop_filter_map("Decompressible Ristretto point", |b| {
|
||||
PublicKey::try_from(b).ok()
|
||||
})
|
||||
.boxed()
|
||||
}
|
||||
|
||||
|
@ -132,10 +132,16 @@ impl From<SharedSecret> for [u8; 32] {
|
|||
|
||||
/// A Diffie-Hellman secret key used to derive a shared secret when
|
||||
/// combined with a public key, that can be stored and loaded.
|
||||
#[derive(Clone, Eq, PartialEq, Deserialize, Serialize)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize)]
|
||||
#[cfg_attr(test, derive(Debug))]
|
||||
pub struct StaticSecret(pub(crate) Scalar);
|
||||
|
||||
impl From<StaticSecret> for [u8; 32] {
|
||||
fn from(static_secret: StaticSecret) -> [u8; 32] {
|
||||
static_secret.0.to_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 32]> for StaticSecret {
|
||||
fn from(bytes: [u8; 32]) -> StaticSecret {
|
||||
match Scalar::from_canonical_bytes(bytes) {
|
||||
|
@ -145,6 +151,12 @@ impl From<[u8; 32]> for StaticSecret {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 64]> for StaticSecret {
|
||||
fn from(bytes: [u8; 64]) -> StaticSecret {
|
||||
Self(Scalar::from_bytes_mod_order_wide(&bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl StaticSecret {
|
||||
/// Generate a `StaticSecret` using a new scalar mod the group
|
||||
/// order.
|
||||
|
@ -171,7 +183,7 @@ impl Arbitrary for StaticSecret {
|
|||
.prop_filter("Valid scalar mod l", |b| {
|
||||
Scalar::from_bytes_mod_order(*b).is_canonical()
|
||||
})
|
||||
.prop_map(|bytes| return Self::from(bytes))
|
||||
.prop_map(Self::from)
|
||||
.boxed()
|
||||
}
|
||||
|
||||
|
@ -181,7 +193,6 @@ impl Arbitrary for StaticSecret {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use bincode;
|
||||
use rand_core::OsRng;
|
||||
|
||||
use super::*;
|
||||
|
@ -205,6 +216,30 @@ mod tests {
|
|||
|
||||
proptest! {
|
||||
|
||||
#[test]
|
||||
fn random_dh_wide(alice_bytes in collection::vec(any::<u8>(), 64),
|
||||
bob_bytes in collection::vec(any::<u8>(), 64)) {
|
||||
let mut a = [0u8; 64];
|
||||
a.copy_from_slice(alice_bytes.as_slice());
|
||||
|
||||
let alice_secret = EphemeralSecret::from(a);
|
||||
let alice_public = PublicKey::from(&alice_secret);
|
||||
|
||||
let mut b = [0u8; 64];
|
||||
b.copy_from_slice(bob_bytes.as_slice());
|
||||
|
||||
let bob_secret = StaticSecret::from(b);
|
||||
let bob_public = PublicKey::from(&bob_secret);
|
||||
|
||||
let alice_shared_secret = alice_secret.diffie_hellman(&bob_public);
|
||||
let bob_shared_secret = bob_secret.diffie_hellman(&alice_public);
|
||||
|
||||
assert_eq!(
|
||||
<[u8; 32]>::from(alice_shared_secret),
|
||||
<[u8; 32]>::from(bob_shared_secret)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ephemeral_dh(
|
||||
alice_secret in any::<EphemeralSecret>(),
|
||||
|
@ -268,6 +303,15 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_into_static_secret_bytes(static_secret in any::<StaticSecret>()) {
|
||||
let bytes: [u8; 32] = static_secret.into();
|
||||
|
||||
prop_assert_eq!(
|
||||
static_secret, StaticSecret::from(bytes)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scalar_mul_different_paths(
|
||||
secret in any::<EphemeralSecret>(),
|
||||
|
|
Loading…
Reference in New Issue