Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Proposal: a multi-buffer (multi-message) hashing trait for parallel independent digests

オープン
#2,478 コメント 5 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
32/100
issue の種類
機能追加
明瞭さ
おおむね明確
活発さ
静か
技術スタック
rust
領域
cryptography

調査の方向性

まず digest/src/block_api.rs を読み、crypto-common の ParBlocks に関する規約を、issue で参照されている cipher の実装および sha2 のバックエンドディスパッチと比較してください。方向性を提案する前に、提案されている 3 つの API 形状と未解決の質問を確認してください。完了の条件は、maintainer が crate、API、lane の表現、MVP の範囲について合意することです。現時点ではまだどの design も選択されていません。

索引モデルが issue の本文から書いたものです。

説明

The core primitive

We'd like to add a first-class abstraction for hashing N independent messages at once, so an implementation can place one message per SIMD lane and run the compression function across all lanes simultaneously:

Given N independent byte messages, produce their N digests in a single call.

This is the classic "multi-buffer" SHA construction (Gueron–Krasnov, Intel isa-l sha512_mb/sha256_mb). It exploits the fact that the round function has no cross-message dependency, even though it's fully serial within one message — so it's a different axis of parallelism from everything RustCrypto has today.

Why it's missing today (prior art)

As far as we can tell this capability doesn't exist anywhere in RustCrypto, and the existing parallelism is all a different axis:

  • ParBlocksSizeUser / ParBlocks (crypto-common, used by cipher) is the closest structural match — "process LANES units at once + scalar tail," via encrypt_par_blocks/encrypt_tail_blocks over inout::InOutBuf. But it means multiple blocks of one stream, not independent messages.
  • BLAKE2bp/sp, BLAKE3 tree mode, the sha2 AVX2 backend (#327) are all single-message internal SIMD.
  • The hashing core API (digest/src/block_api.rs) has no par-blocks concept; update_blocks is serial over one message.

So this would be a genuinely new capability on the hashing side, ideally borrowing the cipher-side conventions.

Motivating use case

Parallel Merkle-tree leaf hashing: the leaves are independent, equal-length messages — the ideal multi-buffer workload. (Our concrete driver is a parallel, order-independent launch-measurement for AMD SEV-SNP confidential VMs, but the primitive is general: tree/dedup/storage/packet hashing all want it.) On AMD in particular, SHA-384/512 has no hardware engine, so multi-buffer is the only way to use the SIMD datapath — and it's substantial on the Zen 5 / Turin native 512-bit path.

Design options

A — High-level one-shot trait on top of Digest, runtime dispatch internal (sha2-style):

pub trait MultiDigest: Digest {
    fn digest_many(msgs: &[&[u8]], out: &mut [Output<Self>]); // impl detects avx2/avx512, chunks internally
}

B — Backend + driver split mirroring cipher's ParBlocks (compile-time width):

pub trait MultiDigestBackend: OutputSizeUser {
    type Lanes: ArraySize;                       // typenum, like ParBlocksSize
    fn digest_lanes(msgs: &Array<&[u8], Lanes>, out: &mut Array<Output<Self>, Lanes>);
    fn digest_tail(..); // len < Lanes
}
// + a driver that splits into Lanes-chunks then a scalar tail

C — Streaming multi-lane context (isa-l manager-style): N independent incremental states with submit/flush, handling unequal-length messages that finish at different times. Most general, closest to isa-l, most complex.

A: one-shot driver B: backend + driver C: streaming manager
Width representation internal (runtime) type Lanes: ArraySize internal
ISA selection runtime cpufeatures (like sha2) compile-time / backend types (like cipher) runtime
Unequal lengths precondition: equal (scalar tail) equal per chunk fully general
Streaming/incremental no (one-shot) no yes
Complexity to land low medium high
Fidelity to existing precedent sha2 dispatch cipher ParBlocks isa-l only

Open questions for @tarcieri

  1. Does a multi-message hashing trait belong in digest (or crypto-common, or a new crate), or would you prefer inherent batch methods on individual hashes rather than a shared trait?
  2. Width as a typenum associated type (type Lanes: ArraySize, matching ParBlocksSize) vs kept internal with runtime cpufeatures dispatch (matching how sha2 selects backends)? These two precedents point in different directions here.
  3. Is a one-shot, equal-length primitive an acceptable MVP, or do you want the general (unequal-length / streaming) shape from the start?
  4. I/O convention: caller-provided output slice (à la inout/InOutBuf), and should inputs reuse InOutBuf or just &[&[u8]]?
  5. Naming: MultiDigest + Lanes (deliberately avoiding Par*, which already means intra-message)?

Happy to prototype whichever direction you prefer — we have a multi-buffer SHA-512/384 (AVX2 4-lane, AVX-512 8-lane) ready to shape to your guidance, with all SHA-2 variants to follow.

主要言語
Rust
スター
760
フォーク
258
PR マージ指標
30日以内にマージされた PR はありません

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

RustCrypto/traits のほかの issue

RustCrypto/traits の issue をすべて見る

似ている issue

Rust の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。