Skip to main content

bouncycastle_core/
traits.rs

1//! Provides simplified abstracted APIs over classes of cryptigraphic primitives, such as Hash, KDF, etc.
2
3use core::marker::Sized;
4use core::fmt::{Debug, Display};
5use crate::errors::{HashError, KDFError, KEMError, MACError, RNGError, SignatureError};
6use crate::key_material::KeyMaterialTrait;
7
8// Imports needed for docs
9#[allow(unused_imports)]
10use crate::key_material::KeyMaterial;
11#[allow(unused_imports)]
12use crate::key_material::KeyType;
13// end of imports needed for docs
14
15pub trait Algorithm {
16    const ALG_NAME: &'static str;
17    const MAX_SECURITY_STRENGTH: SecurityStrength;
18}
19
20pub trait Hash : Default {
21    /// The size of the internal block in bits -- needed by functions such as HMAC to compute security parameters.
22    fn block_bitlen(&self) -> usize;
23
24    /// The size of the output in bytes.
25    fn output_len(&self) -> usize;
26
27    /// A static one-shot API that hashes the provided data.
28    /// `data` can be of any length, including zero bytes.
29    fn hash(self, data: &[u8]) -> Vec<u8>;
30
31    /// A static one-shot API that hashes the provided data into the provided output slice.
32    /// `data` can be of any length, including zero bytes.
33    /// The return value is the number of bytes written.
34    fn hash_out(self, data: &[u8], output: &mut [u8]) -> usize;
35
36    /// Provide a chunk of data to be absorbed into the hashes.
37    /// `data` can be of any length, including zero bytes.
38    /// do_update() is intended to be used as part of a streaming interface, and so may by called multiple times.
39    // fn do_update(&mut self, data: &[u8]) -> Result<(), HashError>;
40    fn do_update(&mut self, data: &[u8]);
41
42    /// Finish absorbing input and produce the hashes output.
43    /// Consumes self, so this must be the final call to this object.
44    // fn do_final(self) -> Result<Vec<u8>, HashError>;
45    fn do_final(self) -> Vec<u8>;
46
47    /// Finish absorbing input and produce the hashes output.
48    /// Consumes self, so this must be the final call to this object.
49    ///
50    /// If the provided buffer is smaller than the hash's output length, the output will be truncated.
51    /// If the provided buffor is larger than the hash's output length, the output  will be placed in
52    /// the first [Hash::output_len] bytes.
53    ///
54    /// The return value is the number of bytes written.
55    fn do_final_out(self, output: &mut [u8]) -> usize;
56
57    /// The same as [Hash::do_final], but allows for supplying a partial byte as the last input.
58    /// Assumes that the input is in the least significant bits (big endian).
59    fn do_final_partial_bits(
60        self,
61        partial_byte: u8,
62        num_partial_bits: usize,
63    ) -> Result<Vec<u8>, HashError>;
64
65    /// The same as [Hash::do_final_out], but allows for supplying a partial byte as the last input.
66    /// Assumes that the input is in the least significant bits (big endian).
67    /// will be placed in the first [Hash::output_len] bytes.
68    /// The return value is the number of bytes written.
69    fn do_final_partial_bits_out(
70        self,
71        partial_byte: u8,
72        num_partial_bits: usize,
73        output: &mut [u8],
74    ) -> Result<usize, HashError>;
75
76    /// Returns the maximum security strength that this KDF is capable of supporting, based on the underlying primitives.
77    fn max_security_strength(&self) -> SecurityStrength;
78}
79
80pub trait HashAlgParams: Algorithm {
81    const OUTPUT_LEN: usize;
82    const BLOCK_LEN: usize;
83}
84
85/// A Key Derivation Function (KDF) is a function that takes in one or more input key and some unstructured
86/// additional input, and uses them to produces a derived key.
87pub trait KDF : Default {
88    /// Implementations of this function are capable of deriving an output key from an input key,
89    /// assuming that they have been properly initialized.
90    ///
91    /// # Entropy Conversion rules
92    /// Implementations SHOULD act on a KeyMaterial of any [KeyType] and will generally
93    /// return a KeyMaterial of the same type
94    ///
95    /// ex.:
96    ///
97    ///   * [KeyType::BytesLowEntropy] -> [KeyType::BytesLowEntropy])
98    ///   * [KeyType::BytesFullEntropy] -> [KeyType::BytesFullEntropy])
99    ///   * [KeyType::SymmetricCipherKey] -> [KeyType::SymmetricCipherKey])
100    ///
101    /// If provided with an input key, even if it is [KeyType::BytesFullEntropy], but that
102    /// contains less key material than the internal block size of the KDF, then the KDF
103    /// will not be considered properly seeded, and the output [KeyMaterial] will be set to
104    /// [KeyType::BytesLowEntropy] -- for example, seeding SHA3-256 with a [KeyMaterial] containing
105    /// only 128 bits of key material.
106    ///
107    /// An implement can, and in most cases SHOULD, return a [HashError] if provided
108    /// with a [KeyMaterial] of type [KeyType::Zeroized].
109    ///
110    /// # Additional Input
111    /// The `additional_input` parameter is used in deriving the key, but is not credited with any entropy,
112    /// and therefore does not affect the type of the output [KeyMaterial].
113    /// This corresponds directly to `FixedInfo` as defined in NIST SP 800-56C.
114    /// The `additional_input` parameter can be empty by passing in `&[0u8; 0]`.
115    ///
116    /// Output length: this function will create a KeyMaterial populated with the default output length
117    /// of the underlying hash primitive.
118    fn derive_key(
119        self,
120        key: &impl KeyMaterialTrait,
121        additional_input: &[u8],
122    ) -> Result<Box<dyn KeyMaterialTrait>, KDFError>;
123
124    /// Same as [KDF::derive_key], but fills the provided output [KeyMaterial].
125    ///
126    /// Output length: this function will behave differently depending on the underlying hash primitive;
127    /// some, such as SHA2 or SHA3 will produce a fixed-length output, while others, such as SHAKE or HKDF,
128    /// will fill the provided KeyMaterial to capacity and require you to truncate it afterwards
129    /// using [KeyMaterialTrait::truncate].
130    fn derive_key_out(
131        self,
132        key: &impl KeyMaterialTrait,
133        additional_input: &[u8],
134        output_key: &mut impl KeyMaterialTrait,
135    ) -> Result<usize, KDFError>;
136
137    /// Meant to be used for hybrid key establishment schemes or other spit-key scenarios where multiple
138    /// keys need to be combined into a single key of the same length.
139    ///
140    /// This function can also be used to mix a KeyMaterial of low entropy with one of full entropy to
141    /// produce a new full entropy key. For the purposes of determining whether enough input key material
142    /// was provided, the lengths of all full-entropy input keys are added together.
143    ///
144    /// Implementations that are not safe to be used as a split-key PRF MAY still implement this function
145    /// and return a result, but SHOULD set the entropy level of the returned key appropriately; for example
146    /// a KDF that is only full-entropy when keyed in the first input SHOULD return a full entropy key
147    /// only if the first input is full entropy.
148    ///
149    /// Implementations can, and in most cases SHOULD, return a [KeyMaterial] of the same type as the
150    /// strongest key, and SHOULD throw a [HashError] if all input keys are zeroized.
151    /// For example output a [KeyType::BytesFullEntropy] key whenever any one of
152    /// the input keys is a [KeyType::BytesFullEntropy] key.
153    /// As another example, combining a [KeyType::BytesLowEntropy] key with a [KeyType::MACKey] key
154    /// should return a [KeyType::MACKey].
155    ///
156    /// Output length: this function will create a KeyMaterial populated with the default output length
157    /// of the underlying hash primitive.
158    fn derive_key_from_multiple(
159        self,
160        keys: &[&impl KeyMaterialTrait],
161        additional_input: &[u8],
162    ) -> Result<Box<dyn KeyMaterialTrait>, KDFError>;
163
164    /// Same as [KDF::derive_key], but fills the provided output [KeyMaterial].
165    ///
166    /// Output length: this function will behave differently depending on the underlying hash primitive;
167    /// some, such as SHA2 or SHA3 will produce a fixed-length output, while others, such as SHAKE or HKDF,
168    /// will fill the provided KeyMaterial to capacity and require you to truncate it afterwards
169    /// by using [KeyMaterialTrait::truncate].
170    fn derive_key_from_multiple_out(
171        self,
172        keys: &[&impl KeyMaterialTrait],
173        additional_input: &[u8],
174        output_key: &mut impl KeyMaterialTrait,
175    ) -> Result<usize, KDFError>;
176
177    /// Returns the maximum security strength that this KDF is capable of supporting, based on the underlying primitives.
178    fn max_security_strength(&self) -> SecurityStrength;
179}
180
181/// A Key Encapsulation Mechanism
182pub trait KEM<
183    PK: KEMPublicKey<PK_LEN>,
184    SK: KEMPrivateKey<SK_LEN>,
185    const PK_LEN: usize,
186    const SK_LEN: usize,
187    const CT_LEN: usize,
188    const SS_LEN: usize,
189>: Sized {
190    /// Generate a keypair.
191    /// Error condition: Basically only on RNG failures
192    fn keygen() -> Result<(PK, SK), KEMError>;
193    
194    /// Performs an encapsulation against the given public key.
195    /// Returns the ciphertext and derived shared secret.
196    fn encaps(pk: &PK) -> Result<(KeyMaterial<SS_LEN>, [u8; CT_LEN]), KEMError>;
197
198    /// Performs a decapsulation of the given ciphertext.
199    /// Returns the derived shared secret.
200    fn decaps(sk: &SK, ct: &[u8]) -> Result<KeyMaterial<SS_LEN>, KEMError>;
201}
202
203// todo: could the public and private key types impl Into<T: AsRef<[u8]>> and From<T: AsRef<[u8]>>
204// todo: that automatically call the encode and from_bytes() ?
205
206/// A public key for a KEM algorithm, often denoted "pk".
207pub trait KEMPublicKey<const PK_LEN: usize> : PartialEq + Eq + Clone + Debug + Display + Sized {
208    /// Write it out to bytes in its standard encoding.
209    fn encode(&self) -> [u8; PK_LEN];
210    /// Write it out to bytes in its standard encoding.
211    fn encode_out(&self, out: &mut [u8; PK_LEN]) -> usize;
212    /// Read it in from bytes in its standard encoding.
213    fn from_bytes(bytes: &[u8]) -> Result<Self, KEMError>;
214}
215
216/// A private key for a KEM algorithm, often denoted "sk" (for "secret key").
217pub trait KEMPrivateKey<const SK_LEN: usize> : PartialEq + Eq + Clone + Secret + Sized {
218    /// Write it out to bytes in its standard encoding.
219    fn encode(&self) -> [u8; SK_LEN];
220    /// Write it out to bytes in its standard encoding.
221    fn encode_out(&self, out: &mut [u8; SK_LEN]) -> usize;
222    /// Read it in from bytes in its standard encoding.
223    fn from_bytes(bytes: &[u8]) -> Result<Self, KEMError>;
224}
225
226
227/// A Message Authentication Code algorithm is a keyed hash function that behaves somewhat like a symmetric signature function.
228/// A MAC algorithm takes in a key and some data, and produces a MAC (message authentication code) that
229/// can be used to verify the integrity of data.
230///
231/// This trait provides one-shot functions [MAC::mac], [MAC::mac_out], and [MAC::verify].
232/// It also provides streaming functions [MAC::do_update], [MAC::do_final], [MAC::do_final_out],
233/// and [MAC::do_verify_final].
234/// The workflow is that a MAC object is initialized with a key with [MAC::new] -- or [MAC::new_allow_weak_key] if you
235/// need to disable the library's safety mechanism to prevent the use of weak keys -- then data is
236/// processed into one or more calls to [MAC::do_update],
237/// after that the object can either create a MAC with [MAC::do_final] or [MAC::do_final_out] (which are final functions, and so consume the object),
238/// or the object can be used to verify a MAC.
239///
240/// For varifying an existing MAC, it is functionally equivalent to use the provided [MAC::verify] and [MAC::do_verify_final]
241/// function or to compute a new MAC and compare it to the existing MAC, however the provided verification functions
242/// use constant-time comparison to avoid cryptographic timing attacks whereby an attacker could learn
243/// the bytes of the MAC value under some conditions. Therefore, it is highly recommended to use the provided verification functions.
244///
245/// Note that the MAC key is not represented in this trait because it is provided to the MAC algorithm
246/// as part of its new functions.
247///
248/// MACs do not implement Default because they do not have a sensible no-args constructor.
249pub trait MAC: Sized {
250    /// Create a new MAC instance with the given key.
251    ///
252    /// This is a common constructor whether creating or verifying a MAC value.
253    ///
254    /// Key / Salt is optional, which is indicated by providing an uninitialized KeyMaterial object of length zero,
255    /// the capacity is irrelevant, so KeyMateriol256::new() or KeyMaterial_internal::<0>::new() would both count as an absent salt.
256    ///
257    /// # Note about the security strength of the provided key:
258    /// If you initialize the MAC with a key that is tagged at a lower [SecurityStrength] than the
259    /// underlying hash function then [MAC::new] will fail with the following error:
260    /// ```text
261    /// MACError::KeyMaterialError(KeyMaterialError::SecurityStrength("HMAC::init(): provided key has a lower security strength than the instantiated HMAC")
262    /// ```
263    /// There are situations in which it is completely reasonable and secure to provide low-entropy
264    /// (and sometimes all-zero) keys / salts; for these cases we have provided [MAC::new_allow_weak_key].
265    fn new(key: &impl KeyMaterialTrait) -> Result<Self, MACError>;
266
267    /// Create a new HMAC instance with the given key.
268    ///
269    /// This constructor completely ignores the [SecurityStrength] tag on the input key and will "just work".
270    /// This should be used if you really do need to use a weak key, such as an all-zero salt,
271    /// but use of this constructor is discouraged and you should really be asking yourself why you need it;
272    /// in most cases it indicates that your key is not long enough to support the security level of this
273    /// HMAC instance, or the key was derived using algorithms at a lower security level, etc.
274    fn new_allow_weak_key(key: &impl KeyMaterialTrait) -> Result<Self, MACError>;
275
276    /// The size of the output in bytes.
277    fn output_len(&self) -> usize;
278
279    /// One-shot API that computes a MAC for the provided data.
280    /// `data` can be of any length, including zero bytes.
281    ///
282    /// Note about the security strength of the provided key:
283    /// If the provided key is tagged at a lower [SecurityStrength] than the instantiated MAC algorithm,
284    /// this will fail with an error:
285    /// ```text
286    /// MACError::KeyMaterialError(KeyMaterialError::SecurityStrength("HMAC::init(): provided key has a lower security strength than the instantiated HMAC")
287    /// ```
288    fn mac(self, data: &[u8]) -> Vec<u8>;
289
290    /// One-shot API that computes a MAC for the provided data and writes it into the provided output slice.
291    /// `data` can be of any length, including zero bytes.
292    ///
293    /// Depending on the underlying MAC implementation, NIST may require that the library enforce
294    /// a minimum length on the mac output value. See documentation for the underlying implementation
295    /// to see conditions under which it throws [MACError::InvalidLength].
296    fn mac_out(self, data: &[u8],out: &mut [u8]) -> Result<usize, MACError>;
297
298    /// One-shot API that verifies a MAC for the provided data.
299    /// `data` can be of any length, including zero bytes.
300    ///
301    /// Internally, this will re-compute the MAC value and then compare it to the provided mac value
302    /// using constant-time comparison. It is highly encouraged to use this utility function instead of
303    /// comparing mac values for equality yourself.
304    ///
305    /// Returns a bool to indicate successful verification of the provided mac value.
306    /// The provided mac value must be an exact match, including length; for example a mac value
307    /// which has been truncated, or which contains extra bytes at the end is considered to not be a match
308    /// and will return false.
309    fn verify(self, data: &[u8], mac: &[u8]) -> bool;
310
311    /// Provide a chunk of data to be absorbed into the MAC.
312    /// `data` can be of any length, including zero bytes.
313    /// do_update() is intended to be used as part of a streaming interface, and so may by called multiple times.
314    fn do_update(&mut self, data: &[u8]);
315
316    fn do_final(self) -> Vec<u8>;
317
318    /// Depending on the underlying MAC implementation, NIST may require that the library enforce
319    /// a minimum length on the mac output value. See documentation for the underlying implementation
320    /// to see conditions under which it throws [MACError::InvalidLength].
321    fn do_final_out(self, out: &mut [u8]) -> Result<usize, MACError>;
322
323    /// Internally, this will re-compute the MAC value and then compare it to the provided mac value
324    /// using constant-time comparison. It is highly encouraged to use this utility function instead of
325    /// comparing mac values for equality yourself.
326    ///
327    /// Returns a bool to indicate successful verification of the provided mac value.
328    /// The provided mac value must be an exact match, including length; for example a mac value
329    /// which has been truncated, or which contains extra bytes at the end is considered to not be a match
330    /// and will return false.
331    fn do_verify_final(self, mac: &[u8]) -> bool;
332
333    /// Returns the maximum security strength that this KDF is capable of supporting, based on the underlying primitives.
334    fn max_security_strength(&self) -> SecurityStrength;
335}
336
337#[derive(Eq, PartialEq, PartialOrd, Clone, Debug)]
338pub enum SecurityStrength {
339    None,
340    _112bit,
341    _128bit,
342    _192bit,
343    _256bit,
344}
345
346impl SecurityStrength {
347    /// Rounds down to the closest supported security strength.
348    /// For example, 120-bits is rounded down to 112-bit.
349    pub fn from_bits(bits: usize) -> Self {
350        if bits < 112 {
351            Self::None
352        } else if bits < 128 {
353            Self::_112bit
354        } else if bits < 192 {
355            Self::_128bit
356        } else if bits < 256 {
357            Self::_192bit
358        } else {
359            Self::_256bit
360        }
361    }
362
363    pub fn from_bytes(bytes: usize) -> Self {
364        Self::from_bits(bytes * 8)
365    }
366
367    pub fn as_int(&self) -> u32 {
368        match self {
369            Self::None => 0,
370            Self::_112bit => 112,
371            Self::_128bit => 128,
372            Self::_192bit => 192,
373            Self::_256bit => 256,
374        }
375    }
376}
377
378/// An interface for random number generation.
379/// This interface is meant to be simpler and more ergonomic than the interfaces provided by the
380/// `rng` crate, but that one should
381/// be used by applications that intend to submit to FIPS certification as it more closely aligns with the
382/// requirements of SP 800-90A.
383/// Note: this interface produces bytes. If you want a [KeyMaterialTrait], then use [KeyMaterial::from_rng].
384pub trait RNG : Default {
385    // TODO: add back once we figure out streaming interaction with entropy sources.
386    // fn add_seed_bytes(&mut self, additional_seed: &[u8]) -> Result<(), RNGError>;
387
388    fn add_seed_keymaterial(&mut self, additional_seed: impl KeyMaterialTrait) -> Result<(), RNGError>;
389    fn next_int(&mut self) -> Result<u32, RNGError>;
390
391    /// Returns the number of requested bytes.
392    fn next_bytes(&mut self, len: usize) -> Result<Vec<u8>, RNGError>;
393
394    /// Returns the number of bytes written.
395    fn next_bytes_out(&mut self, out: &mut [u8]) -> Result<usize, RNGError>;
396
397    fn fill_keymaterial_out(&mut self, out: &mut impl KeyMaterialTrait) -> Result<usize, RNGError>;
398
399    /// Returns the Security Strength of this RNG.
400    fn security_strength(&self) -> SecurityStrength;
401}
402
403/// A trait that forces an object to implement a zeroizing Drop() as well as Debug and Display that
404/// will not log the sensitive contents, even in error or crash-dump scenarios.
405#[allow(drop_bounds)] // Since rust auto-implements Drop, there's a lint that explicitly bounding on Drop is useless.
406                      // I disagree because I want to force things that are secrets to manually implement Drop that zeroizes the data.
407                      // So I'm turning off this lint.
408pub trait Secret : Drop + Debug + Display {}
409
410/// Pre-Hashed Signature is an extension to [Signature] that adds functionality specific to signature
411/// primatives that can operate on a pre-hashed message instead of the full message.
412pub trait PHSignature<
413    PK: SignaturePublicKey<PK_LEN>,
414    SK: SignaturePrivateKey<SK_LEN>,
415    const PK_LEN: usize,
416    const SK_LEN: usize,
417    const SIG_LEN: usize,
418    const PH_LEN: usize>:
419    Signature<PK, SK, PK_LEN, SK_LEN, SIG_LEN>{
420    /// Produce a signature for the provided pre-hashed message and context.
421    ///
422    /// `ctx` accepts a zero-length byte array.
423    ///
424    /// A note about the `ctx` context parameter:
425    /// This is a newer addition to cryptographic signature primitives. It allows for binding the
426    /// signature to some external property of the application so that a signature will fail to validate
427    /// if removed from its intended context.
428    /// This is particularly useful at preventing content confusion attacks between data formats that
429    /// have very similar data structures, for example S/MIME emails, signed PDFs, and signed executables
430    /// that all use the Cryptographic Message Syntax (CMS) data format, or multiple data objects that
431    /// all use the JWS data format.
432    /// To be properly effective, the ctx value must not be under the control of the attacker, which generally
433    /// means that it needs to be a value that is never transmitted over the wire, but rather is something
434    /// known to the application by context.
435    /// For example, "email" vs "pdf" would be a good choice since the application should know what it is
436    /// attempting to sign or verify.
437    /// The `ctx` param can also be used to bind the signed content to a transaction ID or a username,
438    /// but care should be taken to ensure that an attacker attempting a
439    /// content confusion attack not also cause the signed / verifier to use an incorrect transaction ID or username.
440    ///
441    /// Not all signature primitives will support a context value, so you may need to consult the
442    /// documentation for the underlying primitive for how it handles a ctx in that case, for example, it
443    /// might throw an error, ignore the provided ctx value, or append the ctx to the msg in a non-standard way.
444    fn sign_ph(sk: &SK, ph: &[u8; PH_LEN], ctx: Option<&[u8]>) -> Result<[u8; SIG_LEN], SignatureError>;
445    /// Returns the number of bytes written to the output buffer. Can be called with an oversized buffer.
446    fn sign_ph_out(sk: &SK, ph: &[u8; PH_LEN], ctx: Option<&[u8]>, output: &mut [u8; SIG_LEN]) -> Result<usize, SignatureError>;
447    /// On success, returns Ok(())
448    /// On failure, returns Err([SignatureError::SignatureVerificationFailed]); may also return other types of [SignatureError] as appropriate (such as for invalid-length inputs).
449    fn verify_ph(pk: &PK, ph: &[u8; PH_LEN], ctx: Option<&[u8]>, sig: &[u8]) -> Result<(), SignatureError>;
450}
451
452/// A digital signature algorithm is defined as a set of three operations:
453/// key generation, signing, and verification.
454///
455/// To avoid the use of dyn, this trait does not include key generation; you'll have to consult the
456/// documentation for the underlying signature primitive for how to generate a key pair.
457///
458/// This high-level trait defines the operations over a generic signature algorithm that is assumed
459/// to source all its randomness from bouncycastle's default os-backed RNG.
460/// The underlying signature primitives will expose APIs that allow for specifying a specific RNG
461/// or deterministic seed values.
462///
463/// Here we statically-size the arrays used to encode public keys, private keys, and signature values
464/// because this allows us to safely remove runtime checks for array lengths, which overall reduces
465/// the fallibility of the library. This design choice could make this trait complicated to apply
466/// to a signature algorithm that do not have fixed sizes for the encodings of these objects.
467pub trait Signature<
468    PK: SignaturePublicKey<PK_LEN>,
469    SK: SignaturePrivateKey<SK_LEN>,
470    const PK_LEN: usize,
471    const SK_LEN: usize,
472    const SIG_LEN: usize
473>: Sized {
474    /// Generate a keypair.
475    /// Error condition: Basically only on RNG failures
476    fn keygen() -> Result<(PK, SK), SignatureError>;
477
478    /// Produce a signature for the provided message and context.
479    /// Both the `msg` and `ctx` accept zero-length byte arrays.
480    ///
481    /// A note about the `ctx` context parameter:
482    /// This is a newer addition to cryptographic signature primitives. It allows for binding the
483    /// signature to some external property of the application so that a signature will fail to validate
484    /// if removed from its intended context.
485    /// This is particularly useful at preventing content confusion attacks between data formats that
486    /// have very similar data structures, for example S/MIME emails, signed PDFs, and signed executables
487    /// that all use the Cryptographic Message Syntax (CMS) data format, or multiple data objects that
488    /// all use the JWS data format.
489    /// To be properly effective, the ctx value must not be under the control of the attacker, which generally
490    /// means that it needs to be a value that is never transmitted over the wire, but rather is something
491    /// known to the application by context.
492    /// For example, "email" vs "pdf" would be a good choice since the application should know what it is
493    /// attempting to sign or verify.
494    /// The `ctx` param can also be used to bind the signed content to a transaction ID or a username,
495    /// but care should be taken to ensure that an attacker attempting a
496    /// content confusion attack not also cause the signed / verifier to use an incorrect transaction ID or username.
497    ///
498    /// Not all signature primitives will support a context value, so you may need to consult the
499    /// documentation for the underlying primitive for how it handles a ctx in that case, for example, it
500    /// might throw an error, ignore the provided ctx value, or append the ctx to the msg in a non-standard way.
501    fn sign(sk: &SK, msg: &[u8], ctx: Option<&[u8]>) -> Result<[u8; SIG_LEN], SignatureError>;
502
503    /// Returns the number of bytes written to the output buffer. Can be called with an oversized buffer.
504    fn sign_out(sk: &SK, msg: &[u8], ctx: Option<&[u8]>, output: &mut [u8; SIG_LEN]) -> Result<usize, SignatureError>;
505
506    /* streaming signing API */
507    /// Initialize a signer for streaming mode with the provided private key.
508    fn sign_init(sk: &SK, ctx: Option<&[u8]>) -> Result<Self, SignatureError>;
509
510    // todo: make this a AsRef<[u8]> ?
511    /// Update the signer with the next chunk of data.
512    /// This can be called multiple times.
513    fn sign_update(&mut self, msg_chunk: &[u8]);
514
515    /// Complete the signing operation. Consumes self.
516    fn sign_final(self) -> Result<[u8; SIG_LEN], SignatureError>;
517
518    /// Returns the number of bytes written to the output buffer. Can be called with an oversized buffer.
519    fn sign_final_out(self, output: &mut [u8; SIG_LEN]) -> Result<usize, SignatureError>;
520
521    /// On success, returns Ok(())
522    /// On failure, returns Err([SignatureError::SignatureVerificationFailed]); may also return other types of [SignatureError] as appropriate (such as for invalid-length inputs).
523    fn verify(pk: &PK, msg: &[u8], ctx: Option<&[u8]>, sig: &[u8]) -> Result<(), SignatureError>;
524
525    /* streaming verification API */
526    fn verify_init(pk: &PK, ctx: Option<&[u8]>) -> Result<Self, SignatureError>;
527
528    // todo: make this a AsRef<[u8]> ?
529    /// Update the verifier with the next chunk of data.
530    /// This can be called multiple times.
531    fn verify_update(&mut self, msg_chunk: &[u8]);
532
533    /// On success, returns Ok(())
534    /// On failure, returns Err([SignatureError::SignatureVerificationFailed]); may also return other types of [SignatureError] as appropriate (such as for invalid-length inputs).
535    fn verify_final(self, sig: &[u8]) -> Result<(), SignatureError>;
536}
537
538// todo: could the public and private key types impl Into<T: AsRef<[u8]>> and From<T: AsRef<[u8]>>
539// todo: that automatically call the encode and from_bytes() ?
540
541/// A public key for a signature algorithm, often denoted "pk".
542pub trait SignaturePublicKey<const PK_LEN: usize> : PartialEq + Eq + Clone + Debug + Display + Sized {
543    /// Write it out to bytes in its standard encoding.
544    fn encode(&self) -> [u8; PK_LEN];
545    /// Write it out to bytes in its standard encoding.
546    fn encode_out(&self, out: &mut [u8; PK_LEN]) -> usize;
547    /// Read it in from bytes in its standard encoding.
548    fn from_bytes(bytes: &[u8]) -> Result<Self, SignatureError>;
549}
550
551/// A private key for a signature algorithm, often denoted "sk" (for "secret key").
552pub trait SignaturePrivateKey<const SK_LEN: usize> : PartialEq + Eq + Clone + Secret + Sized {
553    /// Write it out to bytes in its standard encoding.
554    fn encode(&self) -> [u8; SK_LEN];
555    /// Write it out to bytes in its standard encoding.
556    fn encode_out(&self, out: &mut [u8; SK_LEN]) -> usize;
557    /// Read it in from bytes in its standard encoding.
558    fn from_bytes(bytes: &[u8]) -> Result<Self, SignatureError>;
559}
560
561
562/// Extensible Output Functions (XOFs) are similar to hash functions, except that they can produce output of arbitrary length.
563/// The naming used for the functions of this trait are borrowed from the SHA3-style sponge constructions that split XOF operation
564/// into two phases: an absorb phase in which an arbitrary amount of input is provided to the XOF,
565/// and then a squeeze phase in which an arbitrary amount of output is extracted.
566/// Once squeezing begins, no more input can be absorbed.
567///
568/// XOFs are _similar to_ hash functions, but are not hash functions for one technical but important reason:
569/// since the amount of output to produce is not provided to the XOF in advance, it cannot be used to
570/// diversify the XOF output streams.
571/// In other words, the overlapping parts of their outputs will be the same!
572/// For example, consider two XOFs that absorb the same input data, one that is squeezed to produce 32 bytes,
573/// and the other to produce 1 kb; both outputs will be identical in their first 32 bytes.
574/// This could lead to loss of security in a number of ways, for example distinguishing attacks where
575/// it is sufficient for the attacker to know that two values came from the same input, even if the
576/// attacker cannot learn what that input was. This is attack is often sufficient, for example,
577/// to break anonymity-preserving technology.
578/// Applications that require the arbitrary-length output of an XOF, but also care about these
579/// distinguishing attacks should consider adding a cryptographic salt to diversify the inputs.
580pub trait XOF : Default {
581    /// A static one-shot API that digests the input data and produces `result_len` bytes of output.
582    fn hash_xof(self, data: &[u8], result_len: usize) -> Vec<u8>;
583
584    /// A static one-shot API that digests the input data and produces `result_len` bytes of output.
585    /// Fills the provided output slice.
586    fn hash_xof_out(self, data: &[u8], output: &mut [u8]) -> usize;
587
588    fn absorb(&mut self, data: &[u8]);
589
590    /// Switches to squeezing.
591    fn absorb_last_partial_byte(
592        &mut self,
593        partial_byte: u8,
594        num_partial_bits: usize,
595    ) -> Result<(), HashError>;
596
597    /// Can be called multiple times.
598    fn squeeze(&mut self, num_bytes: usize) -> Vec<u8>;
599
600    /// Can be called multiple times.
601    /// Fills the provided output slice.
602    fn squeeze_out(&mut self, output: &mut [u8]) -> usize;
603
604    /// Squeezes a partial byte from the XOF.
605    /// Output will be in the top `num_bits` bits of the returned u8 (ie Big Endian).
606    /// This is a final call and consumes self.
607    fn squeeze_partial_byte_final(self, num_bits: usize) -> Result<u8, HashError>;
608
609    fn squeeze_partial_byte_final_out(
610        self,
611        num_bits: usize,
612        output: &mut u8,
613    ) -> Result<(), HashError>;
614
615    /// Returns the maximum security strength that this KDF is capable of supporting, based on the underlying primitives.
616    fn max_security_strength(&self) -> SecurityStrength;
617}