jsonprooftoken/jwk/
key.rs

1// Copyright 2023 Fondazione LINKS
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6
7//     http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::errors::CustomError;
16use serde::{Deserialize, Serialize};
17use zkryptium::{
18    keys::pair::KeyPair,
19    schemes::algorithms::{BbsBls12381Sha256, BbsBls12381Shake256},
20};
21
22use super::{
23    alg_parameters::{Algorithm, JwkAlgorithmParameters, JwkEllipticCurveKeyParameters},
24    types::KeyPairSubtype,
25};
26
27/// JWK parameters defined at https://datatracker.ietf.org/doc/html/rfc7517#section-4
28#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
29pub struct Jwk {
30    /// ID of the key
31    #[serde(skip_serializing_if = "Option::is_none", default)]
32    pub kid: Option<String>,
33
34    /// The intended use of the public key
35    #[serde(rename = "use", skip_serializing_if = "Option::is_none", default)]
36    pub pk_use: Option<PKUse>,
37
38    /// The "key_ops" (key operations) parameter identifies the operation(s) for which the key is intended to be used
39
40    /// The "use" and "key_ops" JWK members SHOULD NOT be used together;
41    /// however, if both are used, the information they convey MUST be
42    /// consistent.  Applications should specify which of these members they
43    /// use, if either is to be used by the application.
44    #[serde(skip_serializing_if = "Option::is_none", default)]
45    pub key_ops: Option<Vec<KeyOps>>,
46
47    /// The algorithm intended to be used
48    #[serde(skip_serializing_if = "Option::is_none", default)]
49    pub alg: Option<Algorithm>,
50
51    /// X.509 Public key cerfificate URL.
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub x5u: Option<String>,
54
55    /// X.509 public key certificate chain.
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub x5c: Option<Vec<String>>,
58
59    /// X.509 Certificate thumbprint.
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub x5t: Option<String>,
62
63    //Key parameters based on the algorithm
64    #[serde(flatten)]
65    pub key_params: JwkAlgorithmParameters,
66}
67
68impl Jwk {
69    pub fn generate(key_type: KeyPairSubtype) -> Result<Self, CustomError> {
70        match key_type {
71            KeyPairSubtype::BLS12381G2Sha256 => {
72                let keypair = KeyPair::<BbsBls12381Sha256>::random()
73                    .map_err(|_| CustomError::JwkGenerationError("Keygen failed".to_owned()))?;
74                let pk = keypair.public_key();
75                let (x, y) = pk.to_coordinates();
76                let sk = keypair.private_key().to_bytes();
77                let okp_params = JwkEllipticCurveKeyParameters::new(
78                    super::curves::EllipticCurveTypes::BLS12381G2,
79                    &x,
80                    &y,
81                    Some(&sk),
82                );
83                let jwk_params = JwkAlgorithmParameters::EllipticCurve(okp_params);
84                Ok(Self {
85                    kid: None,
86                    pk_use: None,
87                    key_ops: None,
88                    alg: None,
89                    x5u: None,
90                    x5c: None,
91                    x5t: None,
92                    key_params: jwk_params,
93                })
94            }
95            KeyPairSubtype::BLS12381G2Shake256 => {
96                let keypair = KeyPair::<BbsBls12381Shake256>::random()
97                    .map_err(|_| CustomError::JwkGenerationError("Keygen failed".to_owned()))?;
98                let pk = keypair.public_key();
99                let (x, y) = pk.to_coordinates();
100                let sk = keypair.private_key().to_bytes();
101                let okp_params = JwkEllipticCurveKeyParameters::new(
102                    super::curves::EllipticCurveTypes::BLS12381G2,
103                    &x,
104                    &y,
105                    Some(&sk),
106                );
107                let jwk_params = JwkAlgorithmParameters::EllipticCurve(okp_params);
108                Ok(Self {
109                    kid: None,
110                    pk_use: None,
111                    key_ops: None,
112                    alg: None,
113                    x5u: None,
114                    x5c: None,
115                    x5t: None,
116                    key_params: jwk_params,
117                })
118            }
119        }
120    }
121
122    pub fn set_kid(&mut self, kid: &str) {
123        self.kid = Some(kid.to_string());
124    }
125
126    pub fn set_pk_use(&mut self, pk_use: PKUse) {
127        self.pk_use = Some(pk_use);
128    }
129
130    pub fn set_key_ops(&mut self, key_ops: Vec<KeyOps>) {
131        self.key_ops = Some(key_ops);
132    }
133
134    pub fn set_alg(&mut self, alg: Algorithm) {
135        self.alg = Some(alg);
136    }
137
138    pub fn set_x5u(&mut self, x5u: &str) {
139        self.x5u = Some(x5u.to_string());
140    }
141
142    pub fn set_x5c(&mut self, x5c: Vec<&str>) {
143        self.x5c = Some(x5c.iter().map(|v| v.to_string()).collect());
144    }
145
146    pub fn set_x5t(&mut self, x5t: &str) {
147        self.x5t = Some(x5t.to_string());
148    }
149
150    /// Returns `true` if _all_ private key components of the key are unset, `false` otherwise.
151    pub fn is_public(&self) -> bool {
152        self.key_params.is_public()
153    }
154
155    /// Returns `true` if _all_ private key components of the key are set, `false` otherwise.
156    pub fn is_private(&self) -> bool {
157        self.key_params.is_private()
158    }
159
160    pub fn from_key_params(key_params: JwkAlgorithmParameters) -> Self {
161        let params: JwkAlgorithmParameters = key_params.into();
162        Self {
163            kid: None,
164            pk_use: None,
165            key_ops: None,
166            alg: None,
167            x5u: None,
168            x5c: None,
169            x5t: None,
170            key_params: params,
171        }
172    }
173
174    pub fn to_public(&self) -> Option<Jwk> {
175        let mut public: Jwk = Jwk::from_key_params(self.key_params.to_public()?);
176
177        if let Some(value) = &self.kid {
178            public.set_kid(value);
179        }
180
181        if let Some(value) = self.pk_use {
182            public.set_pk_use(value);
183        }
184
185        if let Some(value) = &self.key_ops {
186            public.set_key_ops(value.iter().map(|op| op.inverse()).collect());
187        }
188
189        if let Some(value) = self.alg {
190            public.set_alg(value);
191        }
192
193        if let Some(value) = &self.x5u {
194            public.set_x5u(value);
195        }
196
197        if let Some(value) = &self.x5c {
198            public.set_x5c(value.iter().map(|x| x.as_str()).collect());
199        }
200
201        if let Some(value) = &self.x5t {
202            public.set_x5t(value);
203        }
204
205        Some(public)
206    }
207}
208
209#[derive(
210    Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, serde::Deserialize, serde::Serialize,
211)]
212#[serde(rename_all = "camelCase")]
213pub enum KeyOps {
214    /// Compute digital signature or MAC.
215    Sign,
216    /// Verify digital signature or MAC.
217    Verify,
218    /// Encrypt content.
219    Encrypt,
220    /// Decrypt content and validate decryption, if applicable.
221    Decrypt,
222    /// Encrypt key.
223    WrapKey,
224    /// Decrypt key and validate decryption, if applicable.
225    UnwrapKey,
226    /// Derive key.
227    DeriveKey,
228    /// Derive bits not to be used as a key.
229    DeriveBits,
230
231    /// Generate a proof
232    ProofGeneration,
233    ///Verify a proof
234    ProofVerification,
235}
236
237impl KeyOps {
238    pub const fn inverse(&self) -> Self {
239        match self {
240            Self::Sign => Self::Verify,
241            Self::Verify => Self::Sign,
242            Self::Encrypt => Self::Decrypt,
243            Self::Decrypt => Self::Encrypt,
244            Self::WrapKey => Self::UnwrapKey,
245            Self::UnwrapKey => Self::WrapKey,
246            Self::DeriveKey => Self::DeriveKey,
247            Self::DeriveBits => Self::DeriveBits,
248            Self::ProofGeneration => Self::ProofVerification,
249            Self::ProofVerification => Self::ProofVerification,
250        }
251    }
252}
253
254#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
255pub enum PKUse {
256    #[serde(rename = "sig")]
257    Signature,
258    #[serde(rename = "enc")]
259    Encryption,
260    #[serde(rename = "proof")]
261    Proof,
262}