Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

kmac: Towards an implementation

未关闭
#133 5 条评论 2 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
5/5
预计耗时
一周以上
新手友好度
32/100
Issue 类型
功能
描述清晰度
基本清楚
活跃度
停滞
技术栈
rust
领域
cryptography

调研方向

首先阅读 NIST SP 800-185,并比较现有的 hmac 和 sha3 crate,尤其是 digest::Mac、ExtendableOutput、KeyInit 以及 CSHAKE 类型。确定基于 keccak 或 sha3 的设计以及对 digest trait 的任何更改是否可以接受,然后使用链接的 NIST KMAC 示例和 Bouncy Castle 测试来定义覆盖范围。完成的标准是拥有经过审查的 KMAC128/KMAC256 API、实现和测试。

由索引模型根据 Issue 内容生成。

描述

I've given the implementation of KMAC within the RustCrypto ecosystem some thought. My ideas, reproduced below, are informed by the NIST SP 800-185 recommendation and the hmac and sha3 crates.

I'm willing to do any/all of the work described below. However, I'm not a cryptographer or security researcher, so all my work would have to be scrutinized tirelessly by the more qualified.

User experience

In keeping with the principle of least astonishment, I want to be able to use KMAC objects like other existing RustCrypto MAC objects:

use kmac::{Kmac128, Mac};
use hex_literal::hex;

let key = hex!("404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f");
let customization = b"My Tagged Application";
let mut mac = Kmac128::new_with(&key, &customization);
mac.update(hex!("00010203"));
let buf = [0u8;32];
let result = mac.finalize_into(&buf);
let result_bytes = result.into_bytes();
let expected = hex!("3b1fba963cd8b0b59e8c1a6d71888b7143651af8ba0a7070c0979e2811324aa5");
assert_eq!(result_bytes[..], expected[..]);

We should first consider the digest::Mac trait imported in this example. The automatic implementation of Mac is helpful for augmenting a type T (here, Kmac128) with such methods as new, update, finalize and verify, to name a few. This mechanism provides a consistent user experience with little extra development effort across different types of MAC.

This mechanism doesn't support KMAC because it requires inappropriate traits. For example, digest::KeyInit supports initialization from only a key, whereas KMAC must also permit a customization string. Moreover, KMAC is defined in terms of CSHAKE (an extendable-output function) and thus shouldn't implement digest::FixedOutput, a trait required for the automatic implementation of Mac. These limitations shape the implementation strategies I identify below.

Implementing KMAC
Using keccak

Prepare two core types of fixed security strength, Kmac128Core and Kmac256Core, that manage their own state and are implemented in terms of KECCAK[c] as described in Appendix B of NIST SP 800-185. The public API, similar to what we would expect if we were to import Mac, is implemented by hand. This is the cheaper approach but it violates the principle of least astonishment both internally (divergence of implementation strategy) and externally (users don't import a convenience trait). Moreover, it involves the duplication of private code in sha3.

Using sha3

Prepare a core generic type, KmacCore<D>, that wraps a hash function satisfying certain traits, e.g., ExtendableOutputCore. Implement the remaining traits as needed. Optionally, construct the Kmac128 and Kmac256 types, each a CoreWrapper<KmacCore<D>> where D is a sha3::CShake128 and sha3::CShake256, respectively.

Implement a convenience trait in digest that feels like Mac but requires a distinct set of methods. For example, this new trait should rely on digest::ExtendableOutput rather than FixedOutput. Thus, I'll call it MacXof in this post, but I note that this name doesn't capture all the key differences with Mac. In particular, MacXof must also support initialization with both a key and, optionally, a customization string. (The closest trait I can find that enables this behavior is crypto_common::KeyIvInit. However, the iv parameter is indicated for nonces and I'm unsure whether this is appropriate in this context.)

I've identified one concrete obstacle in relation to implementing traits on KmacCore. Consider the following code in hmac (edited for brevity):

impl<D> KeyInit for HmacCore<D>
where
    D: CoreProxy,
    D::Core: HashMarker + UpdateCore + FixedOutputCore + BufferKindUser<BufferKind = Eager> + Default + Clone,
    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
    // ...
    #[inline(always)]
    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
        let mut buf = get_der_key::<CoreWrapper<D::Core>>(key);
        // ...
        let mut digest = D::Core::default();
        digest.update_blocks(slice::from_ref(&buf));
        // ...
    }
    // ...
}

Here, the state can be initialized because the expectation is that D::Core implements Default. CSHAKE types in sha3 don't implement Default and we would need to fill this gap. However, instead of Default, it would be more appropriate to implement an initialization trait—an IvInit of sorts—so that the customization string passed to a Kmac128/Kmac256 constructor can be forwarded to the underlying CShake128/CShake256 constructor call.

In addition, the CSHAKE implementations in sha3 don't store their security strength. I don't see an easy way to prepare the expected algorithm names for KMAC (Kmac128 and Kmac256) without manipulating the CSHAKE type names directly, which I find undesirable.

Overall, this approach requires more development effort. It involves extending the digest API with one or more new traits, and implementing at least one trait on CSHAKE types in sha3. However, I'm in favor of this approach because it preserves both the user experience as well as the existing implementation style for MACs.

Testing

To test MAC implementations, RustCrypto serializes Project Wycheproof test vectors into binary blobs using the blobby crate. In turn, these are consumed by such macros as digest::new_mac_test. But there are no Wycheproof KMAC test vectors, nor does today's Wycheproof MAC schema support specification of the output length. So, we have no straightforward manner of leveraging the MAC test suite for KMAC.

I haven't found any official and public-facing KMAC test vectors. The NIST Cryptographic Algorithm Validation Program page currently provides only HMAC test vectors. There's a collection of KMAC test vectors that appears to be at a legitimate NIST domain (csrc.nist.gov); I'm inclined to use these as the basis for a handwritten test. The Legion of the Bouncy Castle uses these samples in their KMAC tests.


All this aside, my sincere thanks go to the RustCrypto contributors for your work over the years!

主要语言
Rust
星标
372
派生
54
PR 合并指标
30 天内没有已合并 PR

贡献指南

这个仓库没有索引到贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

RustCrypto/MACs 的其他 Issue

查看 RustCrypto/MACs 的全部 Issue

相似的 Issue

更多 Rust Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。