Crate xcbc_fdh

Source
Expand description

Full Domain Hash

A Full Domain Hash (FDH) is a cryptographic construction that extends the size of a hash digest to an arbitrary length. For example, SHA256 can be expanded to 1024 bits instead of the usual 256 bits.

We construct an FDH by computing a number of cycles where cycles=(target length)/(digest length) + 1. We then compute FDH(M) = HASH(M||0) || HASH(M||1) || ... || HASH(M||cycles−1), where HASH is any hash function, M is the message, || denotes concatenation, and numerical values are single byte u8.

FDHs are usually used with an RSA signature scheme where the target length is the size of the key. See https://en.wikipedia.org/wiki/Full_Domain_Hash

This crate makes extensive use of the digest crate’s cryptograhic hash traits, so most useful methods are implemented as part of digest traits. These traits are re-exported for convenience. See https://github.com/RustCrypto/hashes for a list of compatible hashes.

§Example

use sha2::Sha256;
use fdh::{FullDomainHash, Update, VariableOutput};
   
// Expand SHA256 from 256 bits to 1024 bits.
let output_bits = 1024;
let output_bytes = 1024 / 8;
let mut hasher = FullDomainHash::<Sha256>::new(output_bytes).unwrap();
hasher.update(b"ATTACK AT DAWN");
let result = hasher.finalize_boxed().into_vec();

§no_std

This crate also supports no_std.

#![no_std]
use sha2::Sha256;
use fdh::{FullDomainHash, Update, ExtendableOutput, XofReader};

// Expand SHA256 from 256 bits to 512 bits (and beyond), reading it in 16 byte chunks.
let mut hasher = FullDomainHash::<Sha256>::default();
hasher.update(b"ATTACK AT DAWN");
let mut reader = hasher.finalize_xof();
let mut read_buf = <[u8; 16]>::default();

// Read the first 16 bytes into read_buf
reader.read(&mut read_buf);

// Read the second 16 bytes into read_buf
reader.read(&mut read_buf);

// If we want, we can just keep going, reading as many bits as we want indefinitely.
reader.read(&mut read_buf);
reader.read(&mut read_buf);

§Restricted Domain

This crate also supports getting a digest that is within a specific domain. It follows an algorithim like so:

fn digest_in_domain(message, iv):
   digest = fdh(message, iv)
   while not digest.in_domain():
       iv++
       digest = fdh(message, iv)
   return digest, iv

The method results_in_domain() is provided to accomplish this. The helper methods results_between(), results_lt(), results_gt() are provided for the common case where the digest must be in a certain range.

An example that produces a digest that is odd:

use sha2::Sha512;
use fdh::{FullDomainHash, Update, VariableOutput};
use num_bigint::BigUint;
use num_integer::Integer;

// Get a full domain hash that is odd
let mut hasher = FullDomainHash::<Sha512>::new(64).unwrap();
hasher.update(b"ATTACKATDAWN");

fn digest_is_odd(digest: &[u8]) -> bool {
  BigUint::from_bytes_be(digest).is_odd()
}
let iv = 0;

let (digest, iv) = hasher.results_in_domain(iv, digest_is_odd).unwrap();

Modules§

Structs§

Enums§

Traits§

  • The Digest trait specifies an interface common for digest functions.
  • Trait which describes extendable-output functions (XOF).
  • Trait for resetting hash instances
  • Trait for updating digest state with input data.
  • Trait for returning digest result with the variable size
  • Trait for describing readers which are used to extract extendable output from XOF (extendable-output function) result.