digest-0.11.3/.cargo_vcs_info.json0000644000000001441046102023000124160ustar { "git": { "sha1": "2fb9ed8922e244117040bb037a7d141a6a2b8228" }, "path_in_vcs": "digest" }digest-0.11.3/CHANGELOG.md000064400000000000000000000171111046102023000127770ustar 00000000000000# 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.11.3 (2026-04-03) ### Added - `dev::initialized_mac_test` function ([#2367]) - `TryCustomizedInit` trait ([#2395]) [#2367]: https://github.com/RustCrypto/traits/pull/2367 [#2395]: https://github.com/RustCrypto/traits/pull/2395 ## 0.11.2 (2026-03-13) ### Changed - Do not implement `Clone` as part of `(Reset)MacTraits` in the `buffer_fixed!` macro ([#2341]) - `EagerHash` trait to be a sub-trait of `Clone` ([#2341]) [#2341]: https://github.com/RustCrypto/traits/pull/2341 ## 0.11.1 (2026-02-25) [YANKED] Note: this version was yanked because v0.11.2 introduces minor breaking changes affecting only pre-release versions of downstream crates. ### Added - `SmallBlockSizeUser` helper trait. The trait is a sub-trait of `BlockSizeUser` with `BlockSize` bounded by `block_buffer::BlockSizes`. ([#2309]) ### Changed - `BufferKindUser` is now a sub-trait of `SmallBlockSizeUser` ([#2309]) [#2309]: https://github.com/RustCrypto/traits/pull/2309 ## 0.11.0 (2026-02-13) [YANKED] Note: this version was yanked because v0.11.1 introduces breaking changes. Users should migrate to `digest` v0.11.1 and `crypto-common` v0.2.1 using `cargo update`. ### Added - `CustomizedInit` trait ([#1334]) - `SerializableState` support ([#1369]) - `DynDigestWithOid` wrapper trait ([#1390]) - `VariableOutputCoreCustomized` trait ([#1787], [#2043]) - `buffer_fixed`, `buffer_ct_variable`, `buffer_rt_variable`, and `buffer_xof` macros ([#1799]) - `XofFixedWrapper` ([#1815]) - `CollisionResistance` trait ([#1820]) - `CoreProxy::compose/decompose` methods ([#1898]) - `EagerHash` trait ([#2014]) ### Changed - Replaced `generic-array` with `hybrid-array` ([#1358]) - `crypto-common` dependency bumped to v0.2 ([#1173]) - Edition changed to 2024 and MSRV bumped to 1.85 ([#1759]) - Bump `const-oid` dependency to v0.10 ([#1772]) - `digest::core_api` renamed to `digest::block_api` ([#1799]) - `CtVariableCoreWrapper` renamed to `CtOutWrapper` ([#1799]) - Removed the OID type parameter from `CtOutWrapper` ([#1799]) - Implementations of the `SerializableState` trait ([#1953]) - `new_test!` and `new_mac_test!` macros ([#1958]) - Bump `block-buffer` to v0.11 ([#2082]) - Re-export of `crypto-common` moved to `digest::common` ([#2237]) - Bump `crypto-common` to v0.2 ([#2276]) - Replace `subtle` with `ctutils` ([#2301]) ### Removed - `Mac::new`, `Mac::new_from_slice`, and `Mac::generate_key` methods ([#1173]) - `CoreWrapper`, `RtVariableCoreWrapper`, and `XofReaderCoreWrapper` types ([#1799]) - `io::Write/Read` implementations in favor of the `digest_io::IoWrapper` type ([#1809]) - `VariableOutput` trait ([#2043]) - Implementation of `subtle::ConstantTimeEq` for `CtOutput`. Note that implementation of `PartialEq`/`Eq` trait is still const time. ([#2292]) [#1173]: https://github.com/RustCrypto/traits/pull/1173 [#1334]: https://github.com/RustCrypto/traits/pull/1334 [#1358]: https://github.com/RustCrypto/traits/pull/1358 [#1369]: https://github.com/RustCrypto/traits/pull/1369 [#1390]: https://github.com/RustCrypto/traits/pull/1390 [#1759]: https://github.com/RustCrypto/traits/pull/1759 [#1772]: https://github.com/RustCrypto/traits/pull/1772 [#1787]: https://github.com/RustCrypto/traits/pull/1787 [#1799]: https://github.com/RustCrypto/traits/pull/1799 [#1809]: https://github.com/RustCrypto/traits/pull/1809 [#1815]: https://github.com/RustCrypto/traits/pull/1815 [#1820]: https://github.com/RustCrypto/traits/pull/1820 [#1898]: https://github.com/RustCrypto/traits/pull/1898 [#1953]: https://github.com/RustCrypto/traits/pull/1953 [#1958]: https://github.com/RustCrypto/traits/pull/1958 [#2014]: https://github.com/RustCrypto/traits/pull/2014 [#2043]: https://github.com/RustCrypto/traits/pull/2043 [#2082]: https://github.com/RustCrypto/traits/pull/2082 [#2237]: https://github.com/RustCrypto/traits/pull/2237 [#2276]: https://github.com/RustCrypto/traits/pull/2276 [#2292]: https://github.com/RustCrypto/traits/pull/2292 [#2301]: https://github.com/RustCrypto/traits/pull/2301 ## 0.10.7 (2023-05-19) ### Changed - Loosen `subtle` version requirement ([#1260]) [#1260]: https://github.com/RustCrypto/traits/pull/1260 ## 0.10.6 (2022-11-17) ### Added - `Mac::verify_reset` and `Mac::verify_slice_reset` methods ([#1154]) [#1154]: https://github.com/RustCrypto/traits/pull/1154 ## 0.10.5 (2022-09-16) ### Fixed - MSRV build ([#1117]) [#1117]: https://github.com/RustCrypto/traits/pull/1117 ## 0.10.4 (2022-09-16) ### Added - Feature-gated implementation of the `const_oid::AssociatedOid` trait for the core wrappers. ([#1098]) [#1098]: https://github.com/RustCrypto/traits/pull/1098 ## 0.10.3 (2022-02-16) ### Fixed - Minimal versions build ([#940]) [#940]: https://github.com/RustCrypto/traits/pull/940 ## 0.10.2 (2022-02-10) ### Changed - Relax bounds on the `Mac` trait ([#849]) [#849]: https://github.com/RustCrypto/traits/pull/849 ## 0.10.1 (2021-12-14) [YANKED] ### Added - `Update::chain` and `Digest::new_with_prefix` methods. ([#846]) - `Mac::generate_key` method. ([#847]) ### Fixed - Doc cfg attribute for `CtOutput` and `MacError`. ([#842]) - Expose `KeyInit::generate_key` method in docs. ([#847]) [#842]: https://github.com/RustCrypto/traits/pull/842 [#846]: https://github.com/RustCrypto/traits/pull/846 [#847]: https://github.com/RustCrypto/traits/pull/847 ## 0.10.0 (2021-12-07) [YANKED] ### Changed - Dirty traits are removed and instead block-level traits are introduced. Variable output traits reworked and now support both run and compile time selection of output size. ([#380], [#819]) - The `crypto-mac` traits are reworked and merged in. ([#819]) [#819]: https://github.com/RustCrypto/traits/pull/819 [#380]: https://github.com/RustCrypto/traits/pull/380 ## 0.9.0 (2020-06-09) ### Added - `ExtendableOutputDirty` and `VariableOutputDirty` traits ([#183]) - `FixedOutputDirty` trait + `finalize_into*` ([#180]) - `XofReader::read_boxed` method ([#178], [#181], [#182]) - `alloc` feature ([#163]) - Re-export `typenum::consts` as `consts` ([#123]) - `Output` type alias ([#115]) ### Changed - Rename `*result*` methods to `finalize` ala IUF ([#161]) - Use `impl AsRef<[u8]>` instead of generic params on methods ([#112]) - Rename `Input::input` to `Update::update` ala IUF ([#111]) - Upgrade to Rust 2018 edition ([#109]) - Bump `generic-array` to v0.14 ([#95]) [#183]: https://github.com/RustCrypto/traits/pull/183 [#181]: https://github.com/RustCrypto/traits/pull/181 [#182]: https://github.com/RustCrypto/traits/pull/182 [#180]: https://github.com/RustCrypto/traits/pull/180 [#178]: https://github.com/RustCrypto/traits/pull/178 [#163]: https://github.com/RustCrypto/traits/pull/163 [#161]: https://github.com/RustCrypto/traits/pull/161 [#123]: https://github.com/RustCrypto/traits/pull/123 [#115]: https://github.com/RustCrypto/traits/pull/115 [#111]: https://github.com/RustCrypto/traits/pull/111 [#112]: https://github.com/RustCrypto/traits/pull/112 [#109]: https://github.com/RustCrypto/traits/pull/109 [#95]: https://github.com/RustCrypto/traits/pull/95 ## 0.8.1 (2019-06-30) ## 0.8.0 (2018-10-01) ## 0.7.6 (2018-09-21) ## 0.7.5 (2018-07-13) ## 0.7.4 (2018-06-21) ## 0.7.3 (2018-06-20) ## 0.7.2 (2017-11-17) ## 0.7.1 (2017-11-15) ## 0.7.0 (2017-11-14) ## 0.6.2 (2017-07-24) ## 0.6.1 (2017-06-18) ## 0.6.0 (2017-06-12) ## 0.5.2 (2017-05-02) ## 0.5.1 (2017-05-02) ## 0.5.0 (2017-04-06) ## 0.4.0 (2016-12-24) ## 0.3.1 (2016-12-16) ## 0.3.0 (2016-11-17) ## 0.2.1 (2016-10-14) ## 0.2.0 (2016-10-14) ## 0.1.0 (2016-10-06) digest-0.11.3/Cargo.lock0000644000000305111046102023000103720ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "anyhow" version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "bitflags" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "blobby" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89af0b093cc13baa4e51e64e65ec2422f7e73aea0e612e5ad3872986671622f1" [[package]] name = "block-buffer" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ "hybrid-array", "zeroize", ] [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cmov" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" [[package]] name = "const-oid" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" [[package]] name = "cpufeatures" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] [[package]] name = "crypto-common" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" dependencies = [ "getrandom", "hybrid-array", "rand_core", ] [[package]] name = "ctutils" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" dependencies = [ "cmov", ] [[package]] name = "digest" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" dependencies = [ "block-buffer", "const-oid", "crypto-common", ] [[package]] name = "digest" version = "0.11.3" dependencies = [ "blobby", "block-buffer", "const-oid", "crypto-common", "ctutils", "sha2", "zeroize", ] [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "getrandom" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", "r-efi", "rand_core", "wasip2", "wasip3", ] [[package]] name = "hashbrown" version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "foldhash", ] [[package]] name = "hashbrown" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hybrid-array" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" dependencies = [ "typenum", ] [[package]] name = "id-arena" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "indexmap" version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", "hashbrown 0.17.0", "serde", "serde_core", ] [[package]] name = "itoa" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "leb128fmt" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "memchr" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "prettyplease" version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", "syn", ] [[package]] name = "proc-macro2" version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand_core" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "semver" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", ] [[package]] name = "serde_core" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", "serde", "serde_core", "zmij", ] [[package]] name = "sha2" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", "cpufeatures", "digest 0.11.2", ] [[package]] name = "syn" version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "typenum" version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "wasip2" version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ "wit-bindgen 0.46.0", ] [[package]] name = "wasip3" version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ "wit-bindgen 0.51.0", ] [[package]] name = "wasm-encoder" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" dependencies = [ "leb128fmt", "wasmparser", ] [[package]] name = "wasm-metadata" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", "indexmap", "wasm-encoder", "wasmparser", ] [[package]] name = "wasmparser" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags", "hashbrown 0.15.5", "indexmap", "semver", ] [[package]] name = "wit-bindgen" version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" dependencies = [ "wit-bindgen-rust-macro", ] [[package]] name = "wit-bindgen-core" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" dependencies = [ "anyhow", "heck", "wit-parser", ] [[package]] name = "wit-bindgen-rust" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", "heck", "indexmap", "prettyplease", "syn", "wasm-metadata", "wit-bindgen-core", "wit-component", ] [[package]] name = "wit-bindgen-rust-macro" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" dependencies = [ "anyhow", "prettyplease", "proc-macro2", "quote", "syn", "wit-bindgen-core", "wit-bindgen-rust", ] [[package]] name = "wit-component" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", "bitflags", "indexmap", "log", "serde", "serde_derive", "serde_json", "wasm-encoder", "wasm-metadata", "wasmparser", "wit-parser", ] [[package]] name = "wit-parser" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", "indexmap", "log", "semver", "serde", "serde_derive", "serde_json", "unicode-xid", "wasmparser", ] [[package]] name = "zeroize" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" digest-0.11.3/Cargo.toml0000644000000056151046102023000104240ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2024" rust-version = "1.85" name = "digest" version = "0.11.3" authors = ["RustCrypto Developers"] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Traits for cryptographic hash functions and message authentication codes" documentation = "https://docs.rs/digest" readme = "README.md" keywords = [ "digest", "crypto", "hash", ] categories = [ "cryptography", "no-std", ] license = "MIT OR Apache-2.0" repository = "https://github.com/RustCrypto/traits" [package.metadata.docs.rs] all-features = true [features] alloc = [] block-api = ["dep:block-buffer"] default = ["block-api"] dev = ["blobby"] getrandom = [ "common/getrandom", "rand_core", ] mac = ["dep:ctutils"] oid = ["dep:const-oid"] rand_core = ["common/rand_core"] zeroize = [ "dep:zeroize", "block-buffer?/zeroize", ] [lib] name = "digest" path = "src/lib.rs" [[test]] name = "dummy_fixed" path = "tests/dummy_fixed.rs" [dependencies.blobby] version = "0.4" optional = true [dependencies.block-buffer] version = "0.12" optional = true [dependencies.common] version = "0.2" package = "crypto-common" [dependencies.const-oid] version = "0.10" optional = true [dependencies.ctutils] version = "0.4" optional = true [dependencies.zeroize] version = "1.7" optional = true default-features = false [dev-dependencies.sha2] version = "0.11" [lints.clippy] borrow_as_ptr = "warn" cast_lossless = "warn" cast_possible_truncation = "warn" cast_possible_wrap = "warn" cast_precision_loss = "warn" cast_sign_loss = "warn" checked_conversions = "warn" from_iter_instead_of_collect = "warn" implicit_saturating_sub = "warn" manual_assert = "warn" map_unwrap_or = "warn" missing_errors_doc = "warn" missing_panics_doc = "warn" mod_module_files = "warn" must_use_candidate = "warn" needless_range_loop = "allow" ptr_as_ptr = "warn" redundant_closure_for_method_calls = "warn" ref_as_ptr = "warn" return_self_not_must_use = "warn" semicolon_if_nothing_returned = "warn" std_instead_of_alloc = "warn" std_instead_of_core = "warn" trivially_copy_pass_by_ref = "warn" undocumented_unsafe_blocks = "warn" unnecessary_safety_comment = "warn" unwrap_in_result = "warn" unwrap_used = "warn" [lints.rust] missing_copy_implementations = "warn" missing_debug_implementations = "warn" missing_docs = "warn" trivial_casts = "warn" trivial_numeric_casts = "warn" unused_lifetimes = "warn" unused_qualifications = "warn" digest-0.11.3/Cargo.toml.orig000064400000000000000000000023611046102023000140560ustar 00000000000000[package] name = "digest" version = "0.11.3" authors = ["RustCrypto Developers"] edition = "2024" rust-version = "1.85" documentation = "https://docs.rs/digest" readme = "README.md" repository = "https://github.com/RustCrypto/traits" license = "MIT OR Apache-2.0" keywords = ["digest", "crypto", "hash"] categories = ["cryptography", "no-std"] description = "Traits for cryptographic hash functions and message authentication codes" [dependencies] common = { version = "0.2", package = "crypto-common" } # optional dependencies block-buffer = { version = "0.12", optional = true } blobby = { version = "0.4", optional = true } const-oid = { version = "0.10", optional = true } ctutils = { version = "0.4", optional = true } zeroize = { version = "1.7", optional = true, default-features = false } [dev-dependencies] sha2 = "0.11" [features] default = ["block-api"] alloc = [] block-api = ["dep:block-buffer"] # Enable block API traits dev = ["blobby"] getrandom = ["common/getrandom", "rand_core"] mac = ["dep:ctutils"] # Enable MAC traits rand_core = ["common/rand_core"] # Enable random key generation methods oid = ["dep:const-oid"] zeroize = ["dep:zeroize", "block-buffer?/zeroize"] [lints] workspace = true [package.metadata.docs.rs] all-features = true digest-0.11.3/LICENSE-APACHE000064400000000000000000000251411046102023000131140ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. digest-0.11.3/LICENSE-MIT000064400000000000000000000021171046102023000126220ustar 00000000000000Copyright (c) 2017-2025 RustCrypto Developers Copyright (c) 2017 Artyom Pavlov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. digest-0.11.3/README.md000064400000000000000000000077601046102023000124560ustar 00000000000000# RustCrypto: Digest Algorithm Traits [![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] Traits which describe functionality of [cryptographic hash functions][0], a.k.a. digest algorithms. See [RustCrypto/hashes][1] for implementations which use this trait. ## Usage Let us demonstrate how to use crates in this repository using Sha256 as an example. First add the `sha2` crate to your `Cargo.toml`: ```toml [dependencies] sha2 = "0.11" ``` `sha2` and other crates re-export `digest` crate and `Digest` trait for convenience, so you don't have to add `digest` crate as an explicit dependency. Now you can write the following code: ```rust use sha2::{Sha256, Digest}; let mut hasher = Sha256::new(); let data = b"Hello world!"; hasher.update(data); // `input` can be called repeatedly and is generic over `AsRef<[u8]>` hasher.update("String data"); // Note that calling `finalize()` consumes hasher let hash = hasher.finalize(); println!("Result: {:?}", hash); ``` In this example `hash` has type [`Array`][2], which is a generic alternative to `[u8; 32]`. Alternatively you can use chained approach, which is equivalent to the previous example: ```rust use sha2::{Sha256, Digest}; let hash = Sha256::new() .chain_update(b"Hello world!") .chain_update("String data") .finalize(); println!("Result: {:?}", hash); ``` If the whole message is available you also can use convenience `digest` method: ```rust use sha2::{Sha256, Digest}; let hash = Sha256::digest(b"my message"); println!("Result: {:?}", hash); ``` ### Generic code You can write generic code over `Digest` (or other traits from `digest` crate) trait which will work over different hash functions: ```rust use digest::Digest; // Toy example, do not use it in practice! // Instead use crates from: https://github.com/RustCrypto/password-hashing fn hash_password(password: &str, salt: &str, output: &mut [u8]) { let mut hasher = D::new(); hasher.update(password.as_bytes()); hasher.update(b"$"); hasher.update(salt.as_bytes()); output.copy_from_slice(hasher.finalize().as_slice()) } let mut buf1 = [0u8; 32]; let mut buf2 = [0u8; 64]; hash_password::("my_password", "abcd", &mut buf1); hash_password::("my_password", "abcd", &mut buf2); ``` If you want to use hash functions with trait objects, use `digest::DynDigest` trait. ## 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. [//]: # (badges) [crate-image]: https://img.shields.io/crates/v/digest.svg [crate-link]: https://crates.io/crates/digest [docs-image]: https://docs.rs/digest/badge.svg [docs-link]: https://docs.rs/digest/ [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260041-hashes [build-image]: https://github.com/RustCrypto/traits/actions/workflows/digest.yml/badge.svg?branch=master [build-link]: https://github.com/RustCrypto/traits/actions/workflows/digest.yml?query=branch:master [//]: # (general links) [0]: https://en.wikipedia.org/wiki/Cryptographic_hash_function [1]: https://github.com/RustCrypto/hashes [2]: https://docs.rs/hybrid-array [3]: https://doc.rust-lang.org/std/io/trait.Read.html [4]: https://doc.rust-lang.org/std/io/trait.Write.html [5]: https://en.wikipedia.org/wiki/Hash-based_message_authentication_code [6]: https://github.com/RustCrypto/MACs digest-0.11.3/src/block_api/ct_variable.rs000064400000000000000000000130541046102023000165230ustar 00000000000000use super::{ AlgorithmName, Buffer, BufferKindUser, FixedOutputCore, Reset, TruncSide, UpdateCore, VariableOutputCore, VariableOutputCoreCustomized, }; #[cfg(feature = "mac")] use crate::MacMarker; use crate::{CollisionResistance, CustomizedInit, HashMarker}; use common::{ Block, BlockSizeUser, OutputSizeUser, array::{Array, ArraySize}, hazmat::{DeserializeStateError, SerializableState, SerializedState}, typenum::{IsLessOrEqual, True}, }; use core::{fmt, marker::PhantomData}; /// Wrapper around [`VariableOutputCore`] which selects output size at compile time. pub struct CtOutWrapper where T: VariableOutputCore, OutSize: ArraySize + IsLessOrEqual, { inner: T, _out: PhantomData, } impl Clone for CtOutWrapper where T: VariableOutputCore + Clone, OutSize: ArraySize + IsLessOrEqual, { fn clone(&self) -> Self { Self { inner: self.inner.clone(), _out: PhantomData, } } } impl HashMarker for CtOutWrapper where T: VariableOutputCore + HashMarker, OutSize: ArraySize + IsLessOrEqual, { } #[cfg(feature = "mac")] impl MacMarker for CtOutWrapper where T: VariableOutputCore + MacMarker, OutSize: ArraySize + IsLessOrEqual, { } impl CollisionResistance for CtOutWrapper where T: VariableOutputCore + CollisionResistance, OutSize: ArraySize + IsLessOrEqual, { type CollisionResistance = T::CollisionResistance; } impl BlockSizeUser for CtOutWrapper where T: VariableOutputCore, OutSize: ArraySize + IsLessOrEqual, { type BlockSize = T::BlockSize; } impl UpdateCore for CtOutWrapper where T: VariableOutputCore, OutSize: ArraySize + IsLessOrEqual, { #[inline] fn update_blocks(&mut self, blocks: &[Block]) { self.inner.update_blocks(blocks); } } impl OutputSizeUser for CtOutWrapper where T: VariableOutputCore, OutSize: ArraySize + IsLessOrEqual, { type OutputSize = OutSize; } impl BufferKindUser for CtOutWrapper where T: VariableOutputCore, OutSize: ArraySize + IsLessOrEqual, { type BufferKind = T::BufferKind; } impl FixedOutputCore for CtOutWrapper where T: VariableOutputCore, OutSize: ArraySize + IsLessOrEqual, { #[inline] fn finalize_fixed_core( &mut self, buffer: &mut Buffer, out: &mut Array, ) { let mut full_res = Default::default(); self.inner.finalize_variable_core(buffer, &mut full_res); let n = out.len(); let m = full_res.len() - n; match T::TRUNC_SIDE { TruncSide::Left => out.copy_from_slice(&full_res[..n]), TruncSide::Right => out.copy_from_slice(&full_res[m..]), } } } impl Default for CtOutWrapper where T: VariableOutputCore, OutSize: ArraySize + IsLessOrEqual, { #[inline] fn default() -> Self { Self { inner: T::new(OutSize::USIZE).unwrap(), _out: PhantomData, } } } impl CustomizedInit for CtOutWrapper where T: VariableOutputCoreCustomized, OutSize: ArraySize + IsLessOrEqual, { #[inline] fn new_customized(customization: &[u8]) -> Self { Self { inner: T::new_customized(customization, OutSize::USIZE), _out: PhantomData, } } } impl Reset for CtOutWrapper where T: VariableOutputCore, OutSize: ArraySize + IsLessOrEqual, { #[inline] fn reset(&mut self) { *self = Default::default(); } } impl AlgorithmName for CtOutWrapper where T: VariableOutputCore + AlgorithmName, OutSize: ArraySize + IsLessOrEqual, { fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { T::write_alg_name(f)?; f.write_str("_")?; write!(f, "{}", OutSize::USIZE) } } #[cfg(feature = "zeroize")] impl zeroize::ZeroizeOnDrop for CtOutWrapper where T: VariableOutputCore + zeroize::ZeroizeOnDrop, OutSize: ArraySize + IsLessOrEqual, { } impl fmt::Debug for CtOutWrapper where T: VariableOutputCore + AlgorithmName, OutSize: ArraySize + IsLessOrEqual, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Self::write_alg_name(f) } } impl SerializableState for CtOutWrapper where T: VariableOutputCore + SerializableState, OutSize: ArraySize + IsLessOrEqual, { type SerializedStateSize = ::SerializedStateSize; fn serialize(&self) -> SerializedState { self.inner.serialize() } fn deserialize( serialized_state: &SerializedState, ) -> Result { let _out = PhantomData; T::deserialize(serialized_state).map(|inner| Self { inner, _out }) } } digest-0.11.3/src/block_api.rs000064400000000000000000000134731046102023000142550ustar 00000000000000//! Low-level traits operating on blocks and wrappers around them. //! //! Usage of traits in this module in user code is discouraged. Instead use //! core algorithm wrapped by the wrapper types, which implement the //! higher-level traits. use crate::{Digest, HashMarker, InvalidOutputSize}; pub use block_buffer::{Eager, Lazy}; pub use common::{AlgorithmName, Block, BlockSizeUser, OutputSizeUser, Reset}; use block_buffer::{BlockBuffer, BlockSizes, BufferKind}; use common::Output; mod ct_variable; pub use ct_variable::CtOutWrapper; /// Buffer type used by type which implements [`BufferKindUser`]. pub type Buffer = BlockBuffer<::BlockSize, ::BufferKind>; /// Types which consume data in blocks. pub trait UpdateCore: BlockSizeUser { /// Update state using the provided data blocks. fn update_blocks(&mut self, blocks: &[Block]); } /// Sub-trait of [`BlockSizeUser`] implemented if `BlockSize` is /// bigger than `U0` and smaller than `U256`. /// /// This trait relies on the hack suggested [here][0] to work around /// the long standing Rust issue regarding non-propagation of `where` bounds. /// /// [0]: https://github.com/rust-lang/rust/issues/20671#issuecomment-1905186183 pub trait SmallBlockSizeUser: BlockSizeUser::_BlockSize> { /// Helper associated type equal to `::BlockSize`. type _BlockSize: BlockSizes; } impl SmallBlockSizeUser for T where T::BlockSize: BlockSizes, { type _BlockSize = T::BlockSize; } /// Types which use [`BlockBuffer`] functionality. pub trait BufferKindUser: SmallBlockSizeUser { /// Block buffer kind over which type operates. type BufferKind: BufferKind; } /// Trait implemented by eager hashes which expose their block-level core. pub trait EagerHash: SmallBlockSizeUser + Digest + Clone { /// Block-level core type of the hash. type Core: HashMarker + UpdateCore + FixedOutputCore + SmallBlockSizeUser<_BlockSize = ::_BlockSize> + BufferKindUser + Default + Clone; } impl EagerHash for T where T: CoreProxy + SmallBlockSizeUser + Digest + Clone, ::Core: HashMarker + UpdateCore + FixedOutputCore + SmallBlockSizeUser<_BlockSize = ::_BlockSize> + BufferKindUser + Default + Clone, { type Core = T::Core; } /// Core trait for hash functions with fixed output size. pub trait FixedOutputCore: UpdateCore + BufferKindUser + OutputSizeUser { /// Finalize state using remaining data stored in the provided block buffer, /// write result into provided array and leave `self` in a dirty state. fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output); } /// Core trait for hash functions with extendable (XOF) output size. pub trait ExtendableOutputCore: UpdateCore + BufferKindUser { /// XOF reader core state. type ReaderCore: XofReaderCore; /// Retrieve XOF reader using remaining data stored in the block buffer /// and leave hasher in a dirty state. fn finalize_xof_core(&mut self, buffer: &mut Buffer) -> Self::ReaderCore; } /// Core reader trait for extendable-output function (XOF) result. pub trait XofReaderCore: BlockSizeUser { /// Read next XOF block. fn read_block(&mut self) -> Block; } /// Core trait for hash functions with variable output size. /// /// Maximum output size is equal to [`OutputSizeUser::OutputSize`]. /// Users are expected to truncate result returned by the /// [`finalize_variable_core`] to `output_size` passed to the [`new`] method /// during construction. Truncation side is defined by the [`TRUNC_SIDE`] /// associated constant. /// /// [`finalize_variable_core`]: VariableOutputCore::finalize_variable_core /// [`new`]: VariableOutputCore::new /// [`TRUNC_SIDE`]: VariableOutputCore::TRUNC_SIDE pub trait VariableOutputCore: UpdateCore + OutputSizeUser + BufferKindUser + Sized { /// Side which should be used in a truncated result. const TRUNC_SIDE: TruncSide; /// Initialize hasher state for given output size. /// /// # Errors /// Returns [`InvalidOutputSize`] if `output_size` is not valid for /// the algorithm, e.g. if it's bigger than the [`OutputSize`] /// associated type. /// /// [`OutputSize`]: OutputSizeUser::OutputSize fn new(output_size: usize) -> Result; /// Finalize hasher and write full hashing result into the `out` buffer. /// /// The result must be truncated to `output_size` used during hasher /// construction. Truncation side is defined by the [`TRUNC_SIDE`] /// associated constant. /// /// [`TRUNC_SIDE`]: VariableOutputCore::TRUNC_SIDE fn finalize_variable_core(&mut self, buffer: &mut Buffer, out: &mut Output); } /// Trait adding customization string to hash functions with variable output. pub trait VariableOutputCoreCustomized: VariableOutputCore { /// Create new hasher instance with the given customization string and output size. fn new_customized(customization: &[u8], output_size: usize) -> Self; } /// Type which used for defining truncation side in the [`VariableOutputCore`] /// trait. #[derive(Copy, Clone, Debug)] pub enum TruncSide { /// Truncate left side, i.e. `&out[..n]`. Left, /// Truncate right side, i.e. `&out[m..]`. Right, } /// A proxy trait to the core block-level type. pub trait CoreProxy { /// Core block-level type. type Core: BufferKindUser; /// Create `Self` from core and buffer. fn compose(core: Self::Core, buffer: Buffer) -> Self; /// Decompose `self` into core and buffer. fn decompose(self) -> (Self::Core, Buffer); } digest-0.11.3/src/buffer_macros/fixed.rs000064400000000000000000000437761046102023000162570ustar 00000000000000/// Creates a buffered wrapper around block-level "core" type which implements fixed output size traits. #[macro_export] macro_rules! buffer_fixed { ( $(#[$attr:meta])* $v:vis struct $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); impl: $($trait_name:ident)*; ) => { $(#[$attr])* $v struct $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? { core: $core_ty, buffer: $crate::block_api::Buffer<$core_ty>, } $crate::buffer_fixed!( impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*; ); }; ( $(#[$attr:meta])* $v:vis struct $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); oid: $oid:literal; impl: $($trait_name:ident)*; ) => { $crate::buffer_fixed!( $(#[$attr])* $v struct $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); impl: $($trait_name)*; ); #[cfg(feature = "oid")] impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::const_oid::AssociatedOid for $name$(< $( $lt ),+ >)? { const OID: $crate::const_oid::ObjectIdentifier = $crate::const_oid::ObjectIdentifier::new_unwrap($oid); } }; // Terminates `impl_inner` sequences. ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); ; ) => {}; // Implements the set of traits common for fixed output hashes: // `Default`, `Clone`, `HashMarker`, `Reset`, `FixedOutputReset`, `SerializableState` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); FixedHashTraits $($trait_name:ident)*; ) => { $crate::buffer_fixed!( impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); BaseFixedTraits AlgorithmName Default Clone HashMarker Reset FixedOutputReset SerializableState ZeroizeOnDrop $($trait_name)*; ); }; // Implements the set of traits common for MAC functions: // `Debug`, `BlockSizeUser`, `OutputSizeUser`, `CoreProxy`, `Update`, `FixedOutput`, `MacMarker` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); MacTraits $($trait_name:ident)*; ) => { $crate::buffer_fixed!( impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); BaseFixedTraits MacMarker $($trait_name)*; ); }; // Implements the set of traits common for resettable MAC functions: // `Debug`, `BlockSizeUser`, `OutputSizeUser`, `CoreProxy`, `Update`, `FixedOutput`, // `MacMarker`, `Reset`, `FixedOutputReset`. ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); ResetMacTraits $($trait_name:ident)*; ) => { $crate::buffer_fixed!( impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); MacTraits Reset FixedOutputReset $($trait_name)*; ); }; // Implements basic fixed traits: // `Debug`, `BlockSizeUser`, `OutputSizeUser`, `CoreProxy`, `Update`, and `FixedOutput`. ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); BaseFixedTraits $($trait_name:ident)*; ) => { $crate::buffer_fixed!( impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); Debug BlockSizeUser OutputSizeUser CoreProxy Update FixedOutput $($trait_name)*; ); }; // Implements `Debug` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); Debug $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? core::fmt::Debug for $name$(< $( $lt ),+ >)? { #[inline] fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.write_str(concat!(stringify!($name), " { ... }")) } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `AlgorithmName` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); AlgorithmName $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::common::AlgorithmName for $name$(< $( $lt ),+ >)? { #[inline] fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { <$core_ty as $crate::common::AlgorithmName>::write_alg_name(f) } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `BlockSizeUser` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); BlockSizeUser $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::block_api::BlockSizeUser for $name$(< $( $lt ),+ >)? { type BlockSize = <$core_ty as $crate::common::BlockSizeUser>::BlockSize; } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `OutputSizeUser` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); OutputSizeUser $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::OutputSizeUser for $name$(< $( $lt ),+ >)? { type OutputSize = <$core_ty as $crate::block_api::OutputSizeUser>::OutputSize; } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `CoreProxy` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); CoreProxy $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::block_api::CoreProxy for $name$(< $( $lt ),+ >)? { type Core = $core_ty; fn compose(core: Self::Core, buffer: $crate::block_api::Buffer) -> Self { Self { core, buffer } } fn decompose(self) -> (Self::Core, $crate::block_api::Buffer) { let Self { core, buffer } = self; (core, buffer) } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `Update` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); Update $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::Update for $name$(< $( $lt ),+ >)? { #[inline] fn update(&mut self, data: &[u8]) { let Self { core, buffer } = self; buffer.digest_blocks(data, |blocks| { $crate::block_api::UpdateCore::update_blocks(core, blocks) }); } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `FixedOutput` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); FixedOutput $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::FixedOutput for $name$(< $( $lt ),+ >)? { #[inline] fn finalize_into(mut self, out: &mut $crate::Output) { let Self { core, buffer } = &mut self; $crate::block_api::FixedOutputCore::finalize_fixed_core(core, buffer, out); } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `Default` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); Default $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? Default for $name$(< $( $lt ),+ >)? { #[inline] fn default() -> Self { Self { core: Default::default(), buffer: Default::default(), } } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `CustomizedInit` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); CustomizedInit $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::CustomizedInit for $name$(< $( $lt ),+ >)? { #[inline] fn new_customized(customization: &[u8]) -> Self { Self { core: $crate::CustomizedInit::new_customized(customization), buffer: Default::default(), } } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `Clone` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); Clone $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? Clone for $name$(< $( $lt ),+ >)? { #[inline] fn clone(&self) -> Self { Self { core: Clone::clone(&self.core), buffer: Clone::clone(&self.buffer), } } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `HashMarker` and asserts that `$core_ty` implements it ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); HashMarker $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::HashMarker for $name$(< $( $lt ),+ >)? {} // Verify that `$core_ty` implements `HashMarker` const _: () = { fn check$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?(v: &$core_ty) { v as &dyn $crate::HashMarker; } }; $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `MacMarker` and asserts that `$core_ty` implements it ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); MacMarker $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::MacMarker for $name$(< $( $lt ),+ >)? {} // Verify that `$core_ty` implements `MacMarker` const _: () = { fn check$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?(v: &$core_ty) { v as &dyn $crate::MacMarker; } }; $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `InnerUser` and `InnerInit` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); InnerInit $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::common::InnerUser for $name$(< $( $lt ),+ >)? { type Inner = <$core_ty as $crate::common::InnerUser>::Inner; } impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::common::InnerInit for $name$(< $( $lt ),+ >)? { #[inline] fn inner_init(inner: Self::Inner) -> Self { Self { core: <$core_ty as $crate::common::InnerInit>::inner_init(inner), buffer: Default::default(), } } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `KeySizeUser` and `KeyInit` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); KeyInit $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::common::KeySizeUser for $name$(< $( $lt ),+ >)? { type KeySize = <$core_ty as $crate::common::KeySizeUser>::KeySize; } impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::KeyInit for $name$(< $( $lt ),+ >)? { #[inline] fn new(key: &$crate::Key) -> Self { Self { core: <$core_ty as $crate::KeyInit>::new(key), buffer: Default::default(), } } #[inline] fn new_from_slice(key: &[u8]) -> Result { <$core_ty as $crate::KeyInit>::new_from_slice(key).map(|core| Self { core, buffer: Default::default() } ) } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `Reset` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); Reset $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::Reset for $name$(< $( $lt ),+ >)? { #[inline] fn reset(&mut self) { $crate::Reset::reset(&mut self.core); self.buffer.reset(); } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `FixedOutputReset` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); FixedOutputReset $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::FixedOutputReset for $name$(< $( $lt ),+ >)? { #[inline] fn finalize_into_reset(&mut self, out: &mut $crate::Output) { let Self { core, buffer } = self; $crate::block_api::FixedOutputCore::finalize_fixed_core(core, buffer, out); $crate::Reset::reset(self); } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `SerializableState` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); SerializableState $($trait_name:ident)*; ) => { impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::common::hazmat::SerializableState for $name$(< $( $lt ),+ >)? { type SerializedStateSize = $crate::typenum::Sum< <$core_ty as $crate::common::hazmat::SerializableState>::SerializedStateSize, $crate::block_buffer::SerializedBufferSize< <$core_ty as $crate::block_api::BlockSizeUser>::BlockSize, <$core_ty as $crate::block_api::BufferKindUser>::BufferKind, > >; #[inline] fn serialize(&self) -> $crate::common::hazmat::SerializedState { let serialized_core = self.core.serialize(); let serialized_buf = self.buffer.serialize(); serialized_core.concat(serialized_buf) } #[inline] fn deserialize( serialized_state: &$crate::common::hazmat::SerializedState, ) -> Result { use $crate::common::hazmat::{SerializableState, DeserializeStateError}; let (serialized_core, serialized_buf) = serialized_state .split_ref::<<$core_ty as SerializableState>::SerializedStateSize>(); let core = SerializableState::deserialize(serialized_core)?; let buffer = $crate::block_buffer::BlockBuffer::deserialize(serialized_buf) .map_err(|_| DeserializeStateError)?; Ok(Self { core, buffer }) } } $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; // Implements `ZeroizeOnDrop` ( impl_inner: $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ($core_ty:ty); ZeroizeOnDrop $($trait_name:ident)*; ) => { // Verify that `$core_ty` and `Buffer<$core_ty>` implement `ZeroizeOnDrop` #[cfg(feature = "zeroize")] const _: () = { fn check_core$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?(v: &$core_ty) { v as &dyn $crate::zeroize::ZeroizeOnDrop; } fn check_buffer$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?(v: &$crate::block_api::Buffer<$core_ty>) { v as &dyn $crate::zeroize::ZeroizeOnDrop; } }; #[cfg(feature = "zeroize")] impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::zeroize::ZeroizeOnDrop for $name$(< $( $lt ),+ >)? {} $crate::buffer_fixed!(impl_inner: $name$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?($core_ty); $($trait_name)*;); }; } digest-0.11.3/src/buffer_macros/variable.rs000064400000000000000000000207751046102023000167370ustar 00000000000000/// Creates a buffered wrapper around block-level "core" type which implements variable output size traits /// with output size selected at compile time. #[macro_export] macro_rules! buffer_ct_variable { ( $(#[$attr:meta])* $vis:vis struct $name:ident<$out_size:ident>($core_ty:ty); exclude: SerializableState; // Ideally, we would use `$core_ty::OutputSize`, but unfortunately the compiler // does not accept such code. The likely reason is this issue: // https://github.com/rust-lang/rust/issues/79629 max_size: $max_size:ty; ) => { $(#[$attr])* $vis struct $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { core: $crate::block_api::CtOutWrapper<$core_ty, $out_size>, buffer: $crate::block_api::Buffer<$core_ty>, } impl<$out_size> core::fmt::Debug for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { #[inline] fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.write_str(concat!(stringify!($name), " { ... }")) } } impl<$out_size> $crate::common::AlgorithmName for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { #[inline] fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { <$core_ty as $crate::common::AlgorithmName>::write_alg_name(f) } } impl<$out_size> Clone for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { #[inline] fn clone(&self) -> Self { Self { core: Clone::clone(&self.core), buffer: Clone::clone(&self.buffer), } } } impl<$out_size> Default for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { #[inline] fn default() -> Self { Self { core: Default::default(), buffer: Default::default(), } } } impl<$out_size> $crate::Reset for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { #[inline] fn reset(&mut self) { $crate::Reset::reset(&mut self.core); self.buffer.reset(); } } impl<$out_size> $crate::block_api::BlockSizeUser for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { type BlockSize = <$core_ty as $crate::common::BlockSizeUser>::BlockSize; } impl<$out_size> $crate::OutputSizeUser for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { type OutputSize = $out_size; } impl<$out_size> $crate::HashMarker for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, {} // Verify that `$wrapped_ty` implements `HashMarker` const _: () = { fn check<$out_size>(v: &$core_ty) where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size>, $crate::typenum::LeEq<$out_size, $max_size>: $crate::typenum::NonZero, { v as &dyn $crate::HashMarker; } }; impl<$out_size> $crate::block_api::CoreProxy for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { type Core = $crate::block_api::CtOutWrapper<$core_ty, $out_size>; fn compose(core: Self::Core, buffer: $crate::block_api::Buffer) -> Self { Self { core, buffer } } fn decompose(self) -> (Self::Core, $crate::block_api::Buffer) { let Self { core, buffer } = self; (core, buffer) } } impl<$out_size> $crate::Update for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { #[inline] fn update(&mut self, data: &[u8]) { let Self { core, buffer } = self; buffer.digest_blocks(data, |blocks| { $crate::block_api::UpdateCore::update_blocks(core, blocks) }); } } impl<$out_size> $crate::FixedOutput for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { #[inline] fn finalize_into(mut self, out: &mut $crate::Output) { let Self { core, buffer } = &mut self; $crate::block_api::FixedOutputCore::finalize_fixed_core(core, buffer, out); } } impl<$out_size> $crate::FixedOutputReset for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { #[inline] fn finalize_into_reset(&mut self, out: &mut $crate::Output) { let Self { core, buffer } = self; $crate::block_api::FixedOutputCore::finalize_fixed_core(core, buffer, out); $crate::Reset::reset(self); } } }; ( $(#[$attr:meta])* $vis:vis struct $name:ident<$out_size:ident>($core_ty:ty); // Ideally, we would use `$core_ty::OutputSize`, but unfortunately the compiler // does not accept such code. The likely reason is this issue: // https://github.com/rust-lang/rust/issues/79629 max_size: $max_size:ty; ) => { $crate::buffer_ct_variable!( $(#[$attr])* $vis struct $name<$out_size>($core_ty); exclude: SerializableState; max_size: $max_size; ); impl<$out_size> $crate::common::hazmat::SerializableState for $name<$out_size> where $out_size: $crate::array::ArraySize + $crate::typenum::IsLessOrEqual<$max_size, Output = $crate::typenum::True>, { type SerializedStateSize = $crate::typenum::Sum< <$core_ty as $crate::common::hazmat::SerializableState>::SerializedStateSize, $crate::block_buffer::SerializedBufferSize< <$core_ty as $crate::block_api::BlockSizeUser>::BlockSize, <$core_ty as $crate::block_api::BufferKindUser>::BufferKind, > >; #[inline] fn serialize(&self) -> $crate::common::hazmat::SerializedState { let serialized_core = self.core.serialize(); let serialized_buf = self.buffer.serialize(); serialized_core.concat(serialized_buf) } #[inline] fn deserialize( serialized_state: &$crate::common::hazmat::SerializedState, ) -> Result { use $crate::common::hazmat::{SerializableState, DeserializeStateError}; let (serialized_core, serialized_buf) = serialized_state .split_ref::<<$core_ty as SerializableState>::SerializedStateSize>(); let core = SerializableState::deserialize(serialized_core)?; let buffer = $crate::block_buffer::BlockBuffer::deserialize(serialized_buf) .map_err(|_| DeserializeStateError)?; Ok(Self { core, buffer }) } } }; } digest-0.11.3/src/buffer_macros/xof.rs000064400000000000000000000243521046102023000157410ustar 00000000000000/// Creates a buffered wrapper around block-level "core" type which implements extendable output size traits. #[macro_export] macro_rules! buffer_xof { ( $(#[$hasher_attr:meta])* $hasher_vis:vis struct $hasher_name:ident($hasher_core:ty); $(oid: $oid:literal;)? impl: $($hasher_trait_name:ident)*; $(#[$reader_attr:meta])* $reader_vis:vis struct $reader_name:ident($reader_core:ty); impl: $($reader_trait_name:ident)*; ) => { $(#[$hasher_attr])* $hasher_vis struct $hasher_name { core: $hasher_core, buffer: $crate::block_api::Buffer<$hasher_core>, } impl $crate::ExtendableOutput for $hasher_name { type Reader = $reader_name; #[inline] fn finalize_xof(mut self) -> Self::Reader { let Self { core, buffer } = &mut self; let core = <$hasher_core as $crate::block_api::ExtendableOutputCore>::finalize_xof_core(core, buffer); let buffer = Default::default(); Self::Reader { core, buffer } } } $( #[cfg(feature = "oid")] impl $crate::const_oid::AssociatedOid for $hasher_name { const OID: $crate::const_oid::ObjectIdentifier = $crate::const_oid::ObjectIdentifier::new_unwrap($oid); } )? $crate::buffer_xof!( impl_inner: $hasher_name($hasher_core); $($hasher_trait_name)*; ); $(#[$reader_attr])* $reader_vis struct $reader_name { core: $reader_core, buffer: $crate::block_buffer::ReadBuffer<<$reader_core as $crate::block_api::BlockSizeUser>::BlockSize>, } impl $crate::XofReader for $reader_name { #[inline] fn read(&mut self, buf: &mut [u8]) { let Self { core, buffer } = self; buffer.read(buf, |block| { *block = $crate::block_api::XofReaderCore::read_block(core); }); } } $crate::buffer_xof!( impl_inner: $reader_name($reader_core); $($reader_trait_name)*; ); }; // Terminates `impl_inner` sequences. ( impl_inner: $name:ident($core_ty:ty); ; ) => {}; // Implements the set of traits common for XOF hashers ( impl_inner: $name:ident($core_ty:ty); XofHasherTraits $($trait_name:ident)*; ) => { $crate::buffer_xof!( impl_inner: $name($core_ty); Debug AlgorithmName Clone Default BlockSizeUser CoreProxy HashMarker Update SerializableState Reset ExtendableOutputReset $($trait_name)* ; ); }; // Implements the set of traits common for XOF readers ( impl_inner: $name:ident($core_ty:ty); XofReaderTraits $($trait_name:ident)*; ) => { $crate::buffer_xof!( impl_inner: $name($core_ty); Debug Clone BlockSizeUser $($trait_name)*;); }; // Implements `Debug` ( impl_inner: $name:ident($core_ty:ty); Debug $($trait_name:ident)*; ) => { impl core::fmt::Debug for $name { #[inline] fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.write_str(concat!(stringify!($name), " { ... }")) } } $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;); }; // Implements `AlgorithmName` ( impl_inner: $name:ident($core_ty:ty); AlgorithmName $($trait_name:ident)*; ) => { impl $crate::common::AlgorithmName for $name { #[inline] fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { <$core_ty as $crate::common::AlgorithmName>::write_alg_name(f) } } $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;); }; // Implements `Default` ( impl_inner: $name:ident($core_ty:ty); Default $($trait_name:ident)*; ) => { impl Default for $name { #[inline] fn default() -> Self { Self { core: Default::default(), buffer: Default::default(), } } } $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;); }; // Implements `CustomizedInit` ( impl_inner: $name:ident($core_ty:ty); CustomizedInit $($trait_name:ident)*; ) => { impl $crate::CustomizedInit for $name { #[inline] fn new_customized(customization: &[u8]) -> Self { Self { core: $crate::CustomizedInit::new_customized(customization), buffer: Default::default(), } } } $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;); }; // Implements `Clone` ( impl_inner: $name:ident($core_ty:ty); Clone $($trait_name:ident)*; ) => { impl Clone for $name { #[inline] fn clone(&self) -> Self { Self { core: Clone::clone(&self.core), buffer: Clone::clone(&self.buffer), } } } $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;); }; // Implements `BlockSizeUser` ( impl_inner: $name:ident($core_ty:ty); BlockSizeUser $($trait_name:ident)*; ) => { impl $crate::block_api::BlockSizeUser for $name { type BlockSize = <$core_ty as $crate::common::BlockSizeUser>::BlockSize; } $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;); }; // Implements `CoreProxy` ( impl_inner: $name:ident($core_ty:ty); CoreProxy $($trait_name:ident)*; ) => { impl $crate::block_api::CoreProxy for $name { type Core = $core_ty; fn compose(core: Self::Core, buffer: $crate::block_api::Buffer) -> Self { Self { core, buffer } } fn decompose(self) -> (Self::Core, $crate::block_api::Buffer) { let Self { core, buffer } = self; (core, buffer) } } $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;); }; // Implements `HashMarker` ( impl_inner: $name:ident($core_ty:ty); HashMarker $($trait_name:ident)*; ) => { impl $crate::HashMarker for $name {} // Verify that `$core_ty` implements `HashMarker` const _: () = { fn check(v: &$core_ty) { v as &dyn $crate::HashMarker; } }; $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;); }; // Implements `Update` ( impl_inner: $name:ident($core_ty:ty); Update $($trait_name:ident)*; ) => { impl $crate::Update for $name { #[inline] fn update(&mut self, data: &[u8]) { let Self { core, buffer } = self; buffer.digest_blocks(data, |blocks| { $crate::block_api::UpdateCore::update_blocks(core, blocks) }); } } $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;); }; // Implements `Reset` ( impl_inner: $name:ident($core_ty:ty); Reset $($trait_name:ident)*; ) => { impl $crate::Reset for $name { #[inline] fn reset(&mut self) { $crate::Reset::reset(&mut self.core); self.buffer.reset(); } } $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;); }; // Implements `ExtendableOutputReset` ( impl_inner: $name:ident($core_ty:ty); ExtendableOutputReset $($trait_name:ident)*; ) => { impl $crate::ExtendableOutputReset for $name { #[inline] fn finalize_xof_reset(&mut self) -> Self::Reader { let Self { core, buffer } = self; let core = <$core_ty as $crate::block_api::ExtendableOutputCore>::finalize_xof_core(core, buffer); $crate::Reset::reset(self); let buffer = Default::default(); Self::Reader { core, buffer } } } $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;); }; // Implements `SerializableState` ( impl_inner: $name:ident($core_ty:ty); SerializableState $($trait_name:ident)*; ) => { impl $crate::common::hazmat::SerializableState for $name { type SerializedStateSize = $crate::typenum::Sum< <$core_ty as $crate::common::hazmat::SerializableState>::SerializedStateSize, $crate::block_buffer::SerializedBufferSize< <$core_ty as $crate::block_api::BlockSizeUser>::BlockSize, <$core_ty as $crate::block_api::BufferKindUser>::BufferKind, > >; #[inline] fn serialize(&self) -> $crate::common::hazmat::SerializedState { let serialized_core = self.core.serialize(); let serialized_buf = self.buffer.serialize(); serialized_core.concat(serialized_buf) } #[inline] fn deserialize( serialized_state: &$crate::common::hazmat::SerializedState, ) -> Result { use $crate::common::hazmat::{SerializableState, DeserializeStateError}; let (serialized_core, serialized_buf) = serialized_state .split_ref::<<$core_ty as SerializableState>::SerializedStateSize>(); let core = SerializableState::deserialize(serialized_core)?; let buffer = $crate::block_buffer::BlockBuffer::deserialize(serialized_buf) .map_err(|_| DeserializeStateError)?; Ok(Self { core, buffer }) } } $crate::buffer_xof!(impl_inner: $name($core_ty); $($trait_name)*;); }; } digest-0.11.3/src/buffer_macros.rs000064400000000000000000000000421046102023000151330ustar 00000000000000mod fixed; mod variable; mod xof; digest-0.11.3/src/dev/fixed.rs000064400000000000000000000037341046102023000142060ustar 00000000000000use crate::{Digest, FixedOutput, FixedOutputReset, HashMarker, dev::TestVector}; /// Fixed-output resettable digest test via the `Digest` trait pub fn fixed_reset_test( &TestVector { input, output }: &TestVector, ) -> Result<(), &'static str> { let mut hasher = D::new(); // Test that it works when accepting the message all at once hasher.update(input); let mut hasher2 = hasher.clone(); if hasher.finalize()[..] != output[..] { return Err("whole message"); } // Test if reset works correctly hasher2.reset(); hasher2.update(input); if hasher2.finalize_reset()[..] != output[..] { return Err("whole message after reset"); } // Test that it works when accepting the message in chunks for n in 1..core::cmp::min(17, input.len()) { let mut hasher = D::new(); for chunk in input.chunks(n) { hasher.update(chunk); hasher2.update(chunk); } if hasher.finalize()[..] != output[..] { return Err("message in chunks"); } if hasher2.finalize_reset()[..] != output[..] { return Err("message in chunks"); } } Ok(()) } /// Variable-output resettable digest test pub fn fixed_test( &TestVector { input, output }: &TestVector, ) -> Result<(), &'static str> { let mut hasher = D::default(); // Test that it works when accepting the message all at once hasher.update(input); if hasher.finalize_fixed()[..] != output[..] { return Err("whole message"); } // Test that it works when accepting the message in chunks for n in 1..core::cmp::min(17, input.len()) { let mut hasher = D::default(); for chunk in input.chunks(n) { hasher.update(chunk); } if hasher.finalize_fixed()[..] != output[..] { return Err("message in chunks"); } } Ok(()) } digest-0.11.3/src/dev/mac.rs000064400000000000000000000120021046102023000136330ustar 00000000000000use crate::{FixedOutputReset, Mac, common::KeyInit}; /// Tag truncation side used in MAC tests #[derive(Clone, Copy, Debug)] pub enum MacTruncSide { /// Tag truncated from left (i.e. `tag[..n]`) Left, /// Tag truncated from right (i.e. `tag[n..]`) Right, /// Tag is not truncated None, } /// MAC test vector #[derive(Debug, Clone, Copy)] pub struct MacTestVector { /// Initialization key pub key: &'static [u8], /// Input message pub input: &'static [u8], /// Output tag pub tag: &'static [u8], } /// Run MAC test pub fn mac_test( &MacTestVector { key, input, tag }: &MacTestVector, trunc_side: MacTruncSide, ) -> Result<(), &'static str> { let Ok(mac0) = ::new_from_slice(key) else { return Err("Failed to initialize MAC instance"); }; initialized_mac_test(mac0, input, tag, trunc_side) } /// Run the MAC test directly on an initialized MAC. /// This is useful for when custom initialization is needed pub fn initialized_mac_test( mac0: M, input: &[u8], tag: &[u8], trunc_side: MacTruncSide, ) -> Result<(), &'static str> { let mut mac = mac0.clone(); mac.update(input); let result = mac.finalize().into_bytes(); let n = tag.len(); let result_bytes = match trunc_side { MacTruncSide::Left => &result[..n], MacTruncSide::Right => &result[result.len() - n..], MacTruncSide::None => &result[..], }; if result_bytes != tag { return Err("whole message"); } // test reading different chunk sizes for chunk_size in 1..core::cmp::min(64, input.len()) { let mut mac = mac0.clone(); for chunk in input.chunks(chunk_size) { mac.update(chunk); } let res = match trunc_side { MacTruncSide::Left => mac.verify_truncated_left(tag), MacTruncSide::Right => mac.verify_truncated_right(tag), MacTruncSide::None => mac.verify_slice(tag), }; if res.is_err() { return Err("chunked message"); } } Ok(()) } /// Run resettable MAC test pub fn reset_mac_test( &MacTestVector { key, input, tag }: &MacTestVector, trunc_side: MacTruncSide, ) -> Result<(), &'static str> { let Ok(mac0) = ::new_from_slice(key) else { return Err("Failed to initialize MAC instance"); }; let mut mac = mac0.clone(); Mac::update(&mut mac, input); let result = mac.finalize_reset().into_bytes(); let n = tag.len(); let result_bytes = match trunc_side { MacTruncSide::Left => &result[..n], MacTruncSide::Right => &result[result.len() - n..], MacTruncSide::None => &result[..], }; if result_bytes != tag { return Err("whole message"); } // test if reset worked correctly Mac::update(&mut mac, input); let res = match trunc_side { MacTruncSide::Left => mac.verify_truncated_left(tag), MacTruncSide::Right => mac.verify_truncated_right(tag), MacTruncSide::None => mac.verify_slice(tag), }; if res.is_err() { return Err("after reset"); } // test reading different chunk sizes for chunk_size in 1..core::cmp::min(64, input.len()) { let mut mac = mac0.clone(); for chunk in input.chunks(chunk_size) { Mac::update(&mut mac, chunk); } let res = match trunc_side { MacTruncSide::Left => mac.verify_truncated_left(tag), MacTruncSide::Right => mac.verify_truncated_right(tag), MacTruncSide::None => mac.verify_slice(tag), }; if res.is_err() { return Err("chunked message"); } } Ok(()) } /// Define MAC test #[macro_export] macro_rules! new_mac_test { ($name:ident, $mac:ty, $test_fn:ident $(,)?) => { digest::new_mac_test!($name, $mac, $test_fn, $crate::dev::MacTruncSide::None); }; ($name:ident, $mac:ty, $test_fn:ident, trunc_left $(,)?) => { digest::new_mac_test!($name, $mac, $test_fn, $crate::dev::MacTruncSide::Left); }; ($name:ident, $mac:ty, $test_fn:ident, trunc_right $(,)?) => { digest::new_mac_test!($name, $mac, $test_fn, $crate::dev::MacTruncSide::Right); }; ($name:ident, $mac:ty, $test_fn:ident, $trunc:expr $(,)?) => { #[test] fn $name() { use digest::dev::MacTestVector; $crate::dev::blobby::parse_into_structs!( include_bytes!(concat!("data/", stringify!($name), ".blb")); static TEST_VECTORS: &[MacTestVector { key, input, tag }]; ); for (i, tv) in TEST_VECTORS.iter().enumerate() { if let Err(reason) = $test_fn::<$mac>(tv, $trunc) { panic!( "\n\ Failed test #{i}\n\ reason:\t{reason:?}\n\ test vector:\t{tv:?}\n" ); } } } }; } digest-0.11.3/src/dev/rng.rs000064400000000000000000000017251046102023000136730ustar 00000000000000//! Xorshift RNG used for tests. Based on the `rand_xorshift` crate. use core::num::Wrapping; /// Initial RNG state used in tests. // chosen by fair dice roll. guaranteed to be random. pub(crate) const RNG: XorShiftRng = XorShiftRng { x: Wrapping(0x0787_3B4A), y: Wrapping(0xFAAB_8FFE), z: Wrapping(0x1745_980F), w: Wrapping(0xB0AD_B4F3), }; /// Xorshift RNG instance pub(crate) struct XorShiftRng { x: Wrapping, y: Wrapping, z: Wrapping, w: Wrapping, } impl XorShiftRng { pub(crate) fn fill(&mut self, buf: &mut [u8; 1024]) { for chunk in buf.chunks_exact_mut(4) { chunk.copy_from_slice(&self.next_u32().to_le_bytes()); } } fn next_u32(&mut self) -> u32 { let x = self.x; let t = x ^ (x << 11); self.x = self.y; self.y = self.z; self.z = self.w; let w = self.w; self.w = w ^ (w >> 19) ^ (t ^ (t >> 8)); self.w.0 } } digest-0.11.3/src/dev/variable.rs000064400000000000000000000047671046102023000147030ustar 00000000000000use crate::{VariableOutput, VariableOutputReset, dev::TestVector}; /// Variable-output resettable digest test pub fn variable_reset_test( &TestVector { input, output }: &TestVector, ) -> Result<(), &'static str> { let mut hasher = D::new(output.len()).unwrap(); let mut buf = [0u8; 128]; let buf = &mut buf[..output.len()]; // Test that it works when accepting the message all at once hasher.update(input); let mut hasher2 = hasher.clone(); hasher.finalize_variable(buf).unwrap(); if buf != output { return Err("whole message"); } buf.iter_mut().for_each(|b| *b = 0); // Test if reset works correctly hasher2.reset(); hasher2.update(input); hasher2.finalize_variable_reset(buf).unwrap(); if buf != output { return Err("whole message after reset"); } buf.iter_mut().for_each(|b| *b = 0); // Test that it works when accepting the message in chunks for n in 1..core::cmp::min(17, input.len()) { let mut hasher = D::new(output.len()).unwrap(); for chunk in input.chunks(n) { hasher.update(chunk); hasher2.update(chunk); } hasher.finalize_variable(buf).unwrap(); if buf != output { return Err("message in chunks"); } buf.iter_mut().for_each(|b| *b = 0); hasher2.finalize_variable_reset(buf).unwrap(); if buf != output { return Err("message in chunks"); } buf.iter_mut().for_each(|b| *b = 0); } Ok(()) } /// Variable-output resettable digest test pub fn variable_test( &TestVector { input, output }: &TestVector, ) -> Result<(), &'static str> { let mut hasher = D::new(output.len()).unwrap(); let mut buf = [0u8; 128]; let buf = &mut buf[..output.len()]; // Test that it works when accepting the message all at once hasher.update(input); hasher.finalize_variable(buf).unwrap(); if buf != output { return Err("whole message"); } buf.iter_mut().for_each(|b| *b = 0); // Test that it works when accepting the message in chunks for n in 1..core::cmp::min(17, input.len()) { let mut hasher = D::new(output.len()).unwrap(); for chunk in input.chunks(n) { hasher.update(chunk); } hasher.finalize_variable(buf).unwrap(); if buf != output { return Err("message in chunks"); } buf.iter_mut().for_each(|b| *b = 0); } Ok(()) } digest-0.11.3/src/dev/xof.rs000064400000000000000000000027461046102023000137050ustar 00000000000000use crate::{ExtendableOutputReset, dev::TestVector}; use core::fmt::Debug; /// Resettable XOF test pub fn xof_reset_test( &TestVector { input, output }: &TestVector, ) -> Result<(), &'static str> { let mut hasher = D::default(); let mut buf = [0u8; 1024]; let buf = &mut buf[..output.len()]; // Test that it works when accepting the message all at once hasher.update(input); let mut hasher2 = hasher.clone(); hasher.finalize_xof_into(buf); if buf != output { return Err("whole message"); } buf.iter_mut().for_each(|b| *b = 0); // Test if reset works correctly hasher2.reset(); hasher2.update(input); hasher2.finalize_xof_reset_into(buf); if buf != output { return Err("whole message after reset"); } buf.iter_mut().for_each(|b| *b = 0); // Test that it works when accepting the message in chunks for n in 1..core::cmp::min(17, input.len()) { let mut hasher = D::default(); for chunk in input.chunks(n) { hasher.update(chunk); hasher2.update(chunk); } hasher.finalize_xof_into(buf); if buf != output { return Err("message in chunks"); } buf.iter_mut().for_each(|b| *b = 0); hasher2.finalize_xof_reset_into(buf); if buf != output { return Err("message in chunks"); } buf.iter_mut().for_each(|b| *b = 0); } Ok(()) } digest-0.11.3/src/dev.rs000064400000000000000000000107731046102023000131100ustar 00000000000000//! Development-related functionality #![allow(clippy::missing_errors_doc)] pub use blobby; mod fixed; #[cfg(feature = "mac")] mod mac; mod rng; mod xof; pub use fixed::*; #[cfg(feature = "mac")] pub use mac::*; pub use xof::*; /// Test vector for hash functions #[derive(Debug, Clone, Copy)] pub struct TestVector { /// Input data pub input: &'static [u8], /// Output hash pub output: &'static [u8], } /// Define hash function test #[macro_export] macro_rules! new_test { ($name:ident, $hasher:ty, $test_fn:ident $(,)?) => { #[test] fn $name() { use $crate::dev::TestVector; $crate::dev::blobby::parse_into_structs!( include_bytes!(concat!("data/", stringify!($name), ".blb")); static TEST_VECTORS: &[TestVector { input, output }]; ); for (i, tv) in TEST_VECTORS.iter().enumerate() { if let Err(reason) = $test_fn::<$hasher>(tv) { panic!( "\n\ Failed test #{i}:\n\ reason:\t{reason}\n\ test vector:\t{tv:?}\n" ); } } } }; } /// Define hash function serialization test #[macro_export] macro_rules! hash_serialization_test { ($name:ident, $hasher:ty $(,)?) => { #[test] fn $name() { use digest::{ Digest, common::{BlockSizeUser, hazmat::SerializableState}, typenum::Unsigned, }; let mut h = <$hasher>::new(); h.update(&[0x13; <$hasher as BlockSizeUser>::BlockSize::USIZE + 1]); let serialized_state = h.serialize(); let expected = include_bytes!(concat!("data/", stringify!($name), ".bin")); assert_eq!(serialized_state.as_slice(), expected); let mut h = <$hasher>::deserialize(&serialized_state).unwrap(); h.update(&[0x13; <$hasher as BlockSizeUser>::BlockSize::USIZE + 1]); let output1 = h.finalize(); let mut h = <$hasher>::new(); h.update(&[0x13; 2 * (<$hasher as BlockSizeUser>::BlockSize::USIZE + 1)]); let output2 = h.finalize(); assert_eq!(output1, output2); } }; } /// Define hash function serialization test #[macro_export] macro_rules! hash_rt_outsize_serialization_test { ($name:ident, $hasher:ty, $expected_serialized_state:expr) => { #[test] fn $name() { use digest::{ Digest, Update, VariableOutput, common::{BlockSizeUser, hazmat::SerializableState}, typenum::Unsigned, }; const HASH_OUTPUT_SIZE: usize = <$hasher>::MAX_OUTPUT_SIZE - 1; let mut h = <$hasher>::new(HASH_OUTPUT_SIZE).unwrap(); h.update(&[0x13; <$hasher as BlockSizeUser>::BlockSize::USIZE + 1]); let serialized_state = h.serialize(); assert_eq!(serialized_state.as_slice(), $expected_serialized_state); let mut h = <$hasher>::deserialize(&serialized_state).unwrap(); h.update(&[0x13; <$hasher as BlockSizeUser>::BlockSize::USIZE + 1]); let mut output1 = [0; HASH_OUTPUT_SIZE]; h.finalize_variable(&mut output1).unwrap(); let mut h = <$hasher>::new(HASH_OUTPUT_SIZE).unwrap(); h.update(&[0x13; 2 * (<$hasher as BlockSizeUser>::BlockSize::USIZE + 1)]); let mut output2 = [0; HASH_OUTPUT_SIZE]; h.finalize_variable(&mut output2).unwrap(); assert_eq!(output1, output2); } }; } /// Define [`Update`][crate::Update] impl benchmark #[macro_export] macro_rules! bench_update { ( $init:expr; $($name:ident $bs:expr;)* ) => { $( #[bench] fn $name(b: &mut Bencher) { let mut d = $init; let data = [0; $bs]; b.iter(|| { digest::Update::update(&mut d, &data[..]); }); b.bytes = $bs; } )* }; } /// Feed ~1 MiB of pseudorandom data to an updatable state. pub fn feed_rand_16mib(d: &mut D) { let buf = &mut [0u8; 1024]; let mut rng = rng::RNG; let n = 16 * (1 << 20) / buf.len(); for _ in 0..n { rng.fill(buf); d.update(buf); // additional byte, so size of fed data // will not be multiple of block size d.update(&[42]); } } digest-0.11.3/src/digest.rs000064400000000000000000000150401046102023000136010ustar 00000000000000use super::{FixedOutput, FixedOutputReset, InvalidBufferSize, Reset, Update}; use common::{Output, OutputSizeUser, typenum::Unsigned}; #[cfg(feature = "alloc")] use alloc::boxed::Box; #[cfg(feature = "oid")] use const_oid::DynAssociatedOid; /// Marker trait for cryptographic hash functions. pub trait HashMarker {} /// Convenience wrapper trait covering functionality of cryptographic hash /// functions with fixed output size. /// /// This trait wraps [`Update`], [`FixedOutput`], [`Default`], and /// [`HashMarker`] traits and provides additional convenience methods. pub trait Digest: OutputSizeUser { /// Create new hasher instance. fn new() -> Self; /// Create new hasher instance which has processed the provided data. fn new_with_prefix(data: impl AsRef<[u8]>) -> Self; /// Process data, updating the internal state. fn update(&mut self, data: impl AsRef<[u8]>); /// Process input data in a chained manner. #[must_use] fn chain_update(self, data: impl AsRef<[u8]>) -> Self; /// Retrieve result and consume hasher instance. fn finalize(self) -> Output; /// Write result into provided array and consume the hasher instance. fn finalize_into(self, out: &mut Output); /// Retrieve result and reset hasher instance. fn finalize_reset(&mut self) -> Output where Self: FixedOutputReset; /// Write result into provided array and reset the hasher instance. fn finalize_into_reset(&mut self, out: &mut Output) where Self: FixedOutputReset; /// Reset hasher instance to its initial state. fn reset(&mut self) where Self: Reset; /// Get output size of the hasher fn output_size() -> usize; /// Compute hash of `data`. fn digest(data: impl AsRef<[u8]>) -> Output; } impl Digest for D { #[inline] fn new() -> Self { Self::default() } #[inline] fn new_with_prefix(data: impl AsRef<[u8]>) -> Self where Self: Default + Sized, { let mut h = Self::default(); h.update(data.as_ref()); h } #[inline] fn update(&mut self, data: impl AsRef<[u8]>) { Update::update(self, data.as_ref()); } #[inline] fn chain_update(mut self, data: impl AsRef<[u8]>) -> Self { Update::update(&mut self, data.as_ref()); self } #[inline] fn finalize(self) -> Output { FixedOutput::finalize_fixed(self) } #[inline] fn finalize_into(self, out: &mut Output) { FixedOutput::finalize_into(self, out); } #[inline] fn finalize_reset(&mut self) -> Output where Self: FixedOutputReset, { FixedOutputReset::finalize_fixed_reset(self) } #[inline] fn finalize_into_reset(&mut self, out: &mut Output) where Self: FixedOutputReset, { FixedOutputReset::finalize_into_reset(self, out); } #[inline] fn reset(&mut self) where Self: Reset, { Reset::reset(self); } #[inline] fn output_size() -> usize { Self::OutputSize::to_usize() } #[inline] fn digest(data: impl AsRef<[u8]>) -> Output { let mut hasher = Self::default(); hasher.update(data.as_ref()); hasher.finalize() } } /// Modification of the [`Digest`] trait suitable for trait objects. pub trait DynDigest { /// Digest input data. /// /// This method can be called repeatedly for use with streaming messages. fn update(&mut self, data: &[u8]); /// Retrieve result and reset hasher instance #[cfg(feature = "alloc")] fn finalize_reset(&mut self) -> Box<[u8]> { let mut result = vec![0; self.output_size()]; self.finalize_into_reset(&mut result).unwrap(); result.into_boxed_slice() } /// Retrieve result and consume boxed hasher instance #[cfg(feature = "alloc")] #[allow(clippy::boxed_local)] #[must_use] fn finalize(mut self: Box) -> Box<[u8]> { let mut result = vec![0; self.output_size()]; self.finalize_into_reset(&mut result).unwrap(); result.into_boxed_slice() } /// Write result into provided array and consume the hasher instance. /// /// # Errors /// If buffer length is not equal to `output_size`. fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize>; /// Write result into provided array and reset the hasher instance. /// /// # Errors /// If buffer length is not equal to `output_size`. fn finalize_into_reset(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize>; /// Reset hasher instance to its initial state. fn reset(&mut self); /// Get output size of the hasher fn output_size(&self) -> usize; /// Clone hasher state into a boxed trait object #[cfg(feature = "alloc")] fn box_clone(&self) -> Box; } impl DynDigest for D { fn update(&mut self, data: &[u8]) { Update::update(self, data); } #[cfg(feature = "alloc")] fn finalize_reset(&mut self) -> Box<[u8]> { FixedOutputReset::finalize_fixed_reset(self) .to_vec() .into_boxed_slice() } #[cfg(feature = "alloc")] fn finalize(self: Box) -> Box<[u8]> { FixedOutput::finalize_fixed(*self) .to_vec() .into_boxed_slice() } fn finalize_into(self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> { buf.try_into() .map_err(|_| InvalidBufferSize) .map(|buf| FixedOutput::finalize_into(self, buf)) } fn finalize_into_reset(&mut self, buf: &mut [u8]) -> Result<(), InvalidBufferSize> { let buf = <&mut Output>::try_from(buf).map_err(|_| InvalidBufferSize)?; FixedOutputReset::finalize_into_reset(self, buf); Ok(()) } fn reset(&mut self) { Reset::reset(self); } fn output_size(&self) -> usize { ::OutputSize::to_usize() } #[cfg(feature = "alloc")] fn box_clone(&self) -> Box { Box::new(self.clone()) } } #[cfg(feature = "alloc")] impl Clone for Box { fn clone(&self) -> Self { self.box_clone() } } /// Convenience wrapper trait around [DynDigest] and [DynAssociatedOid]. #[cfg(feature = "oid")] pub trait DynDigestWithOid: DynDigest + DynAssociatedOid {} #[cfg(feature = "oid")] impl DynDigestWithOid for T {} digest-0.11.3/src/lib.rs000064400000000000000000000210321046102023000130660ustar 00000000000000#![no_std] #![cfg_attr(docsrs, feature(doc_cfg))] #![doc = include_str!("../README.md")] #![forbid(unsafe_code)] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] #![allow(clippy::unwrap_used)] // TODO //! ## Structure //! //! Traits in this crate are organized into the following levels: //! //! - **High-level convenience traits**: [`Digest`], [`DynDigest`], [`Mac`]. //! Wrappers around lower-level traits for most common use-cases. Users should //! usually prefer using these traits. //! - **Mid-level traits**: [`Update`], [`FixedOutput`], [`FixedOutputReset`], [`ExtendableOutput`], //! [`ExtendableOutputReset`], [`XofReader`], [`Reset`], [`KeyInit`], and [`InnerInit`]. //! These traits atomically describe available functionality of an algorithm. //! - **Marker traits**: [`HashMarker`], [`MacMarker`]. Used to distinguish //! different algorithm classes. //! - **Low-level traits** defined in the [`block_api`] module. These traits //! operate at a block-level and do not contain any built-in buffering. //! They are intended to be implemented by low-level algorithm providers only. //! Usually they should not be used in application-level code. //! //! Additionally hash functions implement traits from the standard library: //! [`Default`] and [`Clone`]. //! //! This crate does not provide any implementations of the `io::Read/Write` traits, //! see the [`digest-io`] crate for `std::io`-compatibility wrappers. //! //! [`digest-io`]: https://docs.rs/digest-io #[cfg(feature = "alloc")] #[macro_use] extern crate alloc; #[cfg(feature = "rand_core")] pub use common::rand_core; #[cfg(feature = "zeroize")] pub use zeroize; #[cfg(feature = "alloc")] use alloc::boxed::Box; #[cfg(feature = "dev")] pub mod dev; #[cfg(feature = "block-api")] pub mod block_api; mod buffer_macros; mod digest; #[cfg(feature = "mac")] mod mac; mod xof_fixed; #[cfg(feature = "block-api")] pub use block_buffer; pub use common; #[cfg(feature = "oid")] pub use const_oid; #[cfg(feature = "oid")] pub use crate::digest::DynDigestWithOid; pub use crate::digest::{Digest, DynDigest, HashMarker}; #[cfg(feature = "mac")] pub use common::{InnerInit, InvalidLength, Key, KeyInit}; pub use common::{Output, OutputSizeUser, Reset, array, typenum, typenum::consts}; #[cfg(feature = "mac")] pub use mac::{CtOutput, Mac, MacError, MacMarker}; pub use xof_fixed::XofFixedWrapper; use common::typenum::Unsigned; use core::fmt; /// Types which consume data with byte granularity. pub trait Update { /// Update state using the provided data. fn update(&mut self, data: &[u8]); /// Digest input data in a chained manner. #[must_use] fn chain(mut self, data: impl AsRef<[u8]>) -> Self where Self: Sized, { self.update(data.as_ref()); self } } /// Trait for hash functions with fixed-size output. pub trait FixedOutput: Update + OutputSizeUser + Sized { /// Consume value and write result into provided array. fn finalize_into(self, out: &mut Output); /// Retrieve result and consume the hasher instance. #[inline] fn finalize_fixed(self) -> Output { let mut out = Default::default(); self.finalize_into(&mut out); out } } /// Trait for hash functions with fixed-size output able to reset themselves. pub trait FixedOutputReset: FixedOutput + Reset { /// Write result into provided array and reset the hasher state. fn finalize_into_reset(&mut self, out: &mut Output); /// Retrieve result and reset the hasher state. #[inline] fn finalize_fixed_reset(&mut self) -> Output { let mut out = Default::default(); self.finalize_into_reset(&mut out); out } } /// Trait for reader types which are used to extract extendable output /// from a XOF (extendable-output function) result. pub trait XofReader { /// Read output into the `buffer`. Can be called an unlimited number of times. fn read(&mut self, buffer: &mut [u8]); /// Read output into a boxed slice of the specified size. /// /// Can be called an unlimited number of times in combination with `read`. /// /// `Box<[u8]>` is used instead of `Vec` to save stack space, since /// they have size of 2 and 3 words respectively. #[cfg(feature = "alloc")] fn read_boxed(&mut self, n: usize) -> Box<[u8]> { let mut buf = vec![0u8; n].into_boxed_slice(); self.read(&mut buf); buf } } /// Trait for hash functions with extendable-output (XOF). pub trait ExtendableOutput: Sized + Update { /// Reader type Reader: XofReader; /// Retrieve XOF reader and consume hasher instance. fn finalize_xof(self) -> Self::Reader; /// Finalize XOF and write result into `out`. fn finalize_xof_into(self, out: &mut [u8]) { self.finalize_xof().read(out); } /// Compute hash of `data` and write it into `output`. fn digest_xof(input: impl AsRef<[u8]>, output: &mut [u8]) where Self: Default, { let mut hasher = Self::default(); hasher.update(input.as_ref()); hasher.finalize_xof().read(output); } /// Retrieve result into a boxed slice of the specified size and consume /// the hasher. /// /// `Box<[u8]>` is used instead of `Vec` to save stack space, since /// they have size of 2 and 3 words respectively. #[cfg(feature = "alloc")] fn finalize_boxed(self, output_size: usize) -> Box<[u8]> { let mut buf = vec![0u8; output_size].into_boxed_slice(); self.finalize_xof().read(&mut buf); buf } } /// Trait for hash functions with extendable-output (XOF) able to reset themselves. pub trait ExtendableOutputReset: ExtendableOutput + Reset { /// Retrieve XOF reader and reset hasher instance state. fn finalize_xof_reset(&mut self) -> Self::Reader; /// Finalize XOF, write result into `out`, and reset the hasher state. fn finalize_xof_reset_into(&mut self, out: &mut [u8]) { self.finalize_xof_reset().read(out); } /// Retrieve result into a boxed slice of the specified size and reset /// the hasher state. /// /// `Box<[u8]>` is used instead of `Vec` to save stack space, since /// they have size of 2 and 3 words respectively. #[cfg(feature = "alloc")] fn finalize_boxed_reset(&mut self, output_size: usize) -> Box<[u8]> { let mut buf = vec![0u8; output_size].into_boxed_slice(); self.finalize_xof_reset().read(&mut buf); buf } } /// Trait for hash functions with customization string for domain separation. pub trait CustomizedInit: Sized { /// Create new hasher instance with the given customization string. fn new_customized(customization: &[u8]) -> Self; } /// Trait for hash functions with customization string for domain separation which place /// restrictions on customization strings. pub trait TryCustomizedInit: Sized { /// Error returned for invalid customization strings. type Error; /// Create new hasher instance with the given customization string. /// /// # Errors /// If the provided customization string is not valid for the hash function. fn try_new_customized(customization: &[u8]) -> Result; } impl TryCustomizedInit for T { type Error = core::convert::Infallible; fn try_new_customized(customization: &[u8]) -> Result { Ok(Self::new_customized(customization)) } } /// Types with a certain collision resistance. pub trait CollisionResistance { /// Collision resistance in bytes. /// /// This applies to an output size of at least `2 * CollisionResistance` bytes. /// For a smaller output size collision resistance can be usually calculated as /// `min(CollisionResistance, OutputSize / 2)`. type CollisionResistance: Unsigned; } /// The error type used in variable hash traits. #[derive(Clone, Copy, Debug, Default)] pub struct InvalidOutputSize; impl fmt::Display for InvalidOutputSize { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("invalid output size") } } impl core::error::Error for InvalidOutputSize {} /// Buffer length is not equal to hash output size. #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] pub struct InvalidBufferSize; impl fmt::Display for InvalidBufferSize { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("invalid buffer length") } } impl core::error::Error for InvalidBufferSize {} digest-0.11.3/src/mac.rs000064400000000000000000000165241046102023000130720ustar 00000000000000use crate::{FixedOutput, FixedOutputReset, Update}; use common::{Output, OutputSizeUser, Reset}; use common::typenum::Unsigned; use core::fmt; use ctutils::CtEq; /// Marker trait for Message Authentication algorithms. pub trait MacMarker {} /// Convenience wrapper trait covering functionality of Message Authentication algorithms. /// /// This trait wraps [`Update`], [`FixedOutput`], and [`MacMarker`] traits /// and provides additional convenience methods. pub trait Mac: OutputSizeUser + Sized { /// Update state using the provided data. fn update(&mut self, data: &[u8]); /// Process input data in a chained manner. #[must_use] fn chain_update(self, data: impl AsRef<[u8]>) -> Self; /// Obtain the result of a [`Mac`] computation as a [`CtOutput`] and consume /// [`Mac`] instance. fn finalize(self) -> CtOutput; /// Obtain the result of a [`Mac`] computation as a [`CtOutput`] and reset /// [`Mac`] instance. fn finalize_reset(&mut self) -> CtOutput where Self: FixedOutputReset; /// Reset MAC instance to its initial state. fn reset(&mut self) where Self: Reset; /// Check if tag/code value is correct for the processed input. /// /// # Errors /// Returns [`MacError`] if `tag` is not valid. fn verify(self, tag: &Output) -> Result<(), MacError>; /// Check if tag/code value is correct for the processed input and reset /// [`Mac`] instance. /// /// # Errors /// Returns [`MacError`] if `tag` is not valid. fn verify_reset(&mut self, tag: &Output) -> Result<(), MacError> where Self: FixedOutputReset; /// Check truncated tag correctness using all bytes /// of calculated tag. /// /// # Errors /// Returns [`MacError`] if `tag` is not valid or not equal in length to this MAC's output. fn verify_slice(self, tag: &[u8]) -> Result<(), MacError>; /// Check truncated tag correctness using all bytes /// of calculated tag and reset [`Mac`] instance. /// /// # Errors /// Returns [`MacError`] if `tag` is not valid or not equal in length to MAC's output. fn verify_slice_reset(&mut self, tag: &[u8]) -> Result<(), MacError> where Self: FixedOutputReset; /// Check truncated tag correctness using left side bytes /// (i.e. `tag[..n]`) of calculated tag. /// /// # Errors /// Returns `Error` if `tag` is not valid or empty. fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError>; /// Check truncated tag correctness using right side bytes /// (i.e. `tag[n..]`) of calculated tag. /// /// # Errors /// Returns `Error` if `tag` is not valid or empty. fn verify_truncated_right(self, tag: &[u8]) -> Result<(), MacError>; } impl Mac for T { #[inline] fn update(&mut self, data: &[u8]) { Update::update(self, data); } #[inline] fn chain_update(mut self, data: impl AsRef<[u8]>) -> Self { Update::update(&mut self, data.as_ref()); self } #[inline] fn finalize(self) -> CtOutput { CtOutput::new(self.finalize_fixed()) } #[inline(always)] fn finalize_reset(&mut self) -> CtOutput where Self: FixedOutputReset, { CtOutput::new(self.finalize_fixed_reset()) } #[inline] fn reset(&mut self) where Self: Reset, { Reset::reset(self); } #[inline] fn verify(self, tag: &Output) -> Result<(), MacError> { if self.finalize() == tag.into() { Ok(()) } else { Err(MacError) } } #[inline] fn verify_reset(&mut self, tag: &Output) -> Result<(), MacError> where Self: FixedOutputReset, { if self.finalize_reset() == tag.into() { Ok(()) } else { Err(MacError) } } #[inline] fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> { let n = tag.len(); if n != Self::OutputSize::USIZE { return Err(MacError); } let choice = self.finalize_fixed().as_slice().ct_eq(tag); if choice.into() { Ok(()) } else { Err(MacError) } } #[inline] fn verify_slice_reset(&mut self, tag: &[u8]) -> Result<(), MacError> where Self: FixedOutputReset, { let n = tag.len(); if n != Self::OutputSize::USIZE { return Err(MacError); } let choice = self.finalize_fixed_reset().as_slice().ct_eq(tag); if choice.into() { Ok(()) } else { Err(MacError) } } fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> { let n = tag.len(); if n == 0 || n > Self::OutputSize::USIZE { return Err(MacError); } let choice = self.finalize_fixed()[..n].ct_eq(tag); if choice.into() { Ok(()) } else { Err(MacError) } } fn verify_truncated_right(self, tag: &[u8]) -> Result<(), MacError> { let n = tag.len(); if n == 0 || n > Self::OutputSize::USIZE { return Err(MacError); } let m = Self::OutputSize::USIZE - n; let choice = self.finalize_fixed()[m..].ct_eq(tag); if choice.into() { Ok(()) } else { Err(MacError) } } } /// Fixed size output value which provides a safe [`Eq`] implementation that /// runs in constant time. /// /// It is useful for implementing Message Authentication Codes (MACs). #[derive(Clone)] pub struct CtOutput { bytes: Output, } impl CtOutput { /// Create a new [`CtOutput`] value. #[inline(always)] pub fn new(bytes: Output) -> Self { Self { bytes } } /// Get reference to the inner [`Output`] array this type wraps. #[inline(always)] pub fn as_bytes(&self) -> &Output { &self.bytes } /// Get the inner [`Output`] array this type wraps. #[inline(always)] pub fn into_bytes(&self) -> Output { self.bytes.clone() } } impl From> for CtOutput { #[inline(always)] fn from(bytes: Output) -> Self { Self { bytes } } } impl<'a, T: OutputSizeUser> From<&'a Output> for CtOutput { #[inline(always)] fn from(bytes: &'a Output) -> Self { bytes.clone().into() } } impl PartialEq for CtOutput { #[inline(always)] fn eq(&self, other: &CtOutput) -> bool { self.bytes.ct_eq(&other.bytes).into() } } impl Eq for CtOutput {} impl fmt::Debug for CtOutput { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("CtOutput { ... }") } } impl Drop for CtOutput { #[inline] fn drop(&mut self) { #[cfg(feature = "zeroize")] { use zeroize::Zeroize; self.bytes.zeroize(); } } } #[cfg(feature = "zeroize")] impl zeroize::ZeroizeOnDrop for CtOutput {} /// Error type for when the [`Output`] of a [`Mac`] /// is not equal to the expected value. #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] pub struct MacError; impl fmt::Display for MacError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("MAC tag mismatch") } } impl core::error::Error for MacError {} digest-0.11.3/src/xof_fixed.rs000064400000000000000000000105141046102023000142760ustar 00000000000000use core::fmt; use core::marker::PhantomData; use common::array::ArraySize; use common::hazmat::SerializableState; use common::{BlockSizeUser, KeyInit, KeySizeUser, OutputSizeUser, Reset}; use crate::{ CollisionResistance, CustomizedInit, ExtendableOutput, ExtendableOutputReset, FixedOutput, FixedOutputReset, HashMarker, Update, }; /// Wrapper around [`ExtendableOutput`] types adding [`OutputSizeUser`] with the given size of `S`. pub struct XofFixedWrapper { hash: T, size: PhantomData, } impl Clone for XofFixedWrapper { fn clone(&self) -> Self { Self { hash: self.hash.clone(), size: PhantomData, } } } impl fmt::Debug for XofFixedWrapper { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("XofFixedWrapper") .field("hash", &self.hash) .field("_size", &self.size) .finish() } } impl Default for XofFixedWrapper { fn default() -> Self { Self { hash: Default::default(), size: PhantomData, } } } impl HashMarker for XofFixedWrapper {} #[cfg(feature = "mac")] impl crate::MacMarker for XofFixedWrapper { } impl CollisionResistance for XofFixedWrapper { type CollisionResistance = T::CollisionResistance; } // this blanket impl is needed for HMAC impl BlockSizeUser for XofFixedWrapper { type BlockSize = T::BlockSize; } impl KeySizeUser for XofFixedWrapper { type KeySize = T::KeySize; } impl KeyInit for XofFixedWrapper { fn new(key: &common::Key) -> Self { Self { hash: T::new(key), size: PhantomData, } } } impl Reset for XofFixedWrapper { fn reset(&mut self) { self.hash.reset(); } } impl Update for XofFixedWrapper { fn update(&mut self, data: &[u8]) { self.hash.update(data); } } impl OutputSizeUser for XofFixedWrapper { type OutputSize = S; } impl FixedOutput for XofFixedWrapper { fn finalize_into(self, out: &mut common::Output) { self.hash.finalize_xof_into(out); } } impl FixedOutputReset for XofFixedWrapper { fn finalize_into_reset(&mut self, out: &mut common::Output) { self.hash.finalize_xof_reset_into(out); } } impl ExtendableOutput for XofFixedWrapper { type Reader = T::Reader; fn finalize_xof(self) -> Self::Reader { self.hash.finalize_xof() } } impl ExtendableOutputReset for XofFixedWrapper { fn finalize_xof_reset(&mut self) -> Self::Reader { self.hash.finalize_xof_reset() } } #[cfg(feature = "zeroize")] impl zeroize::ZeroizeOnDrop for XofFixedWrapper { } impl CustomizedInit for XofFixedWrapper { fn new_customized(customization: &[u8]) -> Self { Self { hash: T::new_customized(customization), size: PhantomData, } } } impl SerializableState for XofFixedWrapper { type SerializedStateSize = T::SerializedStateSize; fn serialize(&self) -> common::hazmat::SerializedState { self.hash.serialize() } fn deserialize( serialized_state: &common::hazmat::SerializedState, ) -> Result { T::deserialize(serialized_state).map(|hash| Self { hash, size: PhantomData, }) } } digest-0.11.3/tests/data/fixed_hash_serialization.bin000064400000000000000000000000201046102023000207610ustar 00000000000000digest-0.11.3/tests/dummy_fixed.rs000064400000000000000000000070101046102023000152050ustar 00000000000000//! Tests against a pseudo-hash. #![cfg(feature = "block-api")] mod block_api { use core::fmt; use digest::{ HashMarker, Output, OutputSizeUser, Reset, block_api::{ AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, FixedOutputCore, UpdateCore, }, common::hazmat::{DeserializeStateError, SerializableState, SerializedState}, consts::U8, }; #[cfg(feature = "zeroize")] use zeroize::Zeroize; /// Core of primitive XOR hasher for testing purposes #[derive(Clone, Default, Debug)] pub struct FixedHashCore { state: u64, } impl AlgorithmName for FixedHashCore { fn write_alg_name(f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { f.write_str("FixedHash") } } impl BlockSizeUser for FixedHashCore { type BlockSize = U8; } impl BufferKindUser for FixedHashCore { type BufferKind = block_buffer::Eager; } impl Reset for FixedHashCore { fn reset(&mut self) { self.state = 0; } } impl UpdateCore for FixedHashCore { fn update_blocks(&mut self, blocks: &[Block]) { for block in blocks { self.state ^= u64::from_le_bytes(block.0); } } } impl HashMarker for FixedHashCore {} impl OutputSizeUser for FixedHashCore { type OutputSize = U8; } impl FixedOutputCore for FixedHashCore { fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { let block = buffer.pad_with_zeros(); self.state ^= u64::from_le_bytes(block.0); out.copy_from_slice(&self.state.to_le_bytes()); } } impl SerializableState for FixedHashCore { type SerializedStateSize = U8; fn serialize(&self) -> SerializedState { self.state.to_le_bytes().into() } fn deserialize( serialized_state: &SerializedState, ) -> Result { Ok(Self { state: u64::from_le_bytes(serialized_state.0), }) } } impl Drop for FixedHashCore { fn drop(&mut self) { #[cfg(feature = "zeroize")] self.state.zeroize(); } } #[cfg(feature = "zeroize")] impl zeroize::ZeroizeOnDrop for FixedHashCore {} } digest::buffer_fixed!( /// Primitive XOR hasher for testing purposes pub struct FixedHash(block_api::FixedHashCore); impl: BaseFixedTraits Default Clone HashMarker Reset FixedOutputReset; ); digest::buffer_fixed!( /// Primitive XOR hasher for testing purposes pub struct FixedHashWithSer(block_api::FixedHashCore); impl: FixedHashTraits; ); digest::buffer_fixed!( /// Primitive XOR hasher for testing purposes pub struct FixedHashWithOid(block_api::FixedHashCore); oid: "0.1.2.3.4.5"; impl: BaseFixedTraits Default Clone HashMarker Reset FixedOutputReset; ); digest::buffer_fixed!( /// Primitive XOR hasher for testing purposes pub struct FixedHashWithOidSer(block_api::FixedHashCore); oid: "0.1.2.3.4.5"; impl: FixedHashTraits; ); #[cfg(feature = "dev")] digest::hash_serialization_test!(fixed_hash_serialization, FixedHashWithSer,); #[cfg(feature = "zeroize")] /// check for `ZeroizeOnDrop` implementations const _: () = { const fn check_zeroize() {} check_zeroize::(); check_zeroize::(); };