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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
//! This module provides types and traits library users need for signing and verifying attenuable JWTs.

use erased_serde::Serialize as ErasedSerialize;
use serde::{de::DeserializeOwned, Deserialize, Serialize};

/// Newtype struct for a string representing a signed JWT.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(transparent)]
pub struct SignedJWT(pub String);

impl AsRef<str> for SignedJWT {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

/// Claims for a sealed attenuated JWT.
/// These are the claims of the JWT produced by [crate::sign::AttenuableJWT::seal].
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct SealedClaims {
    /// Expiration.
    pub exp: Option<SecondsSinceEpoch>,
    /// Not before.
    pub nbf: Option<SecondsSinceEpoch>,
    /// Issuer.
    pub iss: Option<Issuer>,
    /// Audience.
    pub aud: Option<Audience>,
    /// Inner JWTs, starting with the root JWT and ending with the most-attenuated JWT.
    pub jwts: Vec<SignedJWT>,
}

/// Newtype wrapper for the number of seconds elapsed since the unix epoch.
/// Used in the `exp` and `nbf` claims of JWTs.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(transparent)]
pub struct SecondsSinceEpoch(pub u64);

/// Newtype wrapper for issuer identifiers.
/// Used in the `iss` claim of JWTs.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Issuer(pub String);

impl AsRef<str> for Issuer {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

/// Newtype wrapper for audience identifiers.
/// Used in the `aud` claim of JWTs.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Audience(pub String);

impl AsRef<str> for Audience {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

/// A private key. The [ErasedSerialize] implementation must serialize to a JWK.
pub trait PrivateKey: ErasedSerialize {
    /// Key ID.
    fn key_id(&self) -> &str;
    /// Algorithm.
    fn algorithm(&self) -> &str;
    /// Sign the message.
    fn sign(&self, message: &[u8]) -> crate::sign::Result<Vec<u8>>;
}

/// A public key. The [ErasedSerialize] implementation must serialize to a JWK.
pub trait PublicKey: ErasedSerialize {
    /// Key ID.
    fn key_id(&self) -> &str;
    /// Algorithm.
    fn algorithm(&self) -> &str;
    /// Intended use for the key.
    fn key_use(&self) -> KeyUse;
    /// Verify the signature of the message.
    fn verify(&self, message: &[u8], signature: &[u8]) -> bool;
}

erased_serde::serialize_trait_object!(PublicKey);

/// Key use identifiers.
/// Used in the `use` claim of a JWK.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum KeyUse {
    /// Encryption.
    #[serde(rename = "enc")]
    Encryption,
    /// Signing.
    #[serde(rename = "sig")]
    Signing,
}

/// Trait containing all client-supplied information needed for verify a sealed [crate::sign::AttenuableJWT].
pub trait VerificationKeyManager: Clone {
    /// Type of the public key for the root JWT.
    /// The root JWT may be signed by a different algorithm with a different type of key than the attenuated JWTs added to it.
    /// For example, the root JWT may be signed with a secret key, whereas only asymmetric keys are suitable for attenuated JWTs.
    type PublicRootKey: PublicKey;
    /// Type of the public key for attenuated JWTs.
    /// IMPORTANT: THIS MUST BE AN ASYMMETRIC KEY.
    /// This is the public key counterpart to the [Self::PrivateAttenuationKey].
    type PublicAttenuationKey: PublicKey;
    /// Type of the private key for attenuated JWTs.
    /// IMPORTANT: THIS MUST BE AN ASYMMETRIC KEY.
    /// This is the private key counterpart to the [Self::PublicAttenuationKey].
    type PrivateAttenuationKey: PrivateKey;
    /// Type of the client-supplied attenuated claims.
    /// Any type that is serializable to/from a JSON object is suitable.
    type Claims: Serialize + DeserializeOwned;
    /// Type of the JWK that represents a [Self::PublicAttenuationKey].
    type JWK: Serialize + DeserializeOwned;

