mirror of
https://github.com/saymrwulf/fips205-source.git
synced 2026-09-03 19:53:49 +00:00
fips205 prep
This commit is contained in:
parent
ddfabeb6ac
commit
b0213416c8
15 changed files with 562 additions and 357 deletions
113
.github/workflows/test.yml
vendored
Normal file
113
.github/workflows/test.yml
vendored
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
name: test
|
||||
|
||||
on: [ push ]
|
||||
|
||||
|
||||
env:
|
||||
CARGO_INCREMENTAL: 0
|
||||
RUSTFLAGS: "-Dwarnings"
|
||||
RUSTDOCFLAGS: "-Dwarnings"
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
rust:
|
||||
- 1.70.0 # MSRV
|
||||
- stable
|
||||
target:
|
||||
- thumbv7em-none-eabi
|
||||
- wasm32-unknown-unknown
|
||||
- s390x-unknown-linux-gnu
|
||||
- powerpc64-unknown-linux-gnu
|
||||
- riscv64gc-unknown-none-elf
|
||||
- x86_64-pc-windows-gnu
|
||||
- x86_64-apple-darwin
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
targets: ${{ matrix.target }}
|
||||
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features "slh_dsa_sha2_128s slh_dsa_shake_128s slh_dsa_sha2_128f slh_dsa_shake_128f slh_dsa_sha2_192s slh_dsa_shake_192s slh_dsa_sha2_192f slh_dsa_shake_192f slh_dsa_sha2_256s slh_dsa_shake_256s slh_dsa_sha2_256f slh_dsa_shake_256f"
|
||||
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
# 32-bit Linux
|
||||
- target: i686-unknown-linux-gnu
|
||||
rust: 1.70.0 # MSRV
|
||||
deps: sudo apt update && sudo apt install gcc-multilib
|
||||
- target: i686-unknown-linux-gnu
|
||||
rust: stable
|
||||
deps: sudo apt update && sudo apt install gcc-multilib
|
||||
|
||||
# 64-bit Linux
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
rust: 1.70.0 # MSRV
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
rust: stable
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
targets: ${{ matrix.target }}
|
||||
- run: ${{ matrix.deps }}
|
||||
- run: cargo check --target ${{ matrix.target }} --all-features
|
||||
- run: cargo test --release --target ${{ matrix.target }}
|
||||
|
||||
|
||||
cross:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
# ARM32
|
||||
- target: armv7-unknown-linux-gnueabihf
|
||||
rust: 1.70.0 # MSRV (cross)
|
||||
- target: armv7-unknown-linux-gnueabihf
|
||||
rust: stable
|
||||
# ARM64
|
||||
- target: aarch64-unknown-linux-gnu
|
||||
rust: 1.70.0 # MSRV (cross)
|
||||
- target: aarch64-unknown-linux-gnu
|
||||
rust: stable
|
||||
# PPC32
|
||||
- target: powerpc-unknown-linux-gnu
|
||||
rust: 1.70.0 # MSRV (cross)
|
||||
- target: powerpc-unknown-linux-gnu
|
||||
rust: stable
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: ${{ matrix.deps }}
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
targets: ${{ matrix.target }}
|
||||
- uses: RustCrypto/actions/cross-install@master
|
||||
- run: cross test --release --target ${{ matrix.target }} --all-features
|
||||
|
||||
|
||||
doc:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: RustCrypto/actions/cargo-cache@master
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: stable
|
||||
- run: cargo doc --all-features
|
||||
|
||||
clippy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Run Clippy
|
||||
run: cargo clippy --all-targets --all-features
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -1,3 +1,7 @@
|
|||
/target
|
||||
/Cargo.lock
|
||||
/.idea
|
||||
/.idea
|
||||
**/artifacts
|
||||
**/corpus
|
||||
/fuzz/.gitignore
|
||||
**/Cargo.lock
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ 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 (2023-10-15)
|
||||
## 0.1.1 (2024-02-14)
|
||||
|
||||
- Initial API release skeleton
|
||||
- Initial release
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||
license = "MIT OR Apache-2.0"
|
||||
description = "FIPS 205 (draft): Stateless Hash-Based Digital Signature Standard"
|
||||
repository = "https://github.com/integritychain/fips205"
|
||||
rust-version = "1.73"
|
||||
rust-version = "1.70"
|
||||
|
||||
|
||||
[dependencies]
|
||||
|
|
|
|||
85
README.md
Normal file
85
README.md
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# [IntegrityChain]: FIPS 205 Stateless Hash-Based Digital Signature Standard
|
||||
|
||||
[![crate][crate-image]][crate-link]
|
||||
[![Docs][docs-image]][docs-link]
|
||||
[![Build Status][build-image]][build-link]
|
||||
![Apache2/MIT licensed][license-image]
|
||||
![Rust Version][rustc-image]
|
||||
|
||||
[FIPS 205] (Initial Public Draft) Stateless Hash-Based Digital Signature Standard written in pure Rust for server,
|
||||
desktop, browser and embedded applications.
|
||||
|
||||
This crate implements the FIPS 205 **draft** standard in pure Rust with minimal and mainstream dependencies. All
|
||||
twelve (!!) security parameter sets are fully functional. The implementation does not require the standard library,
|
||||
e.g. `#[no_std]`, has no heap allocations, e.g. no `alloc` needed, and exposes the `RNG` so it is suitable for the
|
||||
full range of applications down to the bare-metal. The API is stabilized and the code is heavily biased towards safety
|
||||
and correctness; further performance optimizations will be implemented as the standard matures. This crate will
|
||||
quickly follow any changes to FIPS 205 as they become available.
|
||||
|
||||
See <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.205.ipd.pdf> for a full description of the target functionality.
|
||||
|
||||
The functionality is extremely simple to use, as demonstrated by the following example.
|
||||
|
||||
~~~rust
|
||||
use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets.
|
||||
use fips205::traits::{SerDes, Signer, Verifier};
|
||||
# use std::error::Error;
|
||||
#
|
||||
# fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
let msg_bytes = [0u8, 1, 2, 3, 4, 5, 6, 7];
|
||||
|
||||
// Generate key pair and signature
|
||||
let (pk1, sk) = slh_dsa_shake_128s::try_keygen_vt()?; // Generate both public and secret keys
|
||||
let sig_bytes = sk.try_sign_ct(&msg_bytes, true)?; // Use the secret key to generate a msg signature
|
||||
|
||||
// Serialize the public key, and send with message and signature bytes
|
||||
let (pk_send, msg_send, sig_send) = (pk1.into_bytes(), msg_bytes, sig_bytes);
|
||||
let (pk_recv, msg_recv, sig_recv) = (pk_send, msg_send, sig_send);
|
||||
|
||||
// Deserialize the public key, then use it to verify the msg signature
|
||||
let pk2 = slh_dsa_shake_128s::PublicKey::try_from_bytes(&pk_recv)?;
|
||||
let v = pk2.try_verify_vt(&msg_recv, &sig_recv)?;
|
||||
assert!(v);
|
||||
# Ok(())
|
||||
# }
|
||||
~~~
|
||||
|
||||
The Rust [Documentation][docs-link] lives under each **Module** corresponding to the desired
|
||||
[security parameter](#modules) below.
|
||||
|
||||
## Notes
|
||||
|
||||
* This crate is fully functional and corresponds to the first initial public draft of FIPS 205.
|
||||
* Constant-time assurances target the source-code level only, and are a work in progress.
|
||||
* Note that FIPS 205 places specific requirements on randomness per section 3.1, hence the exposed `RNG`.
|
||||
* Requires Rust **1.70** or higher. The minimum supported Rust version may be changed in the future, but
|
||||
it will be done with a minor version bump.
|
||||
* All on-by-default features of this library are covered by SemVer.
|
||||
* This software is experimental and still under active development -- USE AT YOUR OWN RISK!
|
||||
|
||||
## License
|
||||
|
||||
Contents are licensed under either the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
or [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.
|
||||
|
||||
[//]: # (badges)
|
||||
|
||||
[crate-image]: https://buildstats.info/crate/fips205
|
||||
[crate-link]: https://crates.io/crates/fips205
|
||||
[docs-image]: https://docs.rs/fips205/badge.svg
|
||||
[docs-link]: https://docs.rs/fips205/
|
||||
[build-image]: https://github.com/integritychain/fips205/workflows/test/badge.svg
|
||||
[build-link]: https://github.com/integritychain/fips205/actions?query=workflow%3Atest
|
||||
[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg
|
||||
[rustc-image]: https://img.shields.io/badge/rustc-1.70+-blue.svg
|
||||
|
||||
[//]: # (general links)
|
||||
|
||||
[IntegrityChain]: https://github.com/integritychain/
|
||||
[FIPS 205]: https://csrc.nist.gov/pubs/fips/205/ipd
|
||||
17
SECURITY.md
Normal file
17
SECURITY.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Security updates are applied only to the most recent release.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you have discovered a security vulnerability in this project, please report
|
||||
it privately. **Do not disclose it as a public issue.** This gives us time to
|
||||
work with you to fix the issue before public exposure, reducing the chance that
|
||||
the exploit will be used before a patch is released.
|
||||
|
||||
Please disclose it at [security advisory](https://github.com/integritychain/fips205/security/advisories/new).
|
||||
|
||||
This project is maintained by a team of volunteers on a reasonable-effort basis.
|
||||
As such, please give us at least 90 days to work on a fix before public exposure.
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
use generic_array::{ArrayLength, GenericArray};
|
||||
use crate::types::Adrs;
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
|
||||
|
||||
// Holds hasher function references; constructed by each wrapper
|
||||
|
|
@ -26,14 +26,14 @@ pub(crate) struct Hashers<K: ArrayLength, LEN: ArrayLength, M: ArrayLength, N: A
|
|||
feature = "slh_dsa_shake_256s"
|
||||
))]
|
||||
pub(crate) mod shake {
|
||||
use crate::types::Adrs;
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use sha3::digest::{ExtendableOutput, Update, XofReader};
|
||||
use sha3::Shake256;
|
||||
use crate::types::Adrs;
|
||||
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub fn shake256(input: &[&[u8]], out: &mut [u8]) {
|
||||
fn shake256(input: &[&[u8]], out: &mut [u8]) {
|
||||
let mut hasher = Shake256::default();
|
||||
input.iter().for_each(|item| hasher.update(item));
|
||||
let mut reader = hasher.finalize_xof();
|
||||
|
|
@ -103,13 +103,13 @@ pub(crate) mod shake {
|
|||
|
||||
#[cfg(any(feature = "slh_dsa_sha2_128f", feature = "slh_dsa_sha2_128s"))]
|
||||
pub(crate) mod sha2_cat_1 {
|
||||
use crate::types::Adrs;
|
||||
use core::cmp::min;
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use sha2::{Digest, Sha256};
|
||||
use crate::types::Adrs;
|
||||
|
||||
|
||||
pub fn sha2_256(input: &[&[u8]], out: &mut [u8]) {
|
||||
fn sha2_256(input: &[&[u8]], out: &mut [u8]) {
|
||||
debug_assert!(out.len() <= 32);
|
||||
let mut hasher = Sha256::new();
|
||||
input.iter().for_each(|item| hasher.update(item));
|
||||
|
|
@ -157,7 +157,7 @@ pub(crate) mod sha2_cat_1 {
|
|||
}
|
||||
|
||||
|
||||
pub fn hmac_sha_256(key: &[u8], a0: &[u8], b1: &[u8]) -> [u8; 32] {
|
||||
fn hmac_sha_256(key: &[u8], a0: &[u8], b1: &[u8]) -> [u8; 32] {
|
||||
let k2 = key;
|
||||
let mut padded = [0x36; 64];
|
||||
for (p, &k) in padded.iter_mut().zip(k2.iter()) {
|
||||
|
|
@ -248,13 +248,13 @@ pub(crate) mod sha2_cat_1 {
|
|||
feature = "slh_dsa_sha2_256s"
|
||||
))]
|
||||
pub(crate) mod sha2_cat_3_5 {
|
||||
use crate::types::Adrs;
|
||||
use core::cmp::min;
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use sha2::{Digest, Sha256, Sha512};
|
||||
use crate::types::Adrs;
|
||||
|
||||
|
||||
pub fn sha2_256(input: &[&[u8]], out: &mut [u8]) {
|
||||
fn sha2_256(input: &[&[u8]], out: &mut [u8]) {
|
||||
debug_assert!(out.len() <= 32);
|
||||
let mut hasher = Sha256::new();
|
||||
input.iter().for_each(|item| hasher.update(item));
|
||||
|
|
@ -263,7 +263,7 @@ pub(crate) mod sha2_cat_3_5 {
|
|||
}
|
||||
|
||||
|
||||
pub fn sha2_512(input: &[&[u8]], out: &mut [u8]) {
|
||||
fn sha2_512(input: &[&[u8]], out: &mut [u8]) {
|
||||
debug_assert!(out.len() <= 64);
|
||||
let mut hasher = Sha512::new();
|
||||
input.iter().for_each(|item| hasher.update(item));
|
||||
|
|
@ -311,7 +311,7 @@ pub(crate) mod sha2_cat_3_5 {
|
|||
}
|
||||
|
||||
|
||||
pub fn hmac_sha_512(key: &[u8], a0: &[u8], b1: &[u8]) -> [u8; 64] {
|
||||
fn hmac_sha_512(key: &[u8], a0: &[u8], b1: &[u8]) -> [u8; 64] {
|
||||
let k2 = key;
|
||||
let mut padded = [0x36; 128];
|
||||
for (p, &k) in padded.iter_mut().zip(k2.iter()) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use generic_array::ArrayLength;
|
||||
use crate::types::{Adrs, SlhDsaSig};
|
||||
use generic_array::ArrayLength;
|
||||
|
||||
|
||||
/// Algorithm 1: `toInt(X, n)` on page 14.
|
||||
|
|
@ -120,7 +120,7 @@ impl<
|
|||
N: ArrayLength,
|
||||
> SlhDsaSig<A, D, HP, K, LEN, N>
|
||||
{
|
||||
pub fn deserialize<const SIG_LEN: usize>(self) -> [u8; SIG_LEN] {
|
||||
pub(crate) fn deserialize<const SIG_LEN: usize>(self) -> [u8; SIG_LEN] {
|
||||
let mut out = [0u8; SIG_LEN];
|
||||
debug_assert_eq!(
|
||||
out.len(),
|
||||
|
|
@ -156,8 +156,7 @@ impl<
|
|||
out
|
||||
}
|
||||
|
||||
|
||||
pub fn serialize(bytes: &[u8]) -> Self {
|
||||
pub(crate) fn serialize(bytes: &[u8]) -> Self {
|
||||
debug_assert_eq!(
|
||||
bytes.len(),
|
||||
N::to_usize() + // randomness
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use generic_array::{ArrayLength, GenericArray};
|
||||
use crate::hashers::Hashers;
|
||||
use crate::types::{Adrs, HtSig};
|
||||
use crate::xmss;
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
|
||||
|
||||
/// Algorithm 11: `ht_sign(M, SK.seed, PK.seed, idx_tree, idx_leaf)` on page 27.
|
||||
|
|
|
|||
|
|
@ -2,18 +2,23 @@
|
|||
#![deny(clippy::pedantic)]
|
||||
#![deny(warnings)]
|
||||
//#![deny(missing_docs)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
|
||||
/// Implements FIPS 205 draft Stateless Hash-Based Digital Signature Standard.
|
||||
/// See <https://csrc.nist.gov/pubs/fips/205/ipd>
|
||||
|
||||
/// TKTK crate doc
|
||||
// TODO
|
||||
// 1. General clean-up
|
||||
// 7. Doc, of course!
|
||||
|
||||
mod fors;
|
||||
mod hashers;
|
||||
mod helpers;
|
||||
mod hypertree;
|
||||
mod slh;
|
||||
mod test;
|
||||
mod traits;
|
||||
pub mod traits;
|
||||
mod types;
|
||||
mod wots;
|
||||
mod xmss;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use generic_array::{ArrayLength, GenericArray};
|
||||
use rand_core::CryptoRngCore;
|
||||
use crate::hashers::Hashers;
|
||||
use crate::types::FORS_TREE;
|
||||
use crate::types::{Adrs, SlhDsaSig, SlhPrivateKey, SlhPublicKey};
|
||||
use crate::{fors, helpers, hypertree, xmss};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use rand_core::CryptoRngCore;
|
||||
|
||||
|
||||
/// Algorithm 17: `slh_keygen()` on page 34.
|
||||
|
|
|
|||
332
src/test.rs
332
src/test.rs
File diff suppressed because one or more lines are too long
|
|
@ -1,7 +1,7 @@
|
|||
use generic_array::{ArrayLength, GenericArray};
|
||||
use crate::hashers::Hashers;
|
||||
use crate::helpers;
|
||||
use crate::types::{Adrs, WotsPk, WotsSig, WOTS_PK, WOTS_PRF};
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
|
||||
|
||||
/// Algorithm 4: `chain(X, i, s, PK.seed, ADRS)` on page 17.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use generic_array::{ArrayLength, GenericArray};
|
||||
use crate::hashers::Hashers;
|
||||
use crate::types::{Adrs, XmssSig, TREE, WOTS_HASH};
|
||||
use crate::wots;
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
|
||||
|
||||
/// Algorithm 8: `xmss_node(SK.seed, i, z, PK.seed, ADRS)` on page 22.
|
||||
|
|
|
|||
314
tests/py_vectors.rs
Normal file
314
tests/py_vectors.rs
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue