1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
use std::time::SystemTime;
use generic_array::ArrayLength;
use typenum::Unsigned;
use crate::algorithm::{Signature, Signer as AlgorithmSigner};
use crate::error::BadSignature;
use crate::{BadTimedSignature, Separator, UnsignedValue};
/// A signer can sign and unsign bytes, validating the signature provided.
///
/// A salt can be used to namespace the hash, so that a signed string is only
/// valid for a given namespace. Leaving this at the default value or re-using a salt value
/// across different parts of your application where the same signed value in one part can
/// mean something different in another part is a security risk.
///
/// # Basic Usage
/// ```rust
/// use itsdangerous::{default_builder, Signer};
///
/// // Create a signer using the default builder, and an arbitrary secret key.
/// let signer = default_builder("secret key").build();
///
/// // Sign an arbitrary string.
/// let signed = signer.sign("hello world!");
///
/// // Unsign the string and validate whether or not its expired.
/// let unsigned = signer.unsign(&signed).expect("Signature was not valid");
/// assert_eq!(unsigned, "hello world!");
/// ```
pub trait Signer {
/// Signs the given string.
fn sign<S: AsRef<str>>(&self, value: S) -> String;
/// Unsigns the given string. The logical inverse of [`sign`].
///
/// # Remarks
///
/// This method performs zero copies or heap allocations and returns a reference to a slice
/// of the provided `value`, If you need a copy, consider doing `unsign(..).to_owned()`
/// to convert the [`&str`] to a [`String`].
///
/// [`&str`]: std::str
/// [`sign`]: Signer::sign
fn unsign<'a>(&'a self, value: &'a str) -> Result<&'a str, BadSignature<'a>>;
fn separator(&self) -> Separator;
/// Given a base-64 encoded signature, attempt to verify whether or not
/// it is valid for the given `value`.
fn verify_encoded_signature(&self, value: &[u8], encoded_signature: &[u8]) -> bool;
/// Gets the output size in bytes of the base-64 encoded signature part that this
/// signer will emit.
fn signature_output_size(&self) -> usize;
}
pub trait GetSigner {
type OutputSize: ArrayLength<u8> + Unsigned;
type Signer: AlgorithmSigner<OutputSize = Self::OutputSize>;
/// Returns a signer that can be used to build a signature for a given key + values.
fn get_signer(&self) -> Self::Signer;
/// Returns the signature for a given key + value.
fn get_signature(&self, value: &[u8]) -> Signature<Self::OutputSize> {
self.get_signer().input_chained(value).sign()
}
}
/// A TimestampSigner wraps an inner Signer, giving it the ability to dish
/// out signatures with timestamps.
///
/// # Basic Usage
/// ```rust
/// use std::time::Duration;
/// use itsdangerous::{default_builder, Signer, TimestampSigner, IntoTimestampSigner};
///
/// // Create a signer using the default builder, and an arbitrary secret key.
/// let signer = default_builder("secret key").build().into_timestamp_signer();
///
/// // Sign an arbitrary string.
/// let signed = signer.sign("hello world!");
///
/// // Unsign the string and validate whether or not its expired.
/// let unsigned = signer.unsign(&signed).expect("Signature was not valid");
/// let value = unsigned
/// .value_if_not_expired(Duration::from_secs(60))
/// .expect("Signature was expired");
/// assert_eq!(value, "hello world!");
/// ```
pub trait TimestampSigner {
fn separator(&self) -> Separator;
/// Signs a value with an arbitrary timestamp.
fn sign_with_timestamp<S: AsRef<str>>(&self, value: S, timestamp: SystemTime) -> String;
/// Signs a value using the current system timestamp (as provided by [`SystemTime::now`]).
fn sign<S: AsRef<str>>(&self, value: S) -> String;
/// The inverse of [`sign`] / [`sign_with_timestamp`], returning an [`UnsignedValue`], which you
/// can grab the value, timestamp, and assert the max age of the signed value with.
///
/// # Remarks
///
/// This method performs zero copies or heap allocations and returns a reference to a slice
/// of the provided `value`, inside of the [`UnsignedValue`] that is returned. If you need a
/// copy, consider doing `unsigned_value.value().to_owned()` to convert the [`&str`] to a [`String`].
///
/// [`&str`]: std::str
/// [`sign`]: TimestampSigner::sign
/// [`sign_with_timestamp`]: TimestampSigner::sign_with_timestamp
fn unsign<'a>(&'a self, value: &'a str) -> Result<UnsignedValue, BadTimedSignature<'a>>;
}
pub trait IntoTimestampSigner {
type TimestampSigner: TimestampSigner;
/// Converts this [`Signer`] into a [`TimestampSigner`], giving it the ability
/// to do signing with timestamps!
fn into_timestamp_signer(self) -> Self::TimestampSigner;
}
/// Returns a referenec to the underlying [`Signer`].
pub trait AsSigner {
type Signer: Signer;
/// Returns a reference to the underlying [`Signer`] if you wish to use its methods.
///
/// # Example
/// ```rust
/// use itsdangerous::{default_builder, TimestampSigner, IntoTimestampSigner, Signer, AsSigner};
///
/// let timestamp_signer = default_builder("hello world").build().into_timestamp_signer();
/// let signer = timestamp_signer.as_signer();
/// let signer = signer.sign("hello without a timestamp!");
/// ```
fn as_signer(&self) -> &Self::Signer;
}