    /// Given a `key_id` if it is present in the JWT header, return the corresponding [Self::PublicRootKey].
    fn get_root_key(&self, key_id: &Option<String>) -> Option<Self::PublicRootKey>;
    /// The [VerificationRequirements] to use for verifying the sealed JWT envelope.
    fn get_envelope_verification_requirements(&self) -> VerificationRequirements;
    /// [crate::verify::verify] performs a fold over existing and new claims for each JWT in the chain, invoking the client-provided `resolve_claims` function with the existing and new claims.
    /// The `default_claims` are used as the initial value in that fold.
    fn default_claims(&self) -> Self::Claims;
    /// Given a [Self::JWK], return a [Self::PublicAttenuationKey].

    // Convert a [Self::JWK] into a [Self::PublicAttenuationKey].
    fn jwk_to_public_attenuation_key(&self, jwk: &Self::JWK) -> Option<Self::PublicAttenuationKey>;
}

/// JWT header.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) struct JWTHeader {
    /// Key ID for the key used to sign this JWT.
    #[serde(rename = "kid")]
    pub key_id: Option<String>,
    /// Algorithm used to sign this JWT.
    #[serde(rename = "alg")]
    pub algorithm: String,
}

/// Verification requirements to use when verifying a signed JWT.
#[derive(Clone, Debug)]
pub enum VerificationRequirements {
    /// Verify the signature and provided claims for the JWT.
    VerifyClaims {
        /// Acceptable signing algorithms.
        acceptable_algorithms: Vec<String>,
        /// Acceptable issuers. None indicates any issuer is acceptable.
        acceptable_issuers: Option<Vec<Issuer>>,
        /// Acceptable audiences. None indicates any audience is acceptable.
        acceptable_audiences: Option<Vec<Audience>>,
        /// Acceptable subject. None indicates any subject is acceptable.
        acceptable_subject: Option<String>,
    },
    /// Only verify the signature of the JWT but do not verify any claims.
    VerifySignatureOnly {
        /// Acceptable signing algorithms.
        acceptable_algorithms: Vec<String>,
    },
}

impl VerificationRequirements {
    /// Acceptable signing algorithms.
    pub fn acceptable_algorithms(&self) -> &[String] {
        match self {
            VerificationRequirements::VerifyClaims {
                acceptable_algorithms,
                ..
            } => acceptable_algorithms,
            VerificationRequirements::VerifySignatureOnly {
                acceptable_algorithms,
            } => acceptable_algorithms,
        }
    }
}

/// Trait handling signing and key generation for [crate::sign::AttenuableJWT].
pub trait SigningKeyManager:
    AttenuationKeyGenerator<Self::PublicAttenuationKey, Self::PrivateAttenuationKey> + Clone
{
    /// Type of the JWK for the [Self::PublicAttenuationKey].
    type JWK: Serialize;
    /// Type of the public key for the attenuation keys.
    type PublicAttenuationKey: PublicKey;
    /// Type of the private key for the attenuation keys.
    type PrivateAttenuationKey: PrivateKey;
    /// Type of the private key for the root JWT.
    type PrivateRootKey: PrivateKey;
    /// Type to represent the claims of the JWT. Any type that serializes to a map is suitable.
    type Claims: Serialize;

    /// Return a JWK representing the provided public attenuation key.
    fn jwk_for_public_attenuation_key(
        public_attenuation_key: &Self::PublicAttenuationKey,
    ) -> Self::JWK;
}

/// Trait for generating new attenuation keys.
pub trait AttenuationKeyGenerator<
    PublicAttenuationKey: PublicKey,
    PrivateAttenuationKey: PrivateKey,
>
{
    /// Generate a new, random attenuation key.
    fn generate_attenuation_key(
        &self,
    ) -> Result<(PublicAttenuationKey, PrivateAttenuationKey), crate::sign::Error>;
}

/// The full set of claims for an attenuated JWT, combining user-provided claims with the attenuation key claim.
#[derive(Serialize, Deserialize)]
pub(crate) struct FullClaims<JWK, Claims> {
    /// User-provided claims.
    #[serde(flatten)]
    pub user_provided_claims: Claims,
    /// Attenuation key claim containing a JWK representing the public key of the next attenuation key.
    pub aky: JWK,
}

impl<JWK: Serialize, Claims: Serialize> FullClaims<JWK, Claims> {
    /// Create a FullClaims.
    pub fn new(user_provided_claims: Claims, aky: JWK) -> Self {
        Self {
            user_provided_claims,
            aky,
        }
    }
}