fog_crypto/
identity.rs

1//! Cryptographic signatures.
2//!
3//! This module lets you create a signing [`IdentityKey`], which can be used to create a
4//! [`Signature`] for a given [`Hash`](crate::hash::Hash). Each `IdentityKey` has an associated
5//! [`Identity`], which may be freely shared. A `Signature` may be provided separate from the data
6//! or alongside it, and always includes the `Identity` of the signer.
7//!
8//! All `IdentityKey` structs are backed by some struct that implements the [`SignInterface`] trait;
9//! this can be an in-memory private key, an interface to an OS-managed keystore, an interface to a
10//! hardware security module, or something else.
11//!
12//! # Example
13//!
14//! ```
15//! # use fog_crypto::identity::*;
16//! # use fog_crypto::hash::Hash;
17//! # use std::convert::TryFrom;
18//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
19//!
20//! // Make a new temporary key
21//! let key = IdentityKey::new();
22//!
23//! println!("Identity(Base58): {}", key.id());
24//!
25//! // Sign some data
26//! let hash = Hash::new(b"I am data, soon to be hashed");
27//! let signature = key.sign(&hash);
28//!
29//! // Encode the signature
30//! let mut encoded = Vec::new();
31//! signature.encode_vec(&mut encoded);
32//!
33//! // Decode the signature and verify it
34//! let unverified = UnverifiedSignature::try_from(&encoded[..])?;
35//! match unverified.verify(&hash) {
36//!     Ok(verified) => {
37//!         println!("Got valid signature, signed by {}", verified.signer());
38//!     },
39//!     Err(_) => {
40//!         println!("Signature failed validation");
41//!     }
42//! }
43//! # Ok(())
44//! # }
45//! ```
46//!
47//! # Algorithms
48//!
49//! The current (and only) algorithm for public-key signatures is Ed25519 with [strict
50//! verification][StrictVerification]. The private key is handled by an [`IdentityKey`], while the
51//! public key is available as an [`Identity`].
52//!
53//! [StrictVerification]: https://docs.rs/ed25519-dalek/2.0.0/ed25519_dalek/struct.VerifyingKey.html#method.verify_strict
54//!
55//! # Format
56//!
57//! An [`Identity`] is encoded as a version byte followed by the contained public key, whose length
58//! may be dependant on the version. For Ed25519, it is 32 bytes (plus the version byte).
59//!
60//! An [`IdentityKey`] is encoded as a version byte followed by the contained private key, whose
61//! length may be dependant on the version. For Ed25519, it is 32 bytes (plus the version byte).
62//! This encoding is only ever used for the payload of an [`IdentityLockbox`].
63//!
64//! A [`Signature`] is encoded as the version of hash that was signed, the `Identity` of the
65//! signer, and finally the actual signature bytes. The length of the signature is dependant on the
66//! version of `IdentityKey` (and thus `Identity`) that was used to make the signature. For
67//! Ed25519, it is 64 bytes.
68//!
69//! ```text
70//! +--------------+==========+===========+
71//! | Hash Version | Identity | Signature |
72//! +--------------+==========+===========+
73//!
74//! - Hash Version (1 byte)
75//! - Identity: Variable, depends on Identity version
76//! - Signature: Variable, depends on Identity version
77//! ```
78
79use ed25519_dalek::Signer;
80
81use crate::{
82    hash::{Hash, MAX_HASH_VERSION, MIN_HASH_VERSION},
83    lock::LockId,
84    lockbox::*,
85    stream::StreamKey,
86    CryptoError, CryptoSrc,
87};
88
89use rand_core::{CryptoRng, RngCore};
90
91use zeroize::Zeroize;
92
93use std::{convert::TryFrom, fmt, sync::Arc};
94
95/// Default signature algorithm version.
96pub const DEFAULT_SIGN_VERSION: u8 = 1;
97
98/// Minimum accepted signature algorithm version.
99pub const MIN_SIGN_VERSION: u8 = 1;
100
101/// Maximum accepted signature algorithm version.
102pub const MAX_SIGN_VERSION: u8 = 1;
103
104const V1_IDENTITY_KEY_SIZE: usize = ed25519_dalek::SECRET_KEY_LENGTH;
105const V1_IDENTITY_ID_SIZE: usize = ed25519_dalek::PUBLIC_KEY_LENGTH;
106const V1_IDENTITY_SIGN_SIZE: usize = ed25519_dalek::SIGNATURE_LENGTH;
107
108/// Identity Key that allows signing hashes as a given Identity.
109///
110/// This acts as a wrapper for a specific cryptographic private key, and it is only be used for a
111/// specific corresponding signature algorithm. The underlying private key may be located in a
112/// hardware module or some other private keystore; in this case, it may be impossible to export
113/// the key.
114///
115/// # Example
116///
117/// ```
118/// # use fog_crypto::identity::*;
119/// # use fog_crypto::hash::Hash;
120/// # use std::convert::TryFrom;
121///
122/// // Make a new temporary key
123/// let key = IdentityKey::new();
124///
125/// // Sign some data with it
126/// let hash = Hash::new(b"I am data, about to be signed");
127/// let signature = key.sign(&hash);
128///
129/// ```
130#[derive(Clone)]
131pub struct IdentityKey {
132    /// The interface to the actual private key for signing. We wrap it in a Arc to avoid having it
133    /// in more than one place in memory. Yes, that fact doesn't matter for keys located on hardware
134    /// or in the OS, but it's a property that some crypto libraries (namely ed25519_dalek) want to
135    /// encourage.
136    interface: Arc<dyn SignInterface>,
137}
138
139#[cfg(feature = "getrandom")]
140impl Default for IdentityKey {
141    fn default() -> Self {
142        Self::new()
143    }
144}
145
146impl IdentityKey {
147
148    /// Create a new `IdentityKey`, given a wrapped object that can implement a
149    /// SignInterface.
150    pub fn from_interface(interface: Arc<dyn SignInterface>) -> IdentityKey {
151    IdentityKey { interface } }
152
153    /// Generate a temporary `IdentityKey` that exists in program memory.
154    #[cfg(feature = "getrandom")]
155    pub fn new() -> IdentityKey {
156        let interface = Arc::new(BareIdKey::new());
157        Self::from_interface(interface)
158    }
159
160    /// Generate a temporary `IdentityKey` that exists in program memory, using
161    /// the provided cryptographic RNG.
162    pub fn with_rng<R>(csprng: &mut R) -> IdentityKey
163    where
164        R: rand_core::CryptoRng + rand_core::RngCore,
165    {
166        let interface = Arc::new(BareIdKey::with_rng(csprng));
167        Self::from_interface(interface)
168    }
169
170    /// Generate a temporary `IdentityKey` that exists in program memory. Uses the specified
171    /// version instead of the default, and fails if the version is unsupported.
172    pub fn with_rng_and_version<R>(csprng: &mut R, version: u8) -> Result<IdentityKey, CryptoError>
173    where
174        R: rand_core::CryptoRng + rand_core::RngCore,
175    {
176        let interface = Arc::new(BareIdKey::with_rng_and_version(csprng, version)?);
177        Ok(Self::from_interface(interface))
178    }
179
180    /// Get the signature algorithm version used by this key.
181    pub fn version(&self) -> u8 {
182        self.id().version()
183    }
184
185    /// Get the associated [`Identity`] for this key.
186    pub fn id(&self) -> &Identity {
187        self.interface.id()
188    }
189
190    /// Sign a hash. Signing should be fast and always succeed.
191    pub fn sign(&self, hash: &Hash) -> Signature {
192        self.interface.sign(hash)
193    }
194
195    /// The maximum expected size of a signature from this key
196    pub fn max_signature_size(&self) -> usize {
197        // this comes straight from the Signature code
198        1 + V1_IDENTITY_SIGN_SIZE + self.id().size()
199    }
200
201    #[cfg(feature = "getrandom")]
202    /// Pack this key into a `Lockbox`, meant for the recipient specified by `lock`. Returns None if
203    /// this key cannot be exported.
204    pub fn export_for_lock(
205        &self,
206        lock: &LockId,
207    ) -> Option<IdentityLockbox> {
208        self.interface.self_export_lock(&mut rand_core::OsRng, lock)
209    }
210
211    /// Pack this key into a `Lockbox`, meant for the recipient specified by `lock`. Returns None if
212    /// this key cannot be exported.
213    pub fn export_for_lock_with_rng<R: CryptoRng + RngCore>(
214        &self,
215        csprng: &mut R,
216        lock: &LockId,
217    ) -> Option<IdentityLockbox> {
218        self.interface.self_export_lock(csprng, lock)
219    }
220
221    #[cfg(feature = "getrandom")]
222    /// Pack this key into a `Lockbox`, meant for the recipient specified by `stream`. Returns None
223    /// if this key cannot be exported.
224    pub fn export_for_stream(
225        &self,
226        stream: &StreamKey,
227    ) -> Option<IdentityLockbox> {
228        self.interface.self_export_stream(&mut rand_core::OsRng, stream)
229    }
230
231    /// Pack this key into a `Lockbox`, meant for the recipient specified by `stream`. Returns None
232    /// if this key cannot be exported.
233    pub fn export_for_stream_with_rng<R: CryptoRng + RngCore>(
234        &self,
235        csprng: &mut R,
236        stream: &StreamKey,
237    ) -> Option<IdentityLockbox> {
238        self.interface.self_export_stream(csprng, stream)
239    }
240}
241
242impl fmt::Display for IdentityKey {
243    /// Display just the Identity (never the underlying key).
244    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
245        fmt::Display::fmt(self.id(), f)
246    }
247}
248
249impl fmt::Debug for IdentityKey {
250    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
251        f.debug_struct("IdentityKey")
252            .field("version", &self.version())
253            .field("public_key", &self.id().raw_public_key())
254            .finish()
255    }
256}
257
258impl<T: SignInterface + 'static> From<T> for IdentityKey {
259    fn from(value: T) -> Self {
260        Self::from_interface(Arc::new(value))
261    }
262}
263
264/// An Identity, wrapping a public signing key.
265///
266/// This is useful as an identifier of who has created a given signature.
267#[derive(Clone)]
268pub struct Identity {
269    id: ed25519_dalek::VerifyingKey,
270}
271
272impl Identity {
273    /// Get the cryptographic algorithm version used for this identity.
274    pub fn version(&self) -> u8 {
275        1u8
276    }
277
278    /// Get the raw public signing key contained within.
279    pub fn raw_public_key(&self) -> &[u8] {
280        self.id.as_ref()
281    }
282
283    /// Convert into a byte vector. For extending an existing byte vector, see
284    /// [`encode_vec`](Self::encode_vec).
285    pub fn as_vec(&self) -> Vec<u8> {
286        let mut v = Vec::new();
287        self.encode_vec(&mut v);
288        v
289    }
290
291    /// Attempt to parse a base58-encoded Identity.
292    pub fn from_base58(s: &str) -> Result<Self, CryptoError> {
293        let raw = bs58::decode(s)
294            .into_vec()
295            .or(Err(CryptoError::BadFormat("Not valid Base58")))?;
296        Self::try_from(&raw[..])
297    }
298
299    /// Convert into a base58-encoded Identity.
300    pub fn to_base58(&self) -> String {
301        bs58::encode(&(self.as_vec())).into_string()
302    }
303
304    /// Encode onto an existing byte vector. Writes out the version followed by the public signing
305    /// key. It does not include any length information in the encoding.
306    pub fn encode_vec(&self, buf: &mut Vec<u8>) {
307        let id = self.id.as_bytes();
308        buf.reserve(self.size());
309        buf.push(self.version());
310        buf.extend_from_slice(id);
311    }
312
313    /// Get the length of this Identity once encoded as bytes.
314    pub fn size(&self) -> usize {
315        1 + self.id.as_ref().len()
316    }
317}
318
319impl TryFrom<&[u8]> for Identity {
320    type Error = CryptoError;
321
322    /// Value must be the same length as the Identity was when it was encoded (no trailing bytes
323    /// allowed).
324    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
325        let (&version, data) = value.split_first().ok_or(CryptoError::BadLength {
326            step: "get Identity version",
327            expected: 1,
328            actual: 0,
329        })?;
330        if version != 1u8 {
331            return Err(CryptoError::UnsupportedVersion(version));
332        }
333        let Some(data) = data.try_into().ok() else {
334            return Err(CryptoError::BadLength {
335                step: "get Identity public key",
336                expected: V1_IDENTITY_ID_SIZE,
337                actual: data.len(),
338            });
339        };
340        let id = ed25519_dalek::VerifyingKey::from_bytes(data).or(Err(CryptoError::BadKey))?;
341        Ok(Identity { id })
342    }
343}
344
345impl fmt::Debug for Identity {
346    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
347        f.debug_struct("Identity")
348            .field("version", &self.version())
349            .field("public_key", &self.raw_public_key())
350            .finish()
351    }
352}
353
354impl fmt::Display for Identity {
355    /// Display as a base58-encoded string.
356    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
357        write!(f, "{}", self.to_base58())
358    }
359}
360
361impl fmt::LowerHex for Identity {
362    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
363        for byte in self.as_vec().iter() {
364            write!(f, "{:x}", byte)?;
365        }
366        Ok(())
367    }
368}
369
370impl fmt::UpperHex for Identity {
371    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
372        for byte in self.as_vec().iter() {
373            write!(f, "{:X}", byte)?;
374        }
375        Ok(())
376    }
377}
378
379impl std::cmp::PartialEq for Identity {
380    fn eq(&self, other: &Self) -> bool {
381        self.id == other.id
382    }
383}
384
385impl std::cmp::Eq for Identity {}
386
387impl std::hash::Hash for Identity {
388    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
389        self.id.as_bytes().hash(state);
390    }
391}
392
393/// A Signature interface, implemented by anything that can hold a private cryptographic signing
394/// key.
395///
396/// An implementor must handle all supported cryptographic signing algorithms.
397pub trait SignInterface {
398    /// Get the corresponding `Identity` for the private key.
399    fn id(&self) -> &Identity;
400
401    /// Sign a hash.
402    fn sign(&self, hash: &Hash) -> Signature;
403
404    /// Export the signing key in an `IdentityLockbox`, with `receive_lock` as the recipient. If
405    /// the key cannot be exported, this should return None.
406    fn self_export_lock(
407        &self,
408        csprng: &mut dyn CryptoSrc,
409        receive_lock: &LockId,
410    ) -> Option<IdentityLockbox>;
411
412    /// Export the signing key in an `IdentityLockbox`, with `receive_stream` as the recipient. If
413    /// the key cannot be exported, this should return None. Additionally, if the underlying
414    /// implementation does not allow moving the raw key into memory (i.e. it cannot call
415    /// [`StreamInterface::encrypt`][StreamEncrypt] or [`lock_id_encrypt`][LockEncrypt]) then None
416    /// can also be returned.
417    ///
418    /// [StreamEncrypt]: crate::stream::StreamInterface::encrypt
419    /// [LockEncrypt]: crate::lock::lock_id_encrypt
420    fn self_export_stream(
421        &self,
422        csprng: &mut dyn CryptoSrc,
423        receive_stream: &StreamKey,
424    ) -> Option<IdentityLockbox>;
425}
426
427/// A self-contained implementor of `SignInterface`. It's expected this will be used unless the key
428/// is being managed by the OS or a hardware module.
429///
430/// In general, you *do not* want to use this directly - [`IdentityKey`] is
431/// strongly preferred. This exists only so raw signing keys can be passed out
432/// without having a target [`LockKey`][crate::lock::LockKey] or [`StreamKey`] -
433/// a specialized requirement needed to implement things like invite tokens.
434#[derive(Clone)]
435pub struct BareIdKey { id: Identity, inner: ed25519_dalek::SigningKey, }
436
437impl std::fmt::Debug for BareIdKey {
438    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
439        f.debug_struct("BareIdKey")
440            .field("id", &self.id)
441            .finish_non_exhaustive()
442    }
443}
444
445impl fmt::Display for BareIdKey {
446    /// Display as a base58-encoded string.
447    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
448        write!(f, "{}", self.to_base58())
449    }
450}
451
452#[cfg(feature = "getrandom")]
453impl Default for BareIdKey {
454    fn default() -> Self {
455        Self::new()
456    }
457}
458
459impl BareIdKey {
460
461    /// Generate a new self-contained Identity key.
462    #[cfg(feature = "getrandom")]
463    pub fn new() -> Self {
464        let inner = ed25519_dalek::SigningKey::generate(&mut rand_core::OsRng);
465        let id = Identity { id: inner.verifying_key() };
466        Self { id, inner }
467    }
468
469    /// Generate a new key given a cryptographic random number generator.
470    pub fn with_rng<R>(csprng: &mut R) -> Self
471    where
472        R: rand_core::CryptoRng + rand_core::RngCore,
473    {
474        Self::with_rng_and_version(csprng, DEFAULT_SIGN_VERSION).unwrap()
475    }
476
477    /// Generate a new key with a specific version, given a cryptographic random number generator.
478    /// Fails if the version isn't supported.
479    pub fn with_rng_and_version<R>(csprng: &mut R, version: u8) -> Result<Self, CryptoError>
480    where
481        R: rand_core::CryptoRng + rand_core::RngCore,
482    {
483        if (version < MIN_SIGN_VERSION) || (version > MAX_SIGN_VERSION) {
484            return Err(CryptoError::UnsupportedVersion(version));
485        }
486
487        let inner = ed25519_dalek::SigningKey::generate(csprng);
488        let id = Identity { id: inner.verifying_key() };
489
490        Ok(Self { id, inner })
491    }
492
493    /// Attempt to parse a base58-encoded BareIdKey.
494    pub fn from_base58(s: &str) -> Result<Self, CryptoError> {
495        let raw = bs58::decode(s)
496            .into_vec()
497            .or(Err(CryptoError::BadFormat("Not valid Base58")))?;
498        Self::try_from(&raw[..])
499    }
500
501    /// Convert into a base58-encoded BareIdKey.
502    pub fn to_base58(&self) -> String {
503        let mut buf = Vec::new();
504        self.encode_vec(&mut buf);
505        bs58::encode(&buf).into_string()
506    }
507
508    pub fn size(&self) -> usize {
509        1 + ed25519_dalek::SECRET_KEY_LENGTH
510    }
511
512    /// Encode the raw key, prepended with the version byte. The output vector must be either
513    /// zeroized or encrypted before being dropped.
514    pub fn encode_vec(&self, buf: &mut Vec<u8>) {
515        buf.reserve(1 + ed25519_dalek::SECRET_KEY_LENGTH);
516        buf.push(1u8);
517        buf.extend_from_slice(&self.inner.to_bytes())
518    }
519}
520
521impl TryFrom<&[u8]> for BareIdKey {
522    type Error = CryptoError;
523
524    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
525        let (version, key) = value.split_first().ok_or(CryptoError::BadLength {
526            step: "get IdentityKey version",
527            expected: 1,
528            actual: 0,
529        })?;
530        let version = *version;
531        if version < MIN_SIGN_VERSION {
532            return Err(CryptoError::OldVersion(version));
533        }
534        if version > MAX_SIGN_VERSION {
535            return Err(CryptoError::UnsupportedVersion(version));
536        }
537
538        if key.len() != V1_IDENTITY_KEY_SIZE {
539            return Err(CryptoError::BadLength {
540                step: "get IdentityKey key bytes",
541                expected: V1_IDENTITY_KEY_SIZE,
542                actual: key.len(),
543            });
544        }
545
546        let secret_key = ed25519_dalek::SecretKey::try_from(key).map_err(|_| CryptoError::BadKey)?;
547
548        let inner = ed25519_dalek::SigningKey::from_bytes(&secret_key);
549        let id = inner.verifying_key();
550
551        Ok(Self {
552            inner,
553            id: Identity { id },
554        })
555    }
556}
557
558impl fmt::LowerHex for BareIdKey {
559    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
560        let mut buf = Vec::new();
561        self.encode_vec(&mut buf);
562        for byte in buf.iter() {
563            write!(f, "{:x}", byte)?;
564        }
565        Ok(())
566    }
567}
568
569impl fmt::UpperHex for BareIdKey {
570    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
571        let mut buf = Vec::new();
572        self.encode_vec(&mut buf);
573        for byte in buf.iter() {
574            write!(f, "{:X}", byte)?;
575        }
576        Ok(())
577    }
578}
579
580impl std::cmp::PartialEq for BareIdKey {
581    fn eq(&self, other: &Self) -> bool {
582        self.inner.to_bytes() == other.inner.to_bytes()
583    }
584}
585
586impl std::cmp::Eq for BareIdKey {}
587
588impl std::hash::Hash for BareIdKey {
589    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
590        self.inner.to_bytes().hash(state);
591    }
592}
593
594
595impl SignInterface for BareIdKey {
596    fn sign(&self, hash: &Hash) -> Signature {
597        let inner = self.inner.sign(hash.digest());
598
599        Signature {
600            hash_version: hash.version(),
601            id: self.id.clone(),
602            inner,
603        }
604    }
605
606    fn id(&self) -> &Identity {
607        &self.id
608    }
609
610    fn self_export_lock(
611        &self,
612        csprng: &mut dyn CryptoSrc,
613        receive_lock: &LockId,
614    ) -> Option<IdentityLockbox> {
615        let mut raw_secret = Vec::new(); // Make 100% certain this is zeroized at the end!
616        self.encode_vec(&mut raw_secret);
617        let lockbox_vec = crate::lock::lock_id_encrypt(
618            receive_lock,
619            csprng,
620            LockboxType::Identity(false),
621            &raw_secret,
622        );
623        raw_secret.zeroize();
624        debug_assert!(raw_secret.iter().all(|&x| x == 0)); // You didn't remove the zeroize call, right?
625        Some(identity_lockbox_from_parts(lockbox_vec))
626    }
627
628    fn self_export_stream(
629        &self,
630        csprng: &mut dyn CryptoSrc,
631        receive_stream: &StreamKey,
632    ) -> Option<IdentityLockbox> {
633        let mut raw_secret = Vec::new(); // Make 100% certain this is zeroized at the end!
634        self.encode_vec(&mut raw_secret);
635        let lockbox_vec = crate::stream::stream_key_encrypt(
636            receive_stream,
637            csprng,
638            LockboxType::Identity(true),
639            &raw_secret,
640        );
641        raw_secret.zeroize();
642        debug_assert!(raw_secret.iter().all(|&x| x == 0)); // You didn't remove the zeroize call, right?
643        Some(identity_lockbox_from_parts(lockbox_vec))
644    }
645}
646
647/// An annotated cryptographic signature.
648///
649/// Includes the version of hash that was signed, the [`Identity`] of the signer, and the signature
650/// itself. These are always encoded together to make it easier to verify signatures appended to a
651/// chunk of data.
652///
653/// A signature can be constructed in one of two ways: calling `sign(...)` on an [`IdentityKey`],
654/// or by verifying an [`UnverifiedSignature`].
655///
656/// The byte encoding is specifically:
657/// 1. The Hash version byte
658/// 2. The encoded signing `Identity`
659/// 3. The cryptographic signature's raw bytes
660#[derive(Clone, PartialEq, Eq)]
661pub struct Signature {
662    hash_version: u8,
663    id: Identity,
664    inner: ed25519_dalek::Signature,
665}
666
667impl Signature {
668    /// The version of the [`struct@Hash`] used in signature computation.
669    pub fn hash_version(&self) -> u8 {
670        self.hash_version
671    }
672
673    /// The public [`Identity`] of the [`IdentityKey`] that created this signature.
674    pub fn signer(&self) -> &Identity {
675        &self.id
676    }
677
678    /// Encode the signature onto a `Vec<u8>`. Adds the hash version, signing identity, and
679    /// signature bytes.
680    pub fn encode_vec(&self, buf: &mut Vec<u8>) {
681        let signature = self.inner.to_bytes();
682        buf.push(self.hash_version);
683        self.id.encode_vec(buf);
684        buf.extend_from_slice(&signature);
685    }
686
687    /// The length of the signature, in bytes, when encoded.
688    pub fn size(&self) -> usize {
689        1 + V1_IDENTITY_SIGN_SIZE + self.id.size()
690    }
691}
692
693impl fmt::Debug for Signature {
694    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
695        f.debug_struct("Signature")
696            .field("hash_version", &self.hash_version)
697            .field("signer", &self.id)
698            .field("signature", &self.inner)
699            .finish()
700    }
701}
702
703/// A signature that has been read from a byte slice but hasn't been verified yet.
704///
705/// Verification can be done by getting the appropriate version of hash into the `verify(...)`
706/// function.
707///
708/// # Example
709/// ```
710/// # use fog_crypto::identity::*;
711/// # use fog_crypto::hash::Hash;
712/// # use std::convert::TryFrom;
713/// # use std::sync::Arc;
714/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
715/// #
716/// # let key = IdentityKey::new();
717/// # let mut encoded = Vec::new();
718/// let data = b"I am some test data";
719/// // ...
720/// # let hash = Hash::new(&data[..]);
721/// # let signature = key.sign(&hash);
722/// # signature.encode_vec(&mut encoded);
723///
724/// let unverified = UnverifiedSignature::try_from(&encoded[..])?;
725/// let hash_version = unverified.hash_version();
726/// let hash = Hash::with_version(&data[..], hash_version)?;
727/// match unverified.verify(&hash) {
728///     Ok(verified) => {
729///         println!("Got valid signature, signed by {}", verified.signer());
730///     },
731///     Err(_) => {
732///         println!("Signature failed validation");
733///     }
734/// }
735/// # Ok(())
736/// # }
737/// ```
738#[derive(Clone, PartialEq, Eq)]
739pub struct UnverifiedSignature {
740    hash_version: u8,
741    signature: ed25519_dalek::Signature,
742    id: Identity,
743}
744
745impl UnverifiedSignature {
746    /// Get the version of hash needed to complete the signature.
747    pub fn hash_version(&self) -> u8 {
748        self.hash_version
749    }
750
751    /// The public [`Identity`] provided with this signature. Because this is an unverified
752    /// signature, there can be no assurance that this identity has actually signed the data.
753    pub fn signer(&self) -> &Identity {
754        &self.id
755    }
756
757    /// Verify the Signature, producing a verified Signature or failing.
758    pub fn verify(self, hash: &Hash) -> Result<Signature, CryptoError> {
759        if hash.version() != self.hash_version {
760            return Err(CryptoError::ObjectMismatch(
761                "Verification step got wrong version of hash",
762            ));
763        }
764        if self
765            .id
766            .id
767            .verify_strict(hash.digest(), &self.signature)
768            .is_err()
769        {
770            return Err(CryptoError::SignatureFailed);
771        }
772        Ok(Signature {
773            hash_version: self.hash_version,
774            id: self.id,
775            inner: self.signature,
776        })
777    }
778}
779
780impl fmt::Debug for UnverifiedSignature {
781    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
782        f.debug_struct("UnverifiedSignature")
783            .field("hash_version", &self.hash_version)
784            .field("signer", &self.id)
785            .field("signature", &self.signature)
786            .finish()
787    }
788}
789
790impl TryFrom<&[u8]> for UnverifiedSignature {
791    type Error = CryptoError;
792
793    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
794        let (hash_version, value) = value.as_ref().split_first().ok_or(CryptoError::BadLength {
795            step: "get signature hash version",
796            expected: 1,
797            actual: 0,
798        })?;
799        let hash_version = *hash_version;
800        if hash_version < MIN_HASH_VERSION || hash_version > MAX_HASH_VERSION {
801            return Err(CryptoError::UnsupportedVersion(hash_version));
802        }
803        let (&id_version, data) = value.split_first().ok_or(CryptoError::BadLength {
804            step: "get signature id version",
805            expected: 1,
806            actual: 0,
807        })?;
808        if id_version != 1 {
809            return Err(CryptoError::UnsupportedVersion(id_version));
810        }
811
812        let id_len = V1_IDENTITY_ID_SIZE;
813        let raw_id = data.get(0..id_len).ok_or(CryptoError::BadLength {
814            step: "get signature signer",
815            expected: id_len,
816            actual: data.len(),
817        })?;
818        let raw_signature = data.get(id_len..).ok_or(CryptoError::BadLength {
819            step: "get signature data",
820            expected: V1_IDENTITY_SIGN_SIZE,
821            actual: data.len() - id_len,
822        })?;
823        let raw_id = raw_id.try_into().unwrap();
824        let id = Identity { id: ed25519_dalek::VerifyingKey::from_bytes(raw_id).or(Err(CryptoError::BadKey))? };
825        let signature = ed25519_dalek::Signature::try_from(raw_signature)
826            .or(Err(CryptoError::SignatureFailed))?;
827        Ok(UnverifiedSignature {
828            hash_version,
829            id,
830            signature,
831        })
832    }
833}
834
835#[cfg(test)]
836mod tests {
837    use super::*;
838
839    #[test]
840    fn basics() {
841        let mut csprng = rand::rngs::OsRng;
842        let key = IdentityKey::with_rng(&mut csprng);
843        assert_eq!(key.version(), DEFAULT_SIGN_VERSION);
844        let key = IdentityKey::with_rng_and_version(&mut csprng, DEFAULT_SIGN_VERSION).unwrap();
845        assert_eq!(key.version(), DEFAULT_SIGN_VERSION);
846        let result = IdentityKey::with_rng_and_version(&mut csprng, 99u8);
847        if let Err(CryptoError::UnsupportedVersion(99u8)) = result {
848        } else {
849            panic!("Didn't get expected error on with_rng_and_version");
850        }
851
852        let key = BareIdKey::with_rng(&mut csprng);
853        assert_eq!(key.id().version(), DEFAULT_SIGN_VERSION);
854        let key = BareIdKey::with_rng_and_version(&mut csprng, DEFAULT_SIGN_VERSION).unwrap();
855        assert_eq!(key.id().version(), DEFAULT_SIGN_VERSION);
856        let result = BareIdKey::with_rng_and_version(&mut csprng, 99u8);
857        if let Err(CryptoError::UnsupportedVersion(99u8)) = result {
858        } else {
859            panic!("Didn't get expected error on with_rng_and_version");
860        }
861    }
862
863    #[test]
864    fn display() {
865        let mut csprng = rand::rngs::OsRng;
866        let key = IdentityKey::with_rng(&mut csprng);
867        let disp_key = format!("{}", &key);
868        let disp_id = format!("{}", key.id());
869        let base58 = key.id().to_base58();
870        assert_eq!(disp_key, disp_id);
871        assert_eq!(disp_key, base58);
872        assert!(disp_key.len() > 1);
873    }
874
875    #[test]
876    fn base58_id() {
877        let mut csprng = rand::rngs::OsRng;
878        let key = IdentityKey::with_rng(&mut csprng);
879        let mut base58 = key.id().to_base58();
880        assert!(base58.len() > 1);
881        let id = Identity::from_base58(&base58).unwrap();
882        assert_eq!(&id, key.id());
883        base58.push('a');
884        base58.push('a');
885        assert!(Identity::from_base58(&base58).is_err());
886        base58.pop();
887        base58.pop();
888        base58.pop();
889        assert!(Identity::from_base58(&base58).is_err());
890    }
891
892    #[test]
893    fn base58_bare_id_key() {
894        let key = BareIdKey::new();
895        let mut base58 = key.to_base58();
896        assert!(base58.len() > 1);
897        let key_dec = BareIdKey::from_base58(&base58).unwrap();
898        assert_eq!(key.id(), key_dec.id());
899        base58.push('a');
900        base58.push('a');
901        assert!(BareIdKey::from_base58(&base58).is_err());
902        base58.pop();
903        base58.pop();
904        base58.pop();
905        assert!(BareIdKey::from_base58(&base58).is_err());
906    }
907
908    #[test]
909    fn encode() {
910        let mut csprng = rand::rngs::OsRng;
911        let key = IdentityKey::with_rng(&mut csprng);
912        let id = key.id();
913        let id_v0 = id.as_vec();
914        let mut id_v1 = Vec::new();
915        id.encode_vec(&mut id_v1);
916        assert_eq!(id_v0.len(), id.size());
917        assert_eq!(id_v0, id_v1);
918        let id = Identity::try_from(&id_v0[..]).unwrap();
919        assert_eq!(&id, key.id());
920    }
921
922    #[test]
923    fn encode_bare() {
924        let mut csprng = rand::rngs::OsRng;
925        let key = BareIdKey::with_rng(&mut csprng);
926        let id = key.id();
927        let id_v0 = id.as_vec();
928        let mut id_v1 = Vec::new();
929        id.encode_vec(&mut id_v1);
930        assert_eq!(id_v0.len(), id.size());
931        assert_eq!(id_v0, id_v1);
932        let id = Identity::try_from(&id_v0[..]).unwrap();
933        assert_eq!(&id, key.id());
934    }
935
936    #[test]
937    fn id_len() {
938        let mut csprng = rand::rngs::OsRng;
939        let key = IdentityKey::with_rng(&mut csprng);
940        let id = key.id();
941        let len = id.size();
942
943        let mut enc = Vec::new();
944        id.encode_vec(&mut enc);
945        assert_eq!(len, enc.len());
946        assert_eq!(len, id.as_vec().len());
947    }
948
949    #[test]
950    fn signature_len() {
951        let mut csprng = rand::rngs::OsRng;
952        let key = IdentityKey::with_rng(&mut csprng);
953        let hash = Hash::new(b"I am a test string");
954        let sign = key.sign(&hash);
955        let len = sign.size();
956
957        let mut enc = Vec::new();
958        sign.encode_vec(&mut enc);
959        assert_eq!(len, enc.len());
960    }
961
962    #[test]
963    fn sign() {
964        let mut csprng = rand::rngs::OsRng;
965        let key = IdentityKey::with_rng(&mut csprng);
966
967        // Make new hash and check it
968        let test_data = b"This is a test";
969        let hash = Hash::new(test_data);
970        let sign = key.sign(&hash);
971        assert_eq!(
972            sign.hash_version(),
973            hash.version(),
974            "Hash version in signature should match Hash's"
975        );
976        assert_eq!(
977            sign.signer(),
978            key.id(),
979            "Identity in signature should match original Id"
980        );
981
982        // Encode/decode
983        let mut enc = Vec::new();
984        sign.encode_vec(&mut enc);
985        let dec_sign = UnverifiedSignature::try_from(&enc[..])
986            .expect("Wasn't able to decode an unverified signature")
987            .verify(&hash)
988            .expect("Wasn't able to verify the signature");
989        assert_eq!(
990            dec_sign.signer(),
991            sign.signer(),
992            "Signature Identities don't match"
993        );
994        assert_eq!(
995            dec_sign.hash_version(),
996            sign.hash_version(),
997            "Signature hash versions don't match"
998        );
999    }
1000
1001    #[test]
1002    fn wrong_hashes() {
1003        let mut csprng = rand::rngs::OsRng;
1004        let key = IdentityKey::with_rng(&mut csprng);
1005
1006        // Make new hash and check it
1007        let test_data = b"This is a test";
1008        let hash = Hash::new(test_data);
1009        let bad_hash = Hash::new(b"Not the same data");
1010        let sign = key.sign(&hash);
1011
1012        // Encode
1013        let mut enc = Vec::new();
1014        sign.encode_vec(&mut enc);
1015        // Decode: Fail the verification step
1016        let unverified = UnverifiedSignature::try_from(&enc[..])
1017            .expect("Wasn't able to decode an unverified signature");
1018        if let Err(CryptoError::SignatureFailed) = unverified.verify(&bad_hash) {
1019        } else {
1020            panic!(
1021                "Signature verification should fail with SignatureFailed when given the wrong Hash"
1022            );
1023        }
1024    }
1025
1026    #[test]
1027    fn wrong_hash_versions() {
1028        let mut csprng = rand::rngs::OsRng;
1029        let key = IdentityKey::with_rng(&mut csprng);
1030
1031        // Make new hash and check it
1032        let test_data = b"This is a test";
1033        let hash = Hash::new(test_data);
1034        let sign = key.sign(&hash);
1035
1036        // Encode
1037        let mut enc = Vec::new();
1038        sign.encode_vec(&mut enc);
1039
1040        // Decode: Fail with an unsupported hash
1041        enc[0] = 0;
1042        if let Err(CryptoError::UnsupportedVersion(0)) = UnverifiedSignature::try_from(&enc[..]) {
1043        } else {
1044            panic!("Signature decoding shouldn't permit a hash with version 0");
1045        }
1046        enc[0] = 255;
1047        if let Err(CryptoError::UnsupportedVersion(255)) = UnverifiedSignature::try_from(&enc[..]) {
1048        } else {
1049            panic!("Signature decoding shouldn't permit a hash with version 255");
1050        }
1051    }
1052
1053    #[test]
1054    fn wrong_id_versions() {
1055        let mut csprng = rand::rngs::OsRng;
1056        let key = IdentityKey::with_rng(&mut csprng);
1057
1058        // Make new hash and check it
1059        let test_data = b"This is a test";
1060        let hash = Hash::new(test_data);
1061        let sign = key.sign(&hash);
1062
1063        // Encode
1064        let mut enc = Vec::new();
1065        sign.encode_vec(&mut enc);
1066
1067        // Decode: Fail with an unsupported identity
1068        enc[1] = 0;
1069        if let Err(CryptoError::UnsupportedVersion(0)) = UnverifiedSignature::try_from(&enc[..]) {
1070        } else {
1071            panic!("Signature decoding shouldn't permit an identity with version 0");
1072        }
1073        enc[1] = 255;
1074        if let Err(CryptoError::UnsupportedVersion(255)) = UnverifiedSignature::try_from(&enc[..]) {
1075        } else {
1076            panic!("Signature decoding shouldn't permit an identity with version 255");
1077        }
1078    }
1079
1080    #[test]
1081    fn corrupted_signature() {
1082        let mut csprng = rand::rngs::OsRng;
1083        let key = IdentityKey::with_rng(&mut csprng);
1084
1085        // Make new hash and check it
1086        let test_data = b"This is a test";
1087        let hash = Hash::new(test_data);
1088        let sign = key.sign(&hash);
1089
1090        // Encode
1091        let mut enc = Vec::new();
1092        sign.encode_vec(&mut enc);
1093
1094        // 1st Check: Change the length
1095        let unverified = UnverifiedSignature::try_from(&enc[..enc.len()-1]);
1096        if unverified.is_ok() {
1097            panic!("Should fail with BadLength when the signature has been truncated");
1098        }
1099        enc.push(0);
1100        let unverified = UnverifiedSignature::try_from(&enc[..]);
1101        if unverified.is_ok() {
1102            panic!("Should fail with BadLength when the signature has been extended");
1103        }
1104        enc.pop();
1105
1106        // 2nd Check: corrupt signature so uppermost 3 bits are inverted
1107        // This has a different failure condition than other corruptions, as ed25519_dalek checks the
1108        // uppermost bits during signature verification - a valid signature should have them all zeroed.
1109        let last = enc.last_mut().unwrap();
1110        *last = !*last;
1111        let unverified = UnverifiedSignature::try_from(&enc[..]).unwrap();
1112        if let Err(CryptoError::SignatureFailed) = unverified.verify(&hash) {
1113        } else {
1114            panic!("Should fail with SignatureFailed when the last signature byte is wrong");
1115        }
1116        // 3rd Check: corrupt other signature bytes
1117        let last = enc.last_mut().unwrap();
1118        *last = !*last;
1119        let len = enc.len();
1120        let near_last = enc.get_mut(len - 2).unwrap();
1121        *near_last = !*near_last;
1122        let unverified = UnverifiedSignature::try_from(&enc[..]).unwrap();
1123        if let Err(CryptoError::SignatureFailed) = unverified.verify(&hash) {
1124        } else {
1125            panic!("Should fail with SignatureFailed when the signature bytes are wrong");
1126        }
1127    }
1128
1129    #[test]
1130    fn corrupted_id() {
1131        let mut csprng = rand::rngs::OsRng;
1132        let key = IdentityKey::with_rng(&mut csprng);
1133
1134        // Make new hash and check it
1135        let test_data = b"This is a test";
1136        let hash = Hash::new(test_data);
1137        let sign = key.sign(&hash);
1138
1139        // Encode
1140        let mut enc = Vec::new();
1141        sign.encode_vec(&mut enc);
1142        // Decode: Fail with a changed identity
1143        enc[4] = !enc[4];
1144        match UnverifiedSignature::try_from(&enc[..]) {
1145            Err(CryptoError::BadKey) => {}
1146            Ok(unverified) => {
1147                if let Err(CryptoError::SignatureFailed) = unverified.verify(&hash) {
1148                } else {
1149                    panic!("Should fail with SignatureFailed when identity is wrong for signature");
1150                }
1151            }
1152            _ => {
1153                panic!("Should fail with BadKey when the identity is corrupted and ed25519_dalek can tell");
1154            }
1155        }
1156    }
1157
1158    #[test]
1159    fn substitute_wrong_id() {
1160        let mut csprng = rand::rngs::OsRng;
1161        let key = IdentityKey::with_rng(&mut csprng);
1162        let other_id = IdentityKey::with_rng(&mut csprng);
1163
1164        // Make new hash and check it
1165        let test_data = b"This is a test";
1166        let hash = Hash::new(test_data);
1167        let sign = key.sign(&hash);
1168
1169        let mut enc = Vec::new();
1170        sign.encode_vec(&mut enc);
1171        for (dest, src) in enc.iter_mut().skip(1).zip(other_id.id().as_vec().iter()) {
1172            *dest = *src;
1173        }
1174        match UnverifiedSignature::try_from(&enc[..]) {
1175            Err(CryptoError::BadKey) => {
1176                panic!("Key should be valid, just wrong for the signature");
1177            }
1178            Ok(unverified) => {
1179                if let Err(CryptoError::SignatureFailed) = unverified.verify(&hash) {
1180                } else {
1181                    panic!("Should fail with SignatureFailed when identity is wrong for signature");
1182                }
1183            }
1184            _ => {
1185                panic!("Shouldn't fail on the initial decoding to an UnverifiedSignature");
1186            }
1187        }
1188    }
1189}