Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Rust

on:
push:
branches: ["main"]
branches: ["master"]
pull_request:
branches: ["main"]
branches: ["master"]

env:
CARGO_TERM_COLOR: always
Expand Down Expand Up @@ -46,6 +46,22 @@ jobs:
- name: Check
run: cargo check --all-features

ensure_no_std:
name: Ensure no_std
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Install Rust Toolchain (nightly)
uses: dtolnay/rust-toolchain@nightly
with:
targets: thumbv6m-none-eabi

- name: Build (no_std)
run: cargo build --no-default-features --target thumbv6m-none-eabi
shell: bash

coverage:
name: Coverage
runs-on: ubuntu-latest
Expand Down Expand Up @@ -84,4 +100,4 @@ jobs:
run: cargo install cargo-audit

- name: Run cargo audit
run: cargo audit
run: cargo audit
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@ All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.0] - 2026-08-13

### Changed

- Upgraded the digest stack from digest 0.10 to digest 0.11. This is an internal upgrade with no public API change. The `DynDigest` trait API is the same in both versions. `multi-hash` does not re-export any digest traits in its public API; the public surface (`Multihash`, `Builder`, `EncodedMultihash`, `Error`, `AlgorithmId`, `HashDigest`, `HASH_CODECS`, `SAFE_HASH_CODECS`) is unchanged.
- `sha2` upgraded from `0.10` to `0.11`.
- `sha3` upgraded from `0.10` to `0.12`.
- `blake2` upgraded from `0.10` to `0.11.0-rc.6`.
- `blake3` upgraded from `1.5.1` to `1.8`.
- `md-5` upgraded from `0.10` to `0.11`.
- `ripemd` upgraded from `0.1.3` to `0.2`.
- `sha1` upgraded from `0.10` to `0.11`.
- `digest` upgraded from `0.10` to `0.11`.
- Fixed the `Blake3DynDigest` impl to use `blake3::Hasher::finalize(&self.0)` (fully-qualified call) instead of `self.0.finalize()`, because the `traits-preview` feature makes `blake3::Hasher` implement the `Digest` trait from `digest 0.11`, and the `Digest::finalize()` method shadows the inherent `blake3::Hasher::finalize()` method when `Digest` is in scope. The qualified call returns `blake3::Hash` (which has `as_bytes()`), while the trait method returns `Array` (which does not).

### Notes

- This upgrade unblocks `lamport_signature_plus` support in `multi-key` (Phases 8-9 of the crate extraction plan). `lamport_signature_plus` requires digest 0.11 hash crates (sha3 0.12, sha2 0.11, blake2 0.11, shake 0.1, blake3 1.8).
- `blake2 0.11.0-rc.6` is a release candidate. When the stable `blake2 0.11` is published, the version requirement can be loosened to `"0.11"`.
- `blake3 1.8` still bundles its own copy of `digest 0.11` internally (via the `traits-preview` feature). The `multiple_crate_versions` clippy allow is retained until blake3 publishes a release that depends on the RustCrypto `digest 0.11` crate directly.

## [1.0.7] - 2026-07-29

### Added
Expand Down Expand Up @@ -99,6 +120,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Added a test suite for edge cases, integration, proptests, and security.
- Initial published release on crates.io as `multi-hash`.

[1.1.0]: https://github.com/cryptidtech/multi-hash/compare/v1.0.7...v1.1.0
[1.0.7]: https://github.com/cryptidtech/multi-hash/compare/v1.0.6...v1.0.7
[1.0.6]: https://github.com/cryptidtech/multi-hash/compare/v1.0.5...v1.0.6
[1.0.5]: https://github.com/cryptidtech/multi-hash/compare/v1.0.4...v1.0.5
Expand Down
29 changes: 15 additions & 14 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "multi-hash"
version = "1.0.7"
version = "1.1.0"
edition = "2024"
rust-version = "1.85"
authors = ["Dave Grantham <dwg@linuxprogrammer.org>"]
Expand All @@ -15,39 +15,40 @@ categories = ["cryptography", "encoding"]
default = ["serde"]

[dependencies]
blake2 = "0.10"
blake3 = { version = "1.5.1", features = ["traits-preview", "zeroize"] }
blake2 = "0.11.0-rc.6"
blake3 = { version = "1.8", features = ["traits-preview", "zeroize"] }
multi-base = "1.0"
multi-codec = "1.1"
multi-codec = "1.2"
multi-trait = "1.0"
multi-util = "1.1"
digest = "0.10"
digest = "0.11"
hex = "0.4"
md-5 = "0.10"
ripemd = "0.1.3"
md-5 = "0.11"
ripemd = "0.2"
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"], optional = true }
sha1 = "0.10"
sha2 = "0.10"
sha3 = "0.10"
sha1 = "0.11"
sha2 = "0.11"
sha3 = "0.12"
subtle = "2"
thiserror = { version = "2.0" }
typenum = "1.17"
typenum = "1.20"
unsigned-varint = { version = "0.8", features = ["std"] }

[dev-dependencies]
ciborium = "0.2"
criterion = { version = "0.8", features = ["html_reports"] }
hex = "0.4"
proptest = "1.4"
proptest = "1.11"
serde_json = "1.0"
serde_test = "1.0"

[lints.clippy]
pedantic = { level = "warn", priority = -1 }
nursery = { level = "warn", priority = -1 }
cargo = { level = "warn", priority = -1 }
# blake3 pulls in digest 0.11 while the other RustCrypto crates use 0.10.
# This will resolve when the rest of the ecosystem upgrades.
# blake3 1.8 still pulls in its own digest dependency; allow the version
# duplication until blake3 publishes a release that uses digest 0.11
# directly from the RustCrypto ecosystem.
multiple_crate_versions = { level = "allow", priority = 1 }

[lints.rust]
Expand Down
6 changes: 4 additions & 2 deletions src/mh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,17 @@ impl DynDigest for Blake3DynDigest {
if buf.len() != self.output_size() {
return Err(InvalidBufferSize);
}
buf.copy_from_slice(self.0.finalize().as_bytes());
let hash = blake3::Hasher::finalize(&self.0);
buf.copy_from_slice(hash.as_bytes());
Ok(())
}

fn finalize_into_reset(&mut self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> {
if buf.len() != self.output_size() {
return Err(InvalidBufferSize);
}
buf.copy_from_slice(self.0.finalize().as_bytes());
let hash = blake3::Hasher::finalize(&self.0);
buf.copy_from_slice(hash.as_bytes());
self.reset();
Ok(())
}
Expand Down