std/_wasm_crypto/src/digest.rs

Deno standard library
Go to Latest
File
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.use digest::{ BlockInput, Digest, DynDigest, ExtendableOutput, Reset, Update, VariableOutput,};
/// Enum wrapper over all supported digest implementations.#[derive(Clone)]pub enum Context { Blake2b(Box<blake2::Blake2b>), Blake2b256(Box<blake2::VarBlake2b>), Blake2b384(Box<blake2::VarBlake2b>), Blake2s(Box<blake2::Blake2s>), Blake3(Box<blake3::Hasher>), Keccak224(Box<sha3::Keccak224>), Keccak256(Box<sha3::Keccak256>), Keccak384(Box<sha3::Keccak384>), Keccak512(Box<sha3::Keccak512>), Md5(Box<md5::Md5>), Ripemd160(Box<ripemd160::Ripemd160>), Sha1(Box<sha1::Sha1>), Sha3_224(Box<sha3::Sha3_224>), Sha3_256(Box<sha3::Sha3_256>), Sha3_384(Box<sha3::Sha3_384>), Sha3_512(Box<sha3::Sha3_512>), Sha224(Box<sha2::Sha224>), Sha256(Box<sha2::Sha256>), Sha384(Box<sha2::Sha384>), Sha512(Box<sha2::Sha512>), Shake128(Box<sha3::Shake128>), Shake256(Box<sha3::Shake256>),}
use Context::*;
impl Context { pub fn new(algorithm_name: &str) -> Result<Context, &'static str> { Ok(match algorithm_name { "BLAKE2B" => Blake2b(Default::default()), "BLAKE2B-256" => { Blake2b256(Box::new(blake2::VarBlake2b::new(256 / 8).unwrap())) } "BLAKE2B-384" => { Blake2b384(Box::new(blake2::VarBlake2b::new(384 / 8).unwrap())) } "BLAKE2S" => Blake2s(Default::default()), "BLAKE3" => Blake3(Default::default()), "KECCAK-224" => Keccak224(Default::default()), "KECCAK-256" => Keccak256(Default::default()), "KECCAK-384" => Keccak384(Default::default()), "KECCAK-512" => Keccak512(Default::default()), "MD5" => Md5(Default::default()), "RIPEMD-160" => Ripemd160(Default::default()), "SHA-1" => Sha1(Default::default()), "SHA3-224" => Sha3_224(Default::default()), "SHA3-256" => Sha3_256(Default::default()), "SHA3-384" => Sha3_384(Default::default()), "SHA3-512" => Sha3_512(Default::default()), "SHA-224" => Sha224(Default::default()), "SHA-256" => Sha256(Default::default()), "SHA-384" => Sha384(Default::default()), "SHA-512" => Sha512(Default::default()), "SHAKE128" => Shake128(Default::default()), "SHAKE256" => Shake256(Default::default()), _ => return Err("unsupported algorithm"), }) }
/// The input block length for the algorithm, in bytes. pub fn input_block_length(&self) -> usize { // For algorithm types that implement BlockInput and have a statically // available BlockSize as part of their type definition, we use that value. fn static_block_length<T: BlockInput>(_: &T) -> usize { <T::BlockSize as typenum::Unsigned>::to_usize() }
match self { Blake2b(context) => static_block_length(&**context), Blake2b256(context) => static_block_length(&**context), Blake2b384(context) => static_block_length(&**context), Blake2s(context) => static_block_length(&**context), Blake3(context) => static_block_length(&**context), Keccak224(context) => static_block_length(&**context), Keccak256(context) => static_block_length(&**context), Keccak384(context) => static_block_length(&**context), Keccak512(context) => static_block_length(&**context), Md5(context) => static_block_length(&**context), Ripemd160(context) => static_block_length(&**context), Sha1(context) => static_block_length(&**context), Sha3_224(context) => static_block_length(&**context), Sha3_256(context) => static_block_length(&**context), Sha3_384(context) => static_block_length(&**context), Sha3_512(context) => static_block_length(&**context), Sha224(context) => static_block_length(&**context), Sha256(context) => static_block_length(&**context), Sha384(context) => static_block_length(&**context), Sha512(context) => static_block_length(&**context),
// https://doi.org/10.6028/NIST.FIPS.202 specifies that: // - In general, the input block size (in bits) of a sponge function is // its rate. // - SPONGE[f, pad, r] = The sponge function in which the underlying // function is f, the padding rule is pad, and the rate is r. // - KECCAK[c] = SPONGE[KECCAK-p[1600, 24], pad10*1, 1600–c] // - SHAKE128(M, d) = KECCAK[256] (M || 1111, d) Shake128(_) => 168, // implying a rate of (1600 - 256) bits = 168 bytes // - SHAKE256(M, d) = KECCAK[512] (M || 1111, d). Shake256(_) => 136, // implying a rate of (1600 - 512) bits = 136 bytes } }
/// The output digest length for the algorithm, in bytes. /// /// If the algorithm is variable-length, this returns its default length. pub fn output_length(&self) -> usize { match self { Blake2b(context) => context.output_size(), Blake2b256(context) => context.output_size(), Blake2b384(context) => context.output_size(), Blake2s(context) => context.output_size(), Blake3(context) => context.output_size(), Keccak224(context) => context.output_size(), Keccak256(context) => context.output_size(), Keccak384(context) => context.output_size(), Keccak512(context) => context.output_size(), Md5(context) => context.output_size(), Ripemd160(context) => context.output_size(), Sha1(context) => context.output_size(), Sha3_224(context) => context.output_size(), Sha3_256(context) => context.output_size(), Sha3_384(context) => context.output_size(), Sha3_512(context) => context.output_size(), Sha224(context) => context.output_size(), Sha256(context) => context.output_size(), Sha384(context) => context.output_size(), Sha512(context) => context.output_size(),
// https://doi.org/10.6028/NIST.FIPS.202's Table 4 indicates that in order // to reach the target security strength for these algorithms, the output // size (in bits) needs to be (at least) two times larger than that // security strength (in bits). Shake128(_) => 32, // implying a length of (2 * 128) bits = 32 bytes Shake256(_) => 64, // implying a length of (2 * 256) bits = 64 bytes } }
/// Whether the algorithm has an extendable variable-length digest output /// (whether it is an "XOF"). pub const fn extendable(&self) -> bool { matches!(self, Blake3(_) | Shake128(_) | Shake256(_)) }
/// The name of the algorithm used by this context. /// /// Names are all uppercase (for ease of case-insensitive comparisons) and /// will match the name formatting used in WebCrypto if the algorithm is /// supported by WebCrypto, and otherwise match the formatting used in the /// official specification for the algorithm. pub const fn algorithm_name(&self) -> &'static str { match self { Blake2b(_) => "BLAKE2B", Blake2b256(_) => "BLAKE2B-256", Blake2b384(_) => "BLAKE2B-384", Blake2s(_) => "BLAKE2S", Blake3(_) => "BLAKE3", Keccak224(_) => "KECCAK-224", Keccak256(_) => "KECCAK-256", Keccak384(_) => "KECCAK-384", Keccak512(_) => "KECCAK-512", Md5(_) => "MD5", Ripemd160(_) => "RIPEMD-160", Sha1(_) => "SHA-1", Sha3_224(_) => "SHA3-224", Sha3_256(_) => "SHA3-256", Sha3_384(_) => "SHA3-384", Sha3_512(_) => "SHA3-512", Sha224(_) => "SHA-224", Sha256(_) => "SHA-256", Sha384(_) => "SHA-384", Sha512(_) => "SHA-512", Shake128(_) => "SHAKE128", Shake256(_) => "SHAKE256", } }
pub fn reset(&mut self) { match self { Blake2b(context) => Reset::reset(&mut **context), Blake2b256(context) => Reset::reset(&mut **context), Blake2b384(context) => Reset::reset(&mut **context), Blake2s(context) => Reset::reset(&mut **context), Blake3(context) => Reset::reset(&mut **context), Keccak224(context) => Reset::reset(&mut **context), Keccak256(context) => Reset::reset(&mut **context), Keccak384(context) => Reset::reset(&mut **context), Keccak512(context) => Reset::reset(&mut **context), Md5(context) => Reset::reset(&mut **context), Ripemd160(context) => Reset::reset(&mut **context), Sha1(context) => Reset::reset(&mut **context), Sha3_224(context) => Reset::reset(&mut **context), Sha3_256(context) => Reset::reset(&mut **context), Sha3_384(context) => Reset::reset(&mut **context), Sha3_512(context) => Reset::reset(&mut **context), Sha224(context) => Reset::reset(&mut **context), Sha256(context) => Reset::reset(&mut **context), Sha384(context) => Reset::reset(&mut **context), Sha512(context) => Reset::reset(&mut **context), Shake128(context) => Reset::reset(&mut **context), Shake256(context) => Reset::reset(&mut **context), }; }
pub fn update(&mut self, data: &[u8]) { match self { Blake2b(context) => Digest::update(&mut **context, data), Blake2b256(context) => (&mut **context).update(data), Blake2b384(context) => (&mut **context).update(data), Blake2s(context) => Digest::update(&mut **context, data), Blake3(context) => Digest::update(&mut **context, data), Keccak224(context) => Digest::update(&mut **context, data), Keccak256(context) => Digest::update(&mut **context, data), Keccak384(context) => Digest::update(&mut **context, data), Keccak512(context) => Digest::update(&mut **context, data), Md5(context) => Digest::update(&mut **context, data), Ripemd160(context) => Digest::update(&mut **context, data), Sha1(context) => Digest::update(&mut **context, data), Sha3_224(context) => Digest::update(&mut **context, data), Sha3_256(context) => Digest::update(&mut **context, data), Sha3_384(context) => Digest::update(&mut **context, data), Sha3_512(context) => Digest::update(&mut **context, data), Sha224(context) => Digest::update(&mut **context, data), Sha256(context) => Digest::update(&mut **context, data), Sha384(context) => Digest::update(&mut **context, data), Sha512(context) => Digest::update(&mut **context, data), Shake128(context) => (&mut **context).update(data), Shake256(context) => (&mut **context).update(data), }; }
pub fn digest_and_drop( self, length: Option<usize>, ) -> Result<Box<[u8]>, &'static str> { if let Some(length) = length { if !self.extendable() && length != self.output_length() { return Err( "non-default length specified for non-extendable algorithm", ); } }
let length = length.unwrap_or_else(|| self.output_length());
Ok(match self { Blake2b(context) => context.finalize(), Blake2b256(context) => context.finalize_boxed(), Blake2b384(context) => context.finalize_boxed(), Blake2s(context) => context.finalize(), Blake3(context) => context.finalize_boxed(length), Keccak224(context) => context.finalize(), Keccak256(context) => context.finalize(), Keccak384(context) => context.finalize(), Keccak512(context) => context.finalize(), Md5(context) => context.finalize(), Ripemd160(context) => context.finalize(), Sha1(context) => context.finalize(), Sha3_224(context) => context.finalize(), Sha3_256(context) => context.finalize(), Sha3_384(context) => context.finalize(), Sha3_512(context) => context.finalize(), Sha224(context) => context.finalize(), Sha256(context) => context.finalize(), Sha384(context) => context.finalize(), Sha512(context) => context.finalize(), Shake128(context) => context.finalize_boxed(length), Shake256(context) => context.finalize_boxed(length), }) }
pub fn digest_and_reset( &mut self, length: Option<usize>, ) -> Result<Box<[u8]>, &'static str> { if let Some(length) = length { if !self.extendable() && length != self.output_length() { return Err( "non-default length specified for non-extendable algorithm", ); } }
let length = length.unwrap_or_else(|| self.output_length()); Ok(match self { Blake2b(context) => DynDigest::finalize_reset(context.as_mut()), Blake2b256(context) => context.finalize_boxed_reset(), Blake2b384(context) => context.finalize_boxed_reset(), Blake2s(context) => DynDigest::finalize_reset(context.as_mut()), Blake3(context) => context.finalize_boxed_reset(length), Keccak224(context) => DynDigest::finalize_reset(context.as_mut()), Keccak256(context) => DynDigest::finalize_reset(context.as_mut()), Keccak384(context) => DynDigest::finalize_reset(context.as_mut()), Keccak512(context) => DynDigest::finalize_reset(context.as_mut()), Md5(context) => DynDigest::finalize_reset(context.as_mut()), Ripemd160(context) => DynDigest::finalize_reset(context.as_mut()), Sha1(context) => DynDigest::finalize_reset(context.as_mut()), Sha3_224(context) => DynDigest::finalize_reset(context.as_mut()), Sha3_256(context) => DynDigest::finalize_reset(context.as_mut()), Sha3_384(context) => DynDigest::finalize_reset(context.as_mut()), Sha3_512(context) => DynDigest::finalize_reset(context.as_mut()), Sha224(context) => DynDigest::finalize_reset(context.as_mut()), Sha256(context) => DynDigest::finalize_reset(context.as_mut()), Sha384(context) => DynDigest::finalize_reset(context.as_mut()), Sha512(context) => DynDigest::finalize_reset(context.as_mut()), Shake128(context) => context.finalize_boxed_reset(length), Shake256(context) => context.finalize_boxed_reset(length), }) }
pub fn digest( &self, length: Option<usize>, ) -> Result<Box<[u8]>, &'static str> { self.clone().digest_and_drop(length) }}