Skip to main content

Wots

Struct Wots 

Source
pub struct Wots<P: ReferenceProfile> { /* private fields */ }
Expand description

Stateless HashSigsRS WOTS+ reference implementation for profile P.

Wots<LegacyKeccak> and Wots<HashSigsSha256GenericV1> have different key and signature types. The following accidental cross-profile verification is rejected at compile time:

use hashsigs_reference::{
    HashSigsSha256GenericV1, LegacyKeccak, MessageDigest, PublicKey, Signature,
    Wots, CHAIN_COUNT,
};

let key = PublicKey::<LegacyKeccak>::new([0; 32], [0; 32]);
let signature = Signature::<HashSigsSha256GenericV1>::new([[0; 32]; CHAIN_COUNT]);
let message = MessageDigest::new([0; 32]);
Wots::<LegacyKeccak>::new().verify(&key, &message, &signature);

Serialized keys and signatures have no in-band profile tag. A protocol that handles bytes must authenticate Profile::ID separately.

Implementations§

Source§

impl<P: ReferenceProfile> Wots<P>

Source

pub const fn new() -> Self

Constructs a stateless software oracle.

Source

pub const fn profile_id(&self) -> ProfileId

Returns the cryptographic profile implemented by this oracle.

Source

pub fn prf(&self, seed: &HashValue, index: u16) -> HashValue

Applies the HashSigsRS domain-separated PRF.

The exact preimage is 0x03 || seed || u16_be(index), totaling 35 bytes. The two-byte index is big-endian, matching pinned upstream code.

Source

pub fn randomization_masks(&self, public_seed: &HashValue) -> [HashValue; 16]

Derives all randomization masks that can affect a result.

Pinned upstream allocates 67 PRF results. Its function key is mask zero; signing and key generation start every chain at index zero and perform at most 15 transitions; verification starts at a message digit and ends at index 15. Consequently every observable access is in 0..=15, and upstream masks 16 through 66 are provably unreachable. Computing exactly these 16 entries preserves every key, signature, and verification result.

Source

pub fn message_chain_indexes(&self, message: &MessageDigest) -> [u8; 67]

Converts a 32-byte message digest to 64 base-16 digits plus checksum.

Each byte contributes its high nibble followed by its low nibble. The checksum is sum(15 - digit) and is appended as three big-endian base-16 digits, including leading zeroes.

Source

pub fn private_key_from_seed( &self, private_seed: PrivateSeed<P>, ) -> PrivateKey<P>

Derives a one-time private key by hashing a caller-supplied seed once.

The seed is consumed to discourage accidental derivation of the same key for multiple signing calls.

Source

pub fn public_key_from_private_key( &self, private_key: &PrivateKey<P>, ) -> PublicKey<P>

Derives a public key from a one-time private key.

This computes all 67 complete, 15-transition chains and hashes their concatenated endpoints. The private key is borrowed so callers can derive the public key before consuming it in exactly one signing operation.

Source

pub fn generate_key_pair(&self, private_seed: PrivateSeed<P>) -> KeyPair<P>

Generates a public/private WOTS key pair from a one-time seed.

Source

pub fn sign( &self, private_key: PrivateKey<P>, message: &MessageDigest, ) -> Signature<P>

Signs one 32-byte message digest and consumes the one-time private key.

This compatibility-oriented path stops each chain at its message digit, so its amount of hash work depends on the public message. Use Self::sign_and_public_key_from_private_key for the fixed-work fused hardware oracle.

Source

pub fn verify( &self, public_key: &PublicKey<P>, message: &MessageDigest, signature: &Signature<P>, ) -> bool

Verifies a typed signature against a typed public key and message digest.

Profile mismatches are compile-time type errors. The final public-key hash comparison examines every byte before returning.

Source

pub fn verify_bytes( &self, public_key: &[u8], message: &[u8], signature: &[u8], ) -> Result<bool, LengthError>

Parses and verifies untrusted serialized inputs.

Wrong-length message, public-key, or signature values return a LengthError. Correctly sized but corrupted values return Ok(false).

§Errors

Returns LengthError when any input does not have its protocol-defined fixed length.

Source

pub fn sign_and_public_key_from_private_key( &self, private_key: PrivateKey<P>, message: &MessageDigest, ) -> FusedOutput<P>

Signs and derives the public key in one fixed-work traversal.

Every one of the 67 chains is advanced through all 15 transitions. The signature segment is copied when the public message digit is reached, and the final value becomes the public-key endpoint. No message digit can skip a hash operation. The private key is consumed to discourage reuse.

Source

pub fn sign_and_public_key_from_private_seed( &self, private_seed: PrivateSeed<P>, message: &MessageDigest, ) -> FusedOutput<P>

Derives a private key, signs, and derives its public key at fixed work.

The seed is hashed once and then every chain performs all 15 transitions. For LEGACY_KECCAK this costs exactly 1,173 Keccak-f permutations. For HASHSIGS_SHA256_GENERIC_V1 it costs exactly 1,258 SHA-256 compression blocks. See the corresponding constants in hashsigs-types for the full derivations.

Trait Implementations§

Source§

impl<P: Clone + ReferenceProfile> Clone for Wots<P>

Source§

fn clone(&self) -> Wots<P>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<P: Debug + ReferenceProfile> Debug for Wots<P>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<P: ReferenceProfile> Default for Wots<P>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<P: Copy + ReferenceProfile> Copy for Wots<P>

Auto Trait Implementations§

§

impl<P> Freeze for Wots<P>

§

impl<P> RefUnwindSafe for Wots<P>

§

impl<P> Send for Wots<P>

§

impl<P> Sync for Wots<P>

§

impl<P> Unpin for Wots<P>

§

impl<P> UnsafeUnpin for Wots<P>

§

impl<P> UnwindSafe for Wots<P>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.