Repository navigation
Add ANSI-X9.63-KDF #102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Add ANSI-X9.63-KDF #102
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
dca8f8b
Add ANSI-X9.63-KDF support: add ansi-x963-kdf crate
nemynm 87acb51
Add ANSI-X9.63-KDF support: add ansi-x963-kdf information
nemynm cf0d27a
Add ANSI-X9.63-KDF support: add implementation and tests
nemynm 33c8994
Add ANSI-X9.63-KDF support: adjust variable name to shared_info to ma…
nemynm 0a9087e
Add ANSI-X9.63-KDF support: use alloc_zeroed for input overflow test …
nemynm f386294
Add ANSI-X9.63-KDF support: use Digest::update()
nemynm 7053d87
Add ANSI-X9.63-KDF support: add tests vectors origin
nemynm bdd842b
Add ANSI-X9.63-KDF support: add test assertion
nemynm 8322257
Add ANSI-X9.63-KDF support: use u64 for overflow errors checks
nemynm c1e8153
Add ANSI-X9.63-KDF support: adjust variable name to shared_info
nemynm 60863db
Add ANSI-X9.63-KDF support: switch to doc_auto_cfg
nemynm 6610e14
Add ANSI-X9.63-KDF support: set MSRV to 1.81
nemynm d9ee6e7
Add ANSI-X9.63-KDF support: switch to core::error::Error
nemynm ab920bf
Add ANSI-X9.63-KDF support: clippy lint
nemynm 6facd96
Add ANSI-X9.63-KDF support: add CI job
nemynm 5052040
Add ANSI-X9.63-KDF support: update toolchain to 1.81 for clippy
nemynm 400e73d
Add ANSI-X9.63-KDF support: adjust comments on hashmaxlen and remove …
nemynm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| name: ansi-x963-kdf | ||
|
|
||
| on: | ||
| pull_request: | ||
| paths: | ||
| - "ansi-x963-kdf/**" | ||
| - "Cargo.*" | ||
| push: | ||
| branches: master | ||
|
|
||
| defaults: | ||
| run: | ||
| working-directory: ansi-x963-kdf | ||
|
|
||
| env: | ||
| CARGO_INCREMENTAL: 0 | ||
| RUSTFLAGS: "-Dwarnings" | ||
|
|
||
| jobs: | ||
| build: | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| rust: | ||
| - 1.81.0 # MSRV | ||
| - stable | ||
| target: | ||
| - thumbv7em-none-eabi | ||
| - wasm32-unknown-unknown | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: dtolnay/rust-toolchain@master | ||
| with: | ||
| toolchain: ${{ matrix.rust }} | ||
| targets: ${{ matrix.target }} | ||
| - run: cargo build --no-default-features --target ${{ matrix.target }} | ||
|
|
||
| test: | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| rust: | ||
| - 1.81.0 # MSRV | ||
| - stable | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: dtolnay/rust-toolchain@master | ||
| with: | ||
| toolchain: ${{ matrix.rust }} | ||
| - run: cargo check --all-features | ||
| - run: cargo test --no-default-features | ||
| - run: cargo test | ||
| - run: cargo test --all-features |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,7 @@ | |
| resolver = "2" | ||
| members = [ | ||
| "hkdf", | ||
| "concat-kdf", | ||
| "concat-kdf", "ansi-x963-kdf", | ||
| ] | ||
|
|
||
| [profile.dev] | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # Changelog | ||
| All notable changes to this project will be documented in this file. | ||
|
|
||
| The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | ||
| and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
|
|
||
| ## 0.1.0 (2024-04-10) | ||
| - Initial release |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| [package] | ||
| name = "ansi-x963-kdf" | ||
| version = "0.1.0" | ||
| description = "ANSI X9.63 Key Derivation Function (ANSI-X9.63-KDF)" | ||
| authors = ["RustCrypto Developers"] | ||
| license = "MIT OR Apache-2.0" | ||
| readme = "README.md" | ||
| edition = "2021" | ||
| documentation = "https://docs.rs/ansi-x963-kdf" | ||
| repository = "https://github.com/RustCrypto/KDFs" | ||
| keywords = ["crypto", "ansi-x963-kdf", "KDF", "SEC1"] | ||
| categories = ["cryptography", "no-std"] | ||
| rust-version = "1.81" | ||
|
|
||
| [dependencies] | ||
| digest = "=0.11.0-pre.9" | ||
|
|
||
| [dev-dependencies] | ||
| hex-literal = "0.4" | ||
| sha2 = { version = "=0.11.0-pre.4", default-features = false } | ||
|
|
||
| [features] | ||
| std = [] | ||
|
|
||
| [package.metadata.docs.rs] | ||
| all-features = true | ||
| rustdoc-args = ["--cfg", "docsrs"] | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| # RustCrypto: ANSI X9.63 Key Derivation Function (ANSI-X9.63-KDF) | ||
|
|
||
| [![crate][crate-image]][crate-link] | ||
| [![Docs][docs-image]][docs-link] | ||
| ![Apache2/MIT licensed][license-image] | ||
| ![Rust Version][rustc-image] | ||
| [![Project Chat][chat-image]][chat-link] | ||
| [![Build Status][build-image]][build-link] | ||
|
|
||
| Pure Rust implementation of the ANSI X9.63 Key Derivation Function (ANSI-X9.63-KDF) generic over hash function. | ||
| This function is described in the section 3.6.1 of [SEC 1: Elliptic Curve Cryptography](http://www.secg.org/sec1-v2.pdf). | ||
|
|
||
| # Usage | ||
|
|
||
| The most common way to use ANSI-X9.63-KDF is as follows: you generate a shared secret with other party (e.g. via Diffie-Hellman algorithm) | ||
| and use key derivation function to derive a shared key. | ||
|
|
||
| ```rust | ||
| let mut key = [0u8; 32]; | ||
| ansi_x963_kdf::derive_key_into::<sha2::Sha256>(b"shared-secret", b"other-info", &mut key).unwrap(); | ||
| ``` | ||
|
|
||
| ## Minimum Supported Rust Version | ||
|
|
||
| Rust **1.72** or higher. | ||
|
|
||
| Minimum supported Rust version can be changed in the future, but it will be | ||
| done with a minor version bump. | ||
|
|
||
| ## SemVer Policy | ||
|
|
||
| - All on-by-default features of this library are covered by SemVer | ||
| - MSRV is considered exempt from SemVer as noted above | ||
|
|
||
| ## License | ||
|
|
||
| Licensed under either of: | ||
|
|
||
| * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | ||
| * [MIT license](http://opensource.org/licenses/MIT) | ||
|
|
||
| at your option. | ||
|
|
||
| ### Contribution | ||
|
|
||
| Unless you explicitly state otherwise, any contribution intentionally submitted | ||
| for inclusion in the work by you, as defined in the Apache-2.0 license, shall be | ||
| dual licensed as above, without any additional terms or conditions. | ||
|
|
||
| [crate-image]: https://img.shields.io/crates/v/ansi-x963-kdf.svg | ||
| [crate-link]: https://crates.io/crates/ansi-x963-kdf | ||
| [docs-image]: https://docs.rs/ansi-x963-kdf/badge.svg | ||
| [docs-link]: https://docs.rs/ansi-x963-kdf/ | ||
| [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg | ||
| [rustc-image]: https://img.shields.io/badge/rustc-1.72+-blue.svg | ||
| [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg | ||
| [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260043-KDFs | ||
| [build-image]: https://github.com/RustCrypto/KDFs/workflows/ansi-x963-kdf/badge.svg?branch=master&event=push | ||
| [build-link]: https://github.com/RustCrypto/KDFs/actions?query=workflow:ansi-x963-kdf |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| //! An implementation of ANSI-X9.63 KDF Key Derivation Function. | ||
| //! | ||
| //! This function is described in the section 3.6.1 of [SEC 1: Elliptic Curve Cryptography][1]. | ||
| //! | ||
| //! # Usage | ||
| //! | ||
| //! The most common way to use ANSI-X9.63 KDF is as follows: you generate a shared secret | ||
| //! with other party (e.g. via Diffie-Hellman algorithm) and use key derivation function | ||
| //! to derive a shared key. | ||
| //! | ||
| //! ```rust | ||
| //! let mut key = [0u8; 32]; | ||
| //! ansi_x963_kdf::derive_key_into::<sha2::Sha256>(b"shared-secret", b"other-info", &mut key).unwrap(); | ||
| //! ``` | ||
| //! | ||
| //! [1]: https://www.secg.org/sec1-v2.pdf | ||
|
|
||
| #![no_std] | ||
| #![cfg_attr(docsrs, feature(doc_auto_cfg))] | ||
|
|
||
| use core::fmt; | ||
| use digest::{array::typenum::Unsigned, Digest, FixedOutputReset}; | ||
|
|
||
| #[cfg(feature = "std")] | ||
| extern crate std; | ||
|
|
||
| /// ANSI-X9.63 KDF errors. | ||
| #[derive(Clone, Copy, Debug, PartialEq)] | ||
| pub enum Error { | ||
| /// The length of the secret is zero. | ||
| NoSecret, | ||
| /// The length of the output is zero. | ||
| NoOutput, | ||
| /// The length of the input is too big | ||
| InputOverflow, | ||
| /// The length of the output is too big. | ||
| CounterOverflow, | ||
| } | ||
|
|
||
| impl fmt::Display for Error { | ||
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { | ||
| f.write_str(match self { | ||
| Error::NoSecret => "Buffer for secret has zero length.", | ||
| Error::NoOutput => "Buffer for key has zero length.", | ||
| Error::InputOverflow => "Input length is to big.", | ||
| Error::CounterOverflow => "Requested key length is to big.", | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| impl ::core::error::Error for Error {} | ||
|
|
||
| /// Derives `key` in-place from `secret` and `shared_info`. | ||
| /// ```rust | ||
| /// use hex_literal::hex; | ||
| /// let mut key = [0u8; 42]; | ||
| /// ansi_x963_kdf::derive_key_into::<sha2::Sha256>(b"top-secret", b"info", &mut key).unwrap(); | ||
| /// assert_eq!(key, hex!("85397c03b3894cdc12e7e042698d040f449dbff97a86d0a4dd2d0a4409b8d969e01e57091cf170dfd977")); | ||
| /// ``` | ||
| pub fn derive_key_into<D>(secret: &[u8], shared_info: &[u8], key: &mut [u8]) -> Result<(), Error> | ||
| where | ||
| D: Digest + FixedOutputReset, | ||
| { | ||
| if secret.is_empty() { | ||
| return Err(Error::NoSecret); | ||
| } | ||
|
|
||
| if key.is_empty() { | ||
| return Err(Error::NoOutput); | ||
| } | ||
|
|
||
| // 1. Check that |Z| + |SharedInfo| + 4 < hashmaxlen | ||
| // where "hashmaxlen denote the maximum length in octets of messages that can be hashed using Hash". | ||
| // N.B.: `D::OutputSize::U64 * (u32::MAX as u64)`` is currently used as an approximation of hashmaxlen. | ||
| if secret.len() as u64 + shared_info.len() as u64 + 4 >= D::OutputSize::U64 * (u32::MAX as u64) | ||
| { | ||
| return Err(Error::InputOverflow); | ||
| } | ||
|
|
||
| // 2. Check that keydatalen < hashlen × (2^32 − 1) | ||
| if key.len() as u64 >= D::OutputSize::U64 * (u32::MAX as u64) { | ||
| return Err(Error::CounterOverflow); | ||
| } | ||
|
|
||
| let mut digest = D::new(); | ||
|
|
||
| // 3. Initiate a 4 octet, big-endian octet string Counter as 00000001 | ||
| let mut counter: u32 = 1; | ||
|
|
||
| // 4. For i = 1 to keydatalen/hashlen, | ||
| for chunk in key.chunks_mut(D::OutputSize::USIZE) { | ||
| // 4.1 Compute Ki = Hash(Z ‖ Counter ‖ [SharedInfo]) using the selected hash function | ||
| Digest::update(&mut digest, secret); | ||
| Digest::update(&mut digest, counter.to_be_bytes()); | ||
| Digest::update(&mut digest, shared_info); | ||
| chunk.copy_from_slice(&digest.finalize_reset()[..chunk.len()]); | ||
| // 4.2. Increment Counter | ||
| counter += 1; | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| /// Derives and returns `length` bytes key from `secret` and `shared_info`. | ||
| /// ```rust | ||
| /// use hex_literal::hex; | ||
| /// let key = ansi_x963_kdf::derive_key::<sha2::Sha256>(b"top-secret", b"info", 42).unwrap(); | ||
| /// assert_eq!(key, hex!("85397c03b3894cdc12e7e042698d040f449dbff97a86d0a4dd2d0a4409b8d969e01e57091cf170dfd977")); | ||
| /// ``` | ||
| #[cfg(feature = "std")] | ||
| #[cfg_attr(docsrs, doc(cfg(feature = "std")))] | ||
| pub fn derive_key<D>( | ||
| secret: &[u8], | ||
| shared_info: &[u8], | ||
| length: usize, | ||
| ) -> Result<std::vec::Vec<u8>, Error> | ||
| where | ||
| D: Digest + FixedOutputReset, | ||
| { | ||
| let mut key = std::vec![0u8; length]; | ||
| derive_key_into::<D>(secret, shared_info, &mut key)?; | ||
| Ok(key) | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.