mirror of
https://github.com/saymrwulf/risc0-curve25519-dalek-source.git
synced 2026-09-04 20:03:40 +00:00
Merge remote-tracking branch 'x/main' into monorepo-t1
This commit is contained in:
commit
e7ecb74ed0
15 changed files with 1957 additions and 0 deletions
132
.github/workflows/rust.yml
vendored
Normal file
132
.github/workflows/rust.yml
vendored
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
name: Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ '**' ]
|
||||
pull_request:
|
||||
branches: [ '**' ]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTFLAGS: '-D warnings'
|
||||
RUSTDOCFLAGS: '-D warnings'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test with multiple feature combinations
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
# 32-bit target
|
||||
- target: i686-unknown-linux-gnu
|
||||
deps: sudo apt update && sudo apt install gcc-multilib
|
||||
# 64-bit target
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
- run: ${{ matrix.deps }}
|
||||
- run: cargo test --target ${{ matrix.target }} --no-default-features
|
||||
- run: cargo test --target ${{ matrix.target }} --no-default-features --features reusable_secrets
|
||||
- run: cargo test --target ${{ matrix.target }} --no-default-features --features static_secrets
|
||||
- run: cargo test --target ${{ matrix.target }}
|
||||
- run: cargo test --target ${{ matrix.target }} --all-features
|
||||
|
||||
build-simd:
|
||||
name: Test simd backend (nightly)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- env:
|
||||
RUSTFLAGS: '--cfg curve25519_dalek_backend="simd" -C target_feature=+avx2'
|
||||
run: cargo build --target x86_64-unknown-linux-gnu
|
||||
- env:
|
||||
RUSTFLAGS: '--cfg curve25519_dalek_backend="simd" -C target_feature=+avx512ifma'
|
||||
run: cargo build --target x86_64-unknown-linux-gnu
|
||||
|
||||
msrv:
|
||||
name: Current MSRV is 1.60.0
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
# First delete the checked-in `Cargo.lock`. We're going to regenerate it
|
||||
- run: rm Cargo.lock
|
||||
# Now run `cargo +nightly -Z minimal-verisons check` in order to get a
|
||||
# Cargo.lock with the oldest possible deps
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
- run: cargo -Z minimal-versions check --no-default-features --features serde
|
||||
# Now check that `cargo build` works with respect to the oldest possible
|
||||
# deps and the stated MSRV
|
||||
- uses: dtolnay/rust-toolchain@1.60.0
|
||||
- run: cargo build
|
||||
|
||||
# no_std support is pending feature, tracking:
|
||||
# https://github.com/dalek-cryptography/x25519-dalek/issues/111
|
||||
# # Test no_std integration with no features
|
||||
# build-nostd-base:
|
||||
# name: Build on no_std target (thumbv7em-none-eabi)
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# - uses: dtolnay/rust-toolchain@master
|
||||
# with:
|
||||
# toolchain: stable
|
||||
# targets: thumbv7em-none-eabi
|
||||
# - uses: taiki-e/install-action@cargo-hack
|
||||
# # No default features build
|
||||
# - run: cargo build --target thumbv7em-none-eabi --release --no-default-features
|
||||
#
|
||||
# # Test no_std integration with all no_std features
|
||||
# build-nostd-features:
|
||||
# name: Build on no_std target (thumbv7em-none-eabi)
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# - uses: dtolnay/rust-toolchain@master
|
||||
# with:
|
||||
# toolchain: stable
|
||||
# targets: thumbv7em-none-eabi
|
||||
# - uses: taiki-e/install-action@cargo-hack
|
||||
# # No default features build
|
||||
# - run: cargo hack build --target thumbv7em-none-eabi --release --each-feature --exclude-features default,std
|
||||
|
||||
bench:
|
||||
name: Check that benchmarks compile
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: cargo build --benches
|
||||
|
||||
rustfmt:
|
||||
name: Check formatting
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: rustfmt
|
||||
- run: cargo fmt --all -- --check
|
||||
|
||||
clippy:
|
||||
name: Check that clippy is happy
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@1.65
|
||||
with:
|
||||
components: clippy
|
||||
- run: cargo clippy
|
||||
|
||||
doc:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: stable
|
||||
- run: cargo doc --all-features
|
||||
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
target/
|
||||
**/*.rs.bk
|
||||
|
||||
.cargo
|
||||
|
||||
*~
|
||||
\#*
|
||||
.\#*
|
||||
*.swp
|
||||
*.orig
|
||||
*.bak
|
||||
|
||||
*.s
|
||||
26
.travis.yml
Normal file
26
.travis.yml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
language: rust
|
||||
|
||||
rust:
|
||||
- nightly
|
||||
|
||||
env:
|
||||
- TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='default'
|
||||
- TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='nightly'
|
||||
- TEST_COMMAND=bench EXTRA_FLAGS='' FEATURES='default'
|
||||
- TEST_COMMAND=build EXTRA_FLAGS='--no-default-features' FEATURES='u32_backend nightly'
|
||||
- TEST_COMMAND=build EXTRA_FLAGS='--no-default-features' FEATURES='u64_backend nightly'
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- rust: stable
|
||||
env: TEST_COMMAND=test EXTRA_FLAGS='--no-default-features' FEATURES='std u64_backend'
|
||||
- rust: beta
|
||||
env: TEST_COMMAND=test EXTRA_FLAGS='--no-default-features' FEATURES='std u64_backend'
|
||||
|
||||
script:
|
||||
- cargo $TEST_COMMAND --features="$FEATURES" $EXTRA_FLAGS
|
||||
|
||||
notifications:
|
||||
slack:
|
||||
rooms:
|
||||
- dalek-cryptography:Xxv9WotKYWdSoKlgKNqXiHoD#dalek-bots
|
||||
98
CHANGELOG.md
Normal file
98
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# Changelog
|
||||
|
||||
Entries are listed in reverse chronological order.
|
||||
|
||||
# 2.x Series
|
||||
|
||||
* Note: All `x255919-dalek` 2.x releases are in sync with the underlying `curve25519-dalek` 4.x releases.
|
||||
|
||||
## 2.0.0-rc.3
|
||||
|
||||
* `StaticSecret` serialization and `to_bytes()` no longer returns clamped integers. Clamping is still always done during scalar-point multiplication.
|
||||
* Update underlying `curve25519_dalek` library to `4.0.0-rc.3`. Notable changes:
|
||||
* [curve25519-dalek backend] now by default auto selects `simd` backend over `serial` where supported.
|
||||
|
||||
|
||||
## 2.0.0-rc.2
|
||||
|
||||
* Update MSRV to 1.60.
|
||||
* Update edition to 2021
|
||||
* Add `.as_bytes()` and `AsRef<[u8]>` for `Shared/StaticSecret`
|
||||
* Add `getrandom` feature to provide `random_from_rng` constructors
|
||||
* Make `StaticSecrets` optional via feature `static_secrets`
|
||||
* Update underlying `curve25519_dalek` library to `4.0.0-rc.2`. Notable changes:
|
||||
* [curve25519-dalek backend] additive features have been removed in favor of cfg based selection.
|
||||
* [curve25519-dalek backend] now by default auto selects the appropriate word size over the previous default `32`.
|
||||
|
||||
## 2.0.0-pre.1
|
||||
|
||||
* Loosen restriction on zeroize dependency version from =1.3 to 1.
|
||||
* Update MSRV to 1.51.
|
||||
|
||||
## 2.0.0-pre.0
|
||||
|
||||
* Update `rand_core` dependency to `0.6`.
|
||||
|
||||
# 1.x Series
|
||||
|
||||
## 1.2
|
||||
|
||||
* Add module documentation for using the bytes-oriented `x25519()` API.
|
||||
* Add implementation of `zeroize::Zeroize` for `PublicKey`.
|
||||
* Move unittests to a separate directory.
|
||||
* Add cargo feature flags `"fiat_u32_backend"` and `"fiat_u64_backend"` for
|
||||
activating the Fiat crypto field element implementations.
|
||||
* Fix issue with removed `feature(external_doc)` on nightly compilers.
|
||||
* Pin `zeroize` to version 1.3 to support a wider range of MSRVs.
|
||||
* Add CI via Github actions.
|
||||
* Fix breakage in the serde unittests.
|
||||
* MSRV is now 1.41 for production and 1.48 for development.
|
||||
* Add an optional check to `SharedSecret` for contibutory behaviour.
|
||||
* Add implementation of `ReusableSecret` keys which are non-ephemeral, but which
|
||||
cannot be serialised to discourage long-term use.
|
||||
|
||||
## 1.1.1
|
||||
|
||||
* Fix a typo in the README.
|
||||
|
||||
## 1.1.0
|
||||
|
||||
* Add impls of `PartialEq`, `Eq`, and `Hash` for `PublicKey` (by @jack-michaud)
|
||||
|
||||
## 1.0.1
|
||||
|
||||
* Update underlying `curve25519_dalek` library to `3.0`.
|
||||
|
||||
## 1.0.0
|
||||
|
||||
* Widen generic bound on `EphemeralSecret::new` and `StaticSecret::new` to
|
||||
allow owned as well as borrowed RNGs.
|
||||
* Add `PublicKey::to_bytes` and `SharedSecret::to_bytes`, returning owned byte
|
||||
arrays, complementing the existing `as_bytes` methods returning references.
|
||||
* Remove mention of deprecated `rand_os` crate from examples.
|
||||
* Clarify `EphemeralSecret`/`StaticSecret` distinction in documentation.
|
||||
|
||||
# Pre-1.0.0
|
||||
|
||||
## 0.6.0
|
||||
|
||||
* Updates `rand_core` version to `0.5`.
|
||||
* Adds `serde` support.
|
||||
* Replaces `clear_on_drop` with `zeroize`.
|
||||
* Use Rust 2018.
|
||||
|
||||
## 0.5.2
|
||||
|
||||
* Implement `Clone` for `StaticSecret`.
|
||||
|
||||
## 0.5.1
|
||||
|
||||
* Implement `Copy, Clone, Debug` for `PublicKey`.
|
||||
* Remove doctests.
|
||||
|
||||
## 0.5.0
|
||||
|
||||
* Adds support for static and ephemeral keys.
|
||||
|
||||
[curve25519-dalek backend]: https://github.com/dalek-cryptography/curve25519-dalek/#backends
|
||||
|
||||
28
CONTRIBUTING.md
Normal file
28
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Contributing to curve25519-dalek
|
||||
|
||||
If you have questions or comments, please feel free to email the
|
||||
authors.
|
||||
|
||||
For feature requests, suggestions, and bug reports, please open an issue on
|
||||
[our Github](https://github.com/dalek-cryptography/x25519-dalek). (Or, send us
|
||||
an email if you're opposed to using Github for whatever reason.)
|
||||
|
||||
Patches are welcomed as pull requests on
|
||||
[our Github](https://github.com/dalek-cryptography/x25519-dalek), as well as by
|
||||
email (preferably sent to all of the authors listed in `Cargo.toml`).
|
||||
|
||||
All issues on curve25519-dalek are mentored, if you want help with a bug just
|
||||
ask @isislovecruft.
|
||||
|
||||
Some issues are easier than others. The `easy` label can be used to find the
|
||||
easy issues. If you want to work on an issue, please leave a comment so that we
|
||||
can assign it to you!
|
||||
|
||||
# Code of Conduct
|
||||
|
||||
We follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html),
|
||||
with the following additional clauses:
|
||||
|
||||
* We respect the rights to privacy and anonymity for contributors and people in
|
||||
the community. If someone wishes to contribute under a pseudonym different to
|
||||
their primary identity, that wish is to be respected by all contributors.
|
||||
735
Cargo.lock
generated
Normal file
735
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,735 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "anes"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.19",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"ciborium-ll",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-io"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-ll"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.2.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb"
|
||||
dependencies = [
|
||||
"anes",
|
||||
"atty",
|
||||
"cast",
|
||||
"ciborium",
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"num-traits",
|
||||
"oorandom",
|
||||
"plotters",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tinytemplate",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "4.0.0-rc.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "436ace70fc06e06f7f689d2624dc4e2f0ea666efb5aa704215f7249ae6e047a7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"curve25519-dalek-derive",
|
||||
"fiat-crypto",
|
||||
"platforms",
|
||||
"rustc_version",
|
||||
"serde",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek-derive"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93ace6ec7cc19c8ed33a32eaa9ea692d7faea05006b5356b9e2b668ec4bc3955"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
||||
dependencies = [
|
||||
"hermit-abi 0.2.6",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267"
|
||||
|
||||
[[package]]
|
||||
name = "platforms"
|
||||
version = "3.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"plotters-backend",
|
||||
"plotters-svg",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
|
||||
dependencies = [
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.159"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.159"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "x25519-dalek"
|
||||
version = "2.0.0-rc.3"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"criterion",
|
||||
"curve25519-dalek",
|
||||
"rand_core",
|
||||
"serde",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
|
||||
dependencies = [
|
||||
"zeroize_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize_derive"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.12",
|
||||
]
|
||||
63
Cargo.toml
Normal file
63
Cargo.toml
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
[package]
|
||||
name = "x25519-dalek"
|
||||
edition = "2021"
|
||||
# Before changing this:
|
||||
# - update version in README.md
|
||||
# - update html_root_url
|
||||
# - update CHANGELOG
|
||||
# - if any changes were made to README.md, mirror them in src/lib.rs docs
|
||||
version = "2.0.0-rc.3"
|
||||
authors = [
|
||||
"Isis Lovecruft <isis@patternsinthevoid.net>",
|
||||
"DebugSteven <debugsteven@gmail.com>",
|
||||
"Henry de Valence <hdevalence@hdevalence.ca>",
|
||||
]
|
||||
readme = "README.md"
|
||||
license = "BSD-3-Clause"
|
||||
repository = "https://github.com/dalek-cryptography/x25519-dalek"
|
||||
homepage = "https://dalek.rs/"
|
||||
documentation = "https://docs.rs/x25519-dalek"
|
||||
categories = ["cryptography", "no-std"]
|
||||
keywords = ["cryptography", "curve25519", "key-exchange", "x25519", "diffie-hellman"]
|
||||
description = "X25519 elliptic curve Diffie-Hellman key exchange in pure-Rust, using curve25519-dalek."
|
||||
exclude = [
|
||||
".gitignore",
|
||||
".travis.yml",
|
||||
"CONTRIBUTING.md",
|
||||
]
|
||||
rust-version = "1.60"
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "dalek-cryptography/x25519-dalek", branch = "master"}
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = [
|
||||
"--html-in-header", "docs/assets/rustdoc-include-katex-header.html",
|
||||
"--cfg", "docsrs",
|
||||
]
|
||||
features = ["getrandom", "reusable_secrets", "serde", "static_secrets"]
|
||||
|
||||
[dependencies]
|
||||
curve25519-dalek = { version = "=4.0.0-rc.3", default-features = false }
|
||||
rand_core = { version = "0.6", default-features = false }
|
||||
serde = { version = "1", default-features = false, optional = true, features = ["derive"] }
|
||||
zeroize = { version = "1", default-features = false, optional = true, features = ["zeroize_derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
bincode = "1"
|
||||
criterion = "0.4.0"
|
||||
rand_core = { version = "0.6", default-features = false, features = ["getrandom"] }
|
||||
|
||||
[[bench]]
|
||||
name = "x25519"
|
||||
harness = false
|
||||
|
||||
[features]
|
||||
default = ["alloc", "precomputed-tables", "zeroize"]
|
||||
getrandom = ["rand_core/getrandom"]
|
||||
zeroize = ["dep:zeroize", "curve25519-dalek/zeroize"]
|
||||
serde = ["dep:serde", "curve25519-dalek/serde"]
|
||||
alloc = ["curve25519-dalek/alloc", "serde?/alloc", "zeroize?/alloc"]
|
||||
precomputed-tables = ["curve25519-dalek/precomputed-tables"]
|
||||
reusable_secrets = []
|
||||
static_secrets = []
|
||||
29
LICENSE
Normal file
29
LICENSE
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
Copyright (c) 2017-2021 isis agora lovecruft. All rights reserved.
|
||||
Copyright (c) 2019-2021 DebugSteven. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
139
README.md
Normal file
139
README.md
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
# x25519-dalek [](https://crates.io/crates/x25519-dalek) [](https://docs.rs/x25519-dalek) [](https://travis-ci.org/dalek-cryptography/x25519-dalek)
|
||||
|
||||
A pure-Rust implementation of x25519 elliptic curve Diffie-Hellman key exchange,
|
||||
with curve operations provided by
|
||||
[curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek).
|
||||
|
||||
This crate provides two levels of API: a bare byte-oriented `x25519`
|
||||
function which matches the function specified in [RFC7748][rfc7748], as
|
||||
well as a higher-level Rust API for static and ephemeral Diffie-Hellman.
|
||||
|
||||
## Examples
|
||||
|
||||
<a href="https://shop.bubblesort.io">
|
||||
<img
|
||||
style="float: right; width: auto; height: 300px;"
|
||||
src="https://raw.githubusercontent.com/dalek-cryptography/x25519-dalek/master/res/bubblesort-zines-secret-messages-cover.jpeg"/>
|
||||
</a>
|
||||
|
||||
Alice and Bob are two adorable kittens who have lost their mittens, and they
|
||||
wish to be able to send secret messages to each other to coordinate finding
|
||||
them, otherwise—if their caretaker cat finds out—they will surely be called
|
||||
naughty kittens and be given no pie!
|
||||
|
||||
But the two kittens are quite clever. Even though their paws are still too big
|
||||
and the rest of them is 90% fuzziness, these clever kittens have been studying
|
||||
up on modern public key cryptography and have learned a nifty trick called
|
||||
*elliptic curve Diffie-Hellman key exchange*. With the right incantations, the
|
||||
kittens will be able to secretly organise to find their mittens, and then spend
|
||||
the rest of the afternoon nomming some yummy pie!
|
||||
|
||||
First, Alice uses `EphemeralSecret::random()` and then
|
||||
`PublicKey::from()` to produce her secret and public keys:
|
||||
|
||||
```ignore
|
||||
use x25519_dalek::{EphemeralSecret, PublicKey};
|
||||
|
||||
let alice_secret = EphemeralSecret::random();
|
||||
let alice_public = PublicKey::from(&alice_secret);
|
||||
```
|
||||
|
||||
Bob does the same:
|
||||
|
||||
```ignore
|
||||
# use x25519_dalek::{EphemeralSecret, PublicKey};
|
||||
let bob_secret = EphemeralSecret::random();
|
||||
let bob_public = PublicKey::from(&bob_secret);
|
||||
```
|
||||
|
||||
Alice meows across the room, telling `alice_public` to Bob, and Bob
|
||||
loudly meows `bob_public` back to Alice. Alice now computes her
|
||||
shared secret with Bob by doing:
|
||||
|
||||
```rust
|
||||
# use rand_core::OsRng;
|
||||
# use x25519_dalek::{EphemeralSecret, PublicKey};
|
||||
# let alice_secret = EphemeralSecret::new(OsRng);
|
||||
# let alice_public = PublicKey::from(&alice_secret);
|
||||
# let bob_secret = EphemeralSecret::new(OsRng);
|
||||
# let bob_public = PublicKey::from(&bob_secret);
|
||||
let alice_shared_secret = alice_secret.diffie_hellman(&bob_public);
|
||||
```
|
||||
|
||||
Similarly, Bob computes a shared secret by doing:
|
||||
|
||||
```rust
|
||||
# use rand_core::OsRng;
|
||||
# use x25519_dalek::{EphemeralSecret, PublicKey};
|
||||
# let alice_secret = EphemeralSecret::new(OsRng);
|
||||
# let alice_public = PublicKey::from(&alice_secret);
|
||||
# let bob_secret = EphemeralSecret::new(OsRng);
|
||||
# let bob_public = PublicKey::from(&bob_secret);
|
||||
let bob_shared_secret = bob_secret.diffie_hellman(&alice_public);
|
||||
```
|
||||
|
||||
These secrets are the same:
|
||||
|
||||
```rust
|
||||
# use rand_core::OsRng;
|
||||
# use x25519_dalek::{EphemeralSecret, PublicKey};
|
||||
# let alice_secret = EphemeralSecret::new(OsRng);
|
||||
# let alice_public = PublicKey::from(&alice_secret);
|
||||
# let bob_secret = EphemeralSecret::new(OsRng);
|
||||
# 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!(alice_shared_secret.as_bytes(), bob_shared_secret.as_bytes());
|
||||
```
|
||||
|
||||
Voilà! Alice and Bob can now use their shared secret to encrypt their
|
||||
meows, for example, by using it to generate a key and nonce for an
|
||||
authenticated-encryption cipher.
|
||||
|
||||
This example used the ephemeral DH API, which ensures that secret keys
|
||||
cannot be reused; Alice and Bob could instead use the static DH API
|
||||
and load a long-term secret key.
|
||||
|
||||
# Installation
|
||||
|
||||
To install, add the following to your project's `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
x25519-dalek = "2.0.0-rc.3"
|
||||
```
|
||||
|
||||
# MSRV
|
||||
|
||||
Current MSRV is 1.60.
|
||||
|
||||
# Documentation
|
||||
|
||||
Documentation is available [here](https://docs.rs/x25519-dalek).
|
||||
|
||||
# Performance and backend selection
|
||||
|
||||
Performance is a secondary goal behind correctness, safety, and clarity, but we aim to be competitive with other implementations. To this end, we allow users to choose their _backend_, i.e., the underlying implementation of elliptic curve and scalar arithmetic. Different backends have different use cases. For example, if you demand formally verified code, you want to use the `fiat` backend (as it was generated from [Fiat Crypto][fiat]).
|
||||
|
||||
Further instructions and details regarding backends can be found in the [curve25519-dalek docs](https://github.com/dalek-cryptography/curve25519-dalek#backends).
|
||||
|
||||
# Note
|
||||
|
||||
This code matches the [RFC7748][rfc7748] test vectors.
|
||||
The elliptic curve
|
||||
operations are provided by `curve25519-dalek`, which makes a best-effort
|
||||
attempt to prevent software side-channels.
|
||||
|
||||
"Secret Messages" cover image and [zine](https://shop.bubblesort.io/products/secret-messages-zine)
|
||||
copyright © Amy Wibowo ([@sailorhg](https://twitter.com/sailorhg))
|
||||
|
||||
[rfc7748]: https://tools.ietf.org/html/rfc7748
|
||||
|
||||
# See also
|
||||
|
||||
- [crypto_box]: pure Rust public-key authenticated encryption compatible with
|
||||
the NaCl family of encryption libraries (libsodium, TweetNaCl) which uses
|
||||
`x25519-dalek` for key agreement
|
||||
|
||||
[fiat]: https://github.com/mit-plv/fiat-crypto
|
||||
[crypto_box]: https://github.com/RustCrypto/nacl-compat/tree/master/crypto_box
|
||||
41
benches/x25519.rs
Normal file
41
benches/x25519.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of x25519-dalek.
|
||||
// Copyright (c) 2017-2019 isis agora lovecruft
|
||||
// Copyright (c) 2019 DebugSteven
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
// - isis agora lovecruft <isis@patternsinthevoid.net>
|
||||
// - DebugSteven <debugsteven@gmail.com>
|
||||
|
||||
//! Benchmark the Diffie-Hellman operation.
|
||||
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
|
||||
use rand_core::OsRng;
|
||||
|
||||
use x25519_dalek::EphemeralSecret;
|
||||
use x25519_dalek::PublicKey;
|
||||
|
||||
fn bench_diffie_hellman(c: &mut Criterion) {
|
||||
let bob_secret = EphemeralSecret::random_from_rng(OsRng);
|
||||
let bob_public = PublicKey::from(&bob_secret);
|
||||
|
||||
c.bench_function("diffie_hellman", move |b| {
|
||||
b.iter_with_setup(
|
||||
|| EphemeralSecret::random_from_rng(OsRng),
|
||||
|alice_secret| alice_secret.diffie_hellman(&bob_public),
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group! {
|
||||
name = x25519_benches;
|
||||
config = Criterion::default();
|
||||
targets =
|
||||
bench_diffie_hellman,
|
||||
}
|
||||
criterion_main! {
|
||||
x25519_benches,
|
||||
}
|
||||
12
docs/assets/rustdoc-include-katex-header.html
Normal file
12
docs/assets/rustdoc-include-katex-header.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.3/dist/katex.min.css" integrity="sha384-Juol1FqnotbkyZUT5Z7gUPjQ9gzlwCENvUZTpQBAPxtusdwFLRy382PSDx5UUJ4/" crossorigin="anonymous">
|
||||
|
||||
<!-- The loading of KaTeX is deferred to speed up page rendering -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.3/dist/katex.min.js" integrity="sha384-97gW6UIJxnlKemYavrqDHSX3SiygeOwIZhwyOKRfSaf0JWKRVj9hLASHgFTzT+0O" crossorigin="anonymous"></script>
|
||||
|
||||
<!-- To automatically render math in text elements, include the auto-render extension: -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.3/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"
|
||||
onload="renderMathInElement(document.body);"></script>
|
||||
|
||||
<style>
|
||||
.katex { font-size: 1em !important; }
|
||||
</style>
|
||||
BIN
res/bubblesort-zines-secret-messages-cover.jpeg
Normal file
BIN
res/bubblesort-zines-secret-messages-cover.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 73 KiB |
33
src/lib.rs
Normal file
33
src/lib.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of x25519-dalek.
|
||||
// Copyright (c) 2017-2021 isis lovecruft
|
||||
// Copyright (c) 2019-2021 DebugSteven
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
// - isis agora lovecruft <isis@patternsinthevoid.net>
|
||||
// - DebugSteven <debugsteven@gmail.com>
|
||||
|
||||
// Refuse to compile if documentation is missing, but only on nightly.
|
||||
//
|
||||
// This means that missing docs will still fail CI, but means we can use
|
||||
// README.md as the crate documentation.
|
||||
|
||||
#![no_std]
|
||||
#![cfg_attr(feature = "bench", feature(test))]
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg, doc_cfg_hide))]
|
||||
#![cfg_attr(docsrs, doc(cfg_hide(docsrs)))]
|
||||
#![deny(missing_docs)]
|
||||
#![doc(
|
||||
html_logo_url = "https://cdn.jsdelivr.net/gh/dalek-cryptography/curve25519-dalek/docs/assets/dalek-logo-clear.png"
|
||||
)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// x25519-dalek public API
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
mod x25519;
|
||||
|
||||
pub use crate::x25519::*;
|
||||
377
src/x25519.rs
Normal file
377
src/x25519.rs
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of x25519-dalek.
|
||||
// Copyright (c) 2017-2021 isis lovecruft
|
||||
// Copyright (c) 2019-2021 DebugSteven
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
// - isis agora lovecruft <isis@patternsinthevoid.net>
|
||||
// - DebugSteven <debugsteven@gmail.com>
|
||||
|
||||
//! x25519 Diffie-Hellman key exchange
|
||||
//!
|
||||
//! This implements x25519 key exchange as specified by Mike Hamburg
|
||||
//! and Adam Langley in [RFC7748](https://tools.ietf.org/html/rfc7748).
|
||||
|
||||
use curve25519_dalek::{edwards::EdwardsPoint, montgomery::MontgomeryPoint, traits::IsIdentity};
|
||||
|
||||
use rand_core::CryptoRng;
|
||||
use rand_core::RngCore;
|
||||
|
||||
#[cfg(feature = "zeroize")]
|
||||
use zeroize::Zeroize;
|
||||
|
||||
/// A Diffie-Hellman public key
|
||||
///
|
||||
/// We implement `Zeroize` so that downstream consumers may derive it for `Drop`
|
||||
/// should they wish to erase public keys from memory. Note that this erasure
|
||||
/// (in this crate) does *not* automatically happen, but either must be derived
|
||||
/// for Drop or explicitly called.
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
|
||||
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
|
||||
pub struct PublicKey(pub(crate) MontgomeryPoint);
|
||||
|
||||
impl From<[u8; 32]> for PublicKey {
|
||||
/// Given a byte array, construct a x25519 `PublicKey`.
|
||||
fn from(bytes: [u8; 32]) -> PublicKey {
|
||||
PublicKey(MontgomeryPoint(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl PublicKey {
|
||||
/// Convert this public key to a byte array.
|
||||
#[inline]
|
||||
pub fn to_bytes(&self) -> [u8; 32] {
|
||||
self.0.to_bytes()
|
||||
}
|
||||
|
||||
/// View this public key as a byte array.
|
||||
#[inline]
|
||||
pub fn as_bytes(&self) -> &[u8; 32] {
|
||||
self.0.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for PublicKey {
|
||||
/// View this public key as a byte array.
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
/// A short-lived Diffie-Hellman secret key that can only be used to compute a single
|
||||
/// [`SharedSecret`].
|
||||
///
|
||||
/// This type is identical to the `StaticSecret` type, except that the
|
||||
/// [`EphemeralSecret::diffie_hellman`] method consumes and then wipes the secret key, and there
|
||||
/// are no serialization methods defined. This means that [`EphemeralSecret`]s can only be
|
||||
/// generated from fresh randomness where the compiler statically checks that the resulting
|
||||
/// secret is used at most once.
|
||||
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
|
||||
#[cfg_attr(feature = "zeroize", zeroize(drop))]
|
||||
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(their_public.0.mul_clamped(self.0))
|
||||
}
|
||||
|
||||
/// Generate a new [`EphemeralSecret`] with the supplied RNG.
|
||||
#[deprecated(
|
||||
since = "2.0.0",
|
||||
note = "Renamed to `random_from_rng`. This will be removed in 2.1.0"
|
||||
)]
|
||||
pub fn new<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
|
||||
Self::random_from_rng(&mut csprng)
|
||||
}
|
||||
|
||||
/// Generate a new [`EphemeralSecret`] with the supplied RNG.
|
||||
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
|
||||
// The secret key is random bytes. Clamping is done later.
|
||||
let mut bytes = [0u8; 32];
|
||||
csprng.fill_bytes(&mut bytes);
|
||||
EphemeralSecret(bytes)
|
||||
}
|
||||
|
||||
/// Generate a new [`EphemeralSecret`].
|
||||
#[cfg(feature = "getrandom")]
|
||||
pub fn random() -> Self {
|
||||
Self::random_from_rng(&mut rand_core::OsRng)
|
||||
}
|
||||
}
|
||||
|
||||
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_clamped(secret.0).to_montgomery())
|
||||
}
|
||||
}
|
||||
|
||||
/// A Diffie-Hellman secret key which may be used more than once, but is
|
||||
/// purposefully not serialiseable in order to discourage key-reuse. This is
|
||||
/// implemented to facilitate protocols such as Noise (e.g. Noise IK key usage,
|
||||
/// etc.) and X3DH which require an "ephemeral" key to conduct the
|
||||
/// Diffie-Hellman operation multiple times throughout the protocol, while the
|
||||
/// protocol run at a higher level is only conducted once per key.
|
||||
///
|
||||
/// Similarly to [`EphemeralSecret`], this type does _not_ have serialisation
|
||||
/// methods, in order to discourage long-term usage of secret key material. (For
|
||||
/// long-term secret keys, see `StaticSecret`.)
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// If you're uncertain about whether you should use this, then you likely
|
||||
/// should not be using this. Our strongly recommended advice is to use
|
||||
/// [`EphemeralSecret`] at all times, as that type enforces at compile-time that
|
||||
/// secret keys are never reused, which can have very serious security
|
||||
/// implications for many protocols.
|
||||
#[cfg(feature = "reusable_secrets")]
|
||||
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
|
||||
#[cfg_attr(feature = "zeroize", zeroize(drop))]
|
||||
#[derive(Clone)]
|
||||
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(their_public.0.mul_clamped(self.0))
|
||||
}
|
||||
|
||||
/// Generate a new [`ReusableSecret`] with the supplied RNG.
|
||||
#[deprecated(
|
||||
since = "2.0.0",
|
||||
note = "Renamed to `random_from_rng`. This will be removed in 2.1.0."
|
||||
)]
|
||||
pub fn new<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
|
||||
Self::random_from_rng(&mut csprng)
|
||||
}
|
||||
|
||||
/// Generate a new [`ReusableSecret`] with the supplied RNG.
|
||||
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
|
||||
// The secret key is random bytes. Clamping is done later.
|
||||
let mut bytes = [0u8; 32];
|
||||
csprng.fill_bytes(&mut bytes);
|
||||
ReusableSecret(bytes)
|
||||
}
|
||||
|
||||
/// Generate a new [`ReusableSecret`].
|
||||
#[cfg(feature = "getrandom")]
|
||||
pub fn random() -> Self {
|
||||
Self::random_from_rng(&mut rand_core::OsRng)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "reusable_secrets")]
|
||||
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_clamped(secret.0).to_montgomery())
|
||||
}
|
||||
}
|
||||
|
||||
/// A Diffie-Hellman secret key that can be used to compute multiple [`SharedSecret`]s.
|
||||
///
|
||||
/// This type is identical to the [`EphemeralSecret`] type, except that the
|
||||
/// [`StaticSecret::diffie_hellman`] method does not consume the secret key, and the type provides
|
||||
/// serialization methods to save and load key material. This means that the secret may be used
|
||||
/// multiple times (but does not *have to be*).
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// If you're uncertain about whether you should use this, then you likely
|
||||
/// should not be using this. Our strongly recommended advice is to use
|
||||
/// [`EphemeralSecret`] at all times, as that type enforces at compile-time that
|
||||
/// secret keys are never reused, which can have very serious security
|
||||
/// implications for many protocols.
|
||||
#[cfg(feature = "static_secrets")]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
|
||||
#[cfg_attr(feature = "zeroize", zeroize(drop))]
|
||||
#[derive(Clone)]
|
||||
pub struct StaticSecret([u8; 32]);
|
||||
|
||||
#[cfg(feature = "static_secrets")]
|
||||
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(their_public.0.mul_clamped(self.0))
|
||||
}
|
||||
|
||||
/// Generate a new [`StaticSecret`] with the supplied RNG.
|
||||
#[deprecated(
|
||||
since = "2.0.0",
|
||||
note = "Renamed to `random_from_rng`. This will be removed in 2.1.0"
|
||||
)]
|
||||
pub fn new<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
|
||||
Self::random_from_rng(&mut csprng)
|
||||
}
|
||||
|
||||
/// Generate a new [`StaticSecret`] with the supplied RNG.
|
||||
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
|
||||
// The secret key is random bytes. Clamping is done later.
|
||||
let mut bytes = [0u8; 32];
|
||||
csprng.fill_bytes(&mut bytes);
|
||||
StaticSecret(bytes)
|
||||
}
|
||||
|
||||
/// Generate a new [`StaticSecret`].
|
||||
#[cfg(feature = "getrandom")]
|
||||
pub fn random() -> Self {
|
||||
Self::random_from_rng(&mut rand_core::OsRng)
|
||||
}
|
||||
|
||||
/// Extract this key's bytes for serialization.
|
||||
#[inline]
|
||||
pub fn to_bytes(&self) -> [u8; 32] {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// View this key as a byte array.
|
||||
#[inline]
|
||||
pub fn as_bytes(&self) -> &[u8; 32] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "static_secrets")]
|
||||
impl From<[u8; 32]> for StaticSecret {
|
||||
/// Load a secret key from a byte array.
|
||||
fn from(bytes: [u8; 32]) -> StaticSecret {
|
||||
StaticSecret(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "static_secrets")]
|
||||
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_clamped(secret.0).to_montgomery())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "static_secrets")]
|
||||
impl AsRef<[u8]> for StaticSecret {
|
||||
/// View this key as a byte array.
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of a Diffie-Hellman key exchange.
|
||||
///
|
||||
/// Each party computes this using their [`EphemeralSecret`] or [`StaticSecret`] and their
|
||||
/// counterparty's [`PublicKey`].
|
||||
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
|
||||
#[cfg_attr(feature = "zeroize", zeroize(drop))]
|
||||
pub struct SharedSecret(pub(crate) MontgomeryPoint);
|
||||
|
||||
impl SharedSecret {
|
||||
/// Convert this shared secret to a byte array.
|
||||
#[inline]
|
||||
pub fn to_bytes(&self) -> [u8; 32] {
|
||||
self.0.to_bytes()
|
||||
}
|
||||
|
||||
/// View this shared secret key as a byte array.
|
||||
#[inline]
|
||||
pub fn as_bytes(&self) -> &[u8; 32] {
|
||||
self.0.as_bytes()
|
||||
}
|
||||
|
||||
/// Ensure in constant-time that this shared secret did not result from a
|
||||
/// key exchange with non-contributory behaviour.
|
||||
///
|
||||
/// In some more exotic protocols which need to guarantee "contributory"
|
||||
/// behaviour for both parties, that is, that each party contributed a public
|
||||
/// value which increased the security of the resulting shared secret.
|
||||
/// To take an example protocol attack where this could lead to undesirable
|
||||
/// results [from Thái "thaidn" Dương](https://vnhacker.blogspot.com/2015/09/why-not-validating-curve25519-public.html):
|
||||
///
|
||||
/// > If Mallory replaces Alice's and Bob's public keys with zero, which is
|
||||
/// > a valid Curve25519 public key, he would be able to force the ECDH
|
||||
/// > shared value to be zero, which is the encoding of the point at infinity,
|
||||
/// > and thus get to dictate some publicly known values as the shared
|
||||
/// > keys. It still requires an active man-in-the-middle attack to pull the
|
||||
/// > trick, after which, however, not only Mallory can decode Alice's data,
|
||||
/// > but everyone too! It is also impossible for Alice and Bob to detect the
|
||||
/// > intrusion, as they still share the same keys, and can communicate with
|
||||
/// > each other as normal.
|
||||
///
|
||||
/// The original Curve25519 specification argues that checks for
|
||||
/// non-contributory behaviour are "unnecessary for Diffie-Hellman".
|
||||
/// Whether this check is necessary for any particular given protocol is
|
||||
/// often a matter of debate, which we will not re-hash here, but simply
|
||||
/// cite some of the [relevant] [public] [discussions].
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `true` if the key exchange was contributory (good), and `false`
|
||||
/// otherwise (can be bad for some protocols).
|
||||
///
|
||||
/// [relevant]: https://tools.ietf.org/html/rfc7748#page-15
|
||||
/// [public]: https://vnhacker.blogspot.com/2015/09/why-not-validating-curve25519-public.html
|
||||
/// [discussions]: https://vnhacker.blogspot.com/2016/08/the-internet-of-broken-protocols.html
|
||||
#[must_use]
|
||||
pub fn was_contributory(&self) -> bool {
|
||||
!self.0.is_identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for SharedSecret {
|
||||
/// View this shared secret key as a byte array.
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
/// The bare, byte-oriented x25519 function, exactly as specified in RFC7748.
|
||||
///
|
||||
/// This can be used with [`X25519_BASEPOINT_BYTES`] for people who
|
||||
/// cannot use the better, safer, and faster ephemeral DH API.
|
||||
///
|
||||
/// # Example
|
||||
#[cfg_attr(feature = "static_secrets", doc = "```")]
|
||||
#[cfg_attr(not(feature = "static_secrets"), doc = "```ignore")]
|
||||
/// use rand_core::OsRng;
|
||||
/// use rand_core::RngCore;
|
||||
///
|
||||
/// use x25519_dalek::x25519;
|
||||
/// use x25519_dalek::StaticSecret;
|
||||
/// use x25519_dalek::PublicKey;
|
||||
///
|
||||
/// // Generate Alice's key pair.
|
||||
/// let alice_secret = StaticSecret::random_from_rng(&mut OsRng);
|
||||
/// let alice_public = PublicKey::from(&alice_secret);
|
||||
///
|
||||
/// // Generate Bob's key pair.
|
||||
/// let bob_secret = StaticSecret::random_from_rng(&mut OsRng);
|
||||
/// let bob_public = PublicKey::from(&bob_secret);
|
||||
///
|
||||
/// // Alice and Bob should now exchange their public keys.
|
||||
///
|
||||
/// // Once they've done so, they may generate a shared secret.
|
||||
/// let alice_shared = x25519(alice_secret.to_bytes(), bob_public.to_bytes());
|
||||
/// let bob_shared = x25519(bob_secret.to_bytes(), alice_public.to_bytes());
|
||||
///
|
||||
/// assert_eq!(alice_shared, bob_shared);
|
||||
/// ```
|
||||
pub fn x25519(k: [u8; 32], u: [u8; 32]) -> [u8; 32] {
|
||||
MontgomeryPoint(u).mul_clamped(k).to_bytes()
|
||||
}
|
||||
|
||||
/// The X25519 basepoint, for use with the bare, byte-oriented x25519
|
||||
/// function. This is provided for people who cannot use the typed
|
||||
/// DH API for some reason.
|
||||
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,
|
||||
];
|
||||
231
tests/x25519_tests.rs
Normal file
231
tests/x25519_tests.rs
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
use curve25519_dalek::edwards::EdwardsPoint;
|
||||
|
||||
use x25519_dalek::*;
|
||||
|
||||
#[test]
|
||||
fn byte_basepoint_matches_edwards_scalar_mul() {
|
||||
let mut scalar_bytes = [0x37; 32];
|
||||
|
||||
for i in 0..32 {
|
||||
scalar_bytes[i] += 2;
|
||||
|
||||
let result = x25519(scalar_bytes, X25519_BASEPOINT_BYTES);
|
||||
let expected = EdwardsPoint::mul_base_clamped(scalar_bytes)
|
||||
.to_montgomery()
|
||||
.to_bytes();
|
||||
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "serde")]
|
||||
fn serde_bincode_public_key_roundtrip() {
|
||||
use bincode;
|
||||
|
||||
let public_key = PublicKey::from(X25519_BASEPOINT_BYTES);
|
||||
|
||||
let encoded = bincode::serialize(&public_key).unwrap();
|
||||
let decoded: PublicKey = bincode::deserialize(&encoded).unwrap();
|
||||
|
||||
assert_eq!(encoded.len(), 32);
|
||||
assert_eq!(decoded.as_bytes(), public_key.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "serde")]
|
||||
fn serde_bincode_public_key_matches_from_bytes() {
|
||||
use bincode;
|
||||
|
||||
let expected = PublicKey::from(X25519_BASEPOINT_BYTES);
|
||||
let decoded: PublicKey = bincode::deserialize(&X25519_BASEPOINT_BYTES).unwrap();
|
||||
|
||||
assert_eq!(decoded.as_bytes(), expected.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "serde")]
|
||||
fn serde_bincode_static_secret_roundtrip() {
|
||||
use bincode;
|
||||
|
||||
let static_secret = StaticSecret::from([0x24; 32]);
|
||||
let encoded = bincode::serialize(&static_secret).unwrap();
|
||||
let decoded: StaticSecret = bincode::deserialize(&encoded).unwrap();
|
||||
|
||||
assert_eq!(encoded.len(), 32);
|
||||
assert_eq!(decoded.to_bytes(), static_secret.to_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "serde")]
|
||||
fn serde_bincode_static_secret_matches_from_bytes() {
|
||||
use bincode;
|
||||
|
||||
let expected = StaticSecret::from([0x24; 32]);
|
||||
let decoded: StaticSecret = bincode::deserialize(&[0x24; 32]).unwrap();
|
||||
|
||||
assert_eq!(decoded.to_bytes(), expected.to_bytes());
|
||||
}
|
||||
|
||||
fn do_rfc7748_ladder_test1(input_scalar: [u8; 32], input_point: [u8; 32], expected: [u8; 32]) {
|
||||
let result = x25519(input_scalar, input_point);
|
||||
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rfc7748_ladder_test1_vectorset1() {
|
||||
let input_scalar: [u8; 32] = [
|
||||
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e,
|
||||
0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44,
|
||||
0x9a, 0xc4,
|
||||
];
|
||||
let input_point: [u8; 32] = [
|
||||
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f,
|
||||
0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab,
|
||||
0x1c, 0x4c,
|
||||
];
|
||||
let expected: [u8; 32] = [
|
||||
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08,
|
||||
0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2,
|
||||
0x85, 0x52,
|
||||
];
|
||||
|
||||
do_rfc7748_ladder_test1(input_scalar, input_point, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rfc7748_ladder_test1_vectorset2() {
|
||||
let input_scalar: [u8; 32] = [
|
||||
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a,
|
||||
0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18,
|
||||
0xba, 0x0d,
|
||||
];
|
||||
let input_point: [u8; 32] = [
|
||||
0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae,
|
||||
0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15,
|
||||
0xa4, 0x93,
|
||||
];
|
||||
let expected: [u8; 32] = [
|
||||
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73,
|
||||
0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac,
|
||||
0x79, 0x57,
|
||||
];
|
||||
|
||||
do_rfc7748_ladder_test1(input_scalar, input_point, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // Run only if you want to burn a lot of CPU doing 1,000,000 DH operations
|
||||
fn rfc7748_ladder_test2() {
|
||||
use curve25519_dalek::constants::X25519_BASEPOINT;
|
||||
|
||||
let mut k: [u8; 32] = X25519_BASEPOINT.0;
|
||||
let mut u: [u8; 32] = X25519_BASEPOINT.0;
|
||||
let mut result: [u8; 32];
|
||||
|
||||
macro_rules! do_iterations {
|
||||
($n:expr) => {
|
||||
for _ in 0..$n {
|
||||
result = x25519(k, u);
|
||||
// OBVIOUS THING THAT I'M GOING TO NOTE ANYWAY BECAUSE I'VE
|
||||
// SEEN PEOPLE DO THIS WITH GOLANG'S STDLIB AND YOU SURE AS
|
||||
// HELL SHOULDN'T DO HORRIBLY STUPID THINGS LIKE THIS WITH
|
||||
// MY LIBRARY:
|
||||
//
|
||||
// NEVER EVER TREAT SCALARS AS POINTS AND/OR VICE VERSA.
|
||||
//
|
||||
// ↓↓ DON'T DO THIS ↓↓
|
||||
u = k.clone();
|
||||
k = result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// After one iteration:
|
||||
// 422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079
|
||||
// After 1,000 iterations:
|
||||
// 684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51
|
||||
// After 1,000,000 iterations:
|
||||
// 7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424
|
||||
|
||||
do_iterations!(1);
|
||||
assert_eq!(
|
||||
k,
|
||||
[
|
||||
0x42, 0x2c, 0x8e, 0x7a, 0x62, 0x27, 0xd7, 0xbc, 0xa1, 0x35, 0x0b, 0x3e, 0x2b, 0xb7,
|
||||
0x27, 0x9f, 0x78, 0x97, 0xb8, 0x7b, 0xb6, 0x85, 0x4b, 0x78, 0x3c, 0x60, 0xe8, 0x03,
|
||||
0x11, 0xae, 0x30, 0x79,
|
||||
]
|
||||
);
|
||||
do_iterations!(999);
|
||||
assert_eq!(
|
||||
k,
|
||||
[
|
||||
0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55, 0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f,
|
||||
0x4d, 0x3c, 0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87, 0x5f, 0x2e, 0xb9, 0x4d,
|
||||
0x99, 0x53, 0x2c, 0x51,
|
||||
]
|
||||
);
|
||||
do_iterations!(999_000);
|
||||
assert_eq!(
|
||||
k,
|
||||
[
|
||||
0x7c, 0x39, 0x11, 0xe0, 0xab, 0x25, 0x86, 0xfd, 0x86, 0x44, 0x97, 0x29, 0x7e, 0x57,
|
||||
0x5e, 0x6f, 0x3b, 0xc6, 0x01, 0xc0, 0x88, 0x3c, 0x30, 0xdf, 0x5f, 0x4d, 0xd2, 0xd2,
|
||||
0x4f, 0x66, 0x54, 0x24,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
mod rand_core {
|
||||
|
||||
use super::*;
|
||||
use ::rand_core::OsRng;
|
||||
|
||||
#[test]
|
||||
fn ephemeral_from_rng() {
|
||||
#[allow(deprecated)]
|
||||
EphemeralSecret::new(OsRng);
|
||||
EphemeralSecret::random_from_rng(OsRng);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "reusable_secrets")]
|
||||
fn reusable_from_rng() {
|
||||
#[allow(deprecated)]
|
||||
ReusableSecret::new(OsRng);
|
||||
ReusableSecret::random_from_rng(OsRng);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "static_secrets")]
|
||||
fn static_from_rng() {
|
||||
#[allow(deprecated)]
|
||||
StaticSecret::new(OsRng);
|
||||
StaticSecret::random_from_rng(OsRng);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "getrandom")]
|
||||
mod getrandom {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn ephemeral_random() {
|
||||
EphemeralSecret::random();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "reusable_secrets")]
|
||||
fn reusable_random() {
|
||||
ReusableSecret::random();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "static_secrets")]
|
||||
fn static_random() {
|
||||
StaticSecret::random();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue