aries_askar/kms/
local_key.rs

1use std::borrow::Cow;
2use std::str::FromStr;
3
4use super::enc::{Encrypted, ToDecrypt};
5pub use crate::crypto::{
6    alg::KeyAlg,
7    backend::KeyBackend,
8    buffer::{SecretBytes, WriteBuffer},
9    encrypt::KeyAeadParams,
10};
11use crate::{
12    crypto::{
13        alg::{bls::BlsKeyGen, AnyKey, AnyKeyCreate},
14        encrypt::KeyAeadInPlace,
15        jwk::{FromJwk, ToJwk},
16        kdf::{KeyDerivation, KeyExchange},
17        random::{fill_random, RandomDet},
18        repr::{ToPublicBytes, ToSecretBytes},
19        sign::{KeySigVerify, KeySign, SignatureType},
20        Error as CryptoError,
21    },
22    error::Error,
23};
24
25#[cfg(feature = "mobile_secure_element")]
26use crate::crypto::alg::p256_hardware::P256HardwareKeyPair;
27
28/// A stored key entry
29#[derive(Debug)]
30pub struct LocalKey {
31    pub(crate) inner: Box<AnyKey>,
32    pub(crate) ephemeral: bool,
33}
34
35impl LocalKey {
36    /// Create a new random key or keypair
37    pub fn generate_with_rng(alg: KeyAlg, ephemeral: bool) -> Result<Self, Error> {
38        let inner = Box::<AnyKey>::random(alg)?;
39        Ok(Self { inner, ephemeral })
40    }
41
42    /// Create a new random keypair backed by hardware
43    pub fn generate_for_hardware(alg: KeyAlg, ephemeral: bool) -> Result<Self, Error> {
44        let inner = Box::<AnyKey>::generate_for_hardware(alg)?;
45        Ok(Self { inner, ephemeral })
46    }
47
48    /// Get a local key by id
49    pub fn from_id(alg: KeyAlg, id: &str) -> Result<Self, Error> {
50        let inner = Box::<AnyKey>::get_with_id(alg, id)?;
51        Ok(Self {
52            inner,
53            ephemeral: false,
54        })
55    }
56
57    /// Create a new deterministic key or keypair
58    pub fn from_seed(alg: KeyAlg, seed: &[u8], method: Option<&str>) -> Result<Self, Error> {
59        let inner = match method {
60            Some("bls_keygen") => Box::<AnyKey>::generate_with_rng(alg, BlsKeyGen::new(seed)?)?,
61            None | Some("") => Box::<AnyKey>::generate_with_rng(alg, RandomDet::new(seed))?,
62            _ => {
63                return Err(err_msg!(
64                    Unsupported,
65                    "Unknown seed method for key generation"
66                ))
67            }
68        };
69        Ok(Self {
70            inner,
71            ephemeral: false,
72        })
73    }
74
75    /// Import a key or keypair from a JWK in binary format
76    pub fn from_jwk_slice(jwk: &[u8]) -> Result<Self, Error> {
77        let inner = Box::<AnyKey>::from_jwk_slice(jwk)?;
78        Ok(Self {
79            inner,
80            ephemeral: false,
81        })
82    }
83
84    /// Import a key or keypair from a JWK
85    pub fn from_jwk(jwk: &str) -> Result<Self, Error> {
86        let inner = Box::<AnyKey>::from_jwk(jwk)?;
87        Ok(Self {
88            inner,
89            ephemeral: false,
90        })
91    }
92
93    /// Import a public key from its compact representation
94    pub fn from_public_bytes(alg: KeyAlg, public: &[u8]) -> Result<Self, Error> {
95        let inner = Box::<AnyKey>::from_public_bytes(alg, public)?;
96        Ok(Self {
97            inner,
98            ephemeral: false,
99        })
100    }
101
102    /// Export the raw bytes of the public key
103    pub fn to_public_bytes(&self) -> Result<SecretBytes, Error> {
104        Ok(self.inner.to_public_bytes()?)
105    }
106
107    /// Import a symmetric key or public-private keypair from its compact representation
108    pub fn from_secret_bytes(alg: KeyAlg, secret: &[u8]) -> Result<Self, Error> {
109        let inner = Box::<AnyKey>::from_secret_bytes(alg, secret)?;
110        Ok(Self {
111            inner,
112            ephemeral: false,
113        })
114    }
115
116    /// Export the raw bytes of the private key
117    pub fn to_secret_bytes(&self) -> Result<SecretBytes, Error> {
118        Ok(self.inner.to_secret_bytes()?)
119    }
120
121    /// Derive a new key from a Diffie-Hellman exchange between this keypair and a public key
122    pub fn to_key_exchange(&self, alg: KeyAlg, pk: &LocalKey) -> Result<Self, Error> {
123        let inner = Box::<AnyKey>::from_key_exchange(alg, &*self.inner, &*pk.inner)?;
124        Ok(Self {
125            inner,
126            ephemeral: self.ephemeral || pk.ephemeral,
127        })
128    }
129
130    pub(crate) fn from_key_derivation(
131        alg: KeyAlg,
132        derive: impl KeyDerivation,
133    ) -> Result<Self, Error> {
134        let inner = Box::<AnyKey>::from_key_derivation(alg, derive)?;
135        Ok(Self {
136            inner,
137            ephemeral: false,
138        })
139    }
140
141    pub(crate) fn encode(&self) -> Result<SecretBytes, Error> {
142        Ok(self.inner.to_jwk_secret(None)?)
143    }
144
145    /// Accessor for the key algorithm
146    pub fn algorithm(&self) -> KeyAlg {
147        self.inner.algorithm()
148    }
149
150    /// Get the public JWK representation for this key or keypair
151    pub fn to_jwk_public(&self, alg: Option<KeyAlg>) -> Result<String, Error> {
152        Ok(self.inner.to_jwk_public(alg)?)
153    }
154
155    /// Get the JWK representation for this private key or keypair
156    pub fn to_jwk_secret(&self) -> Result<SecretBytes, Error> {
157        Ok(self.inner.to_jwk_secret(None)?)
158    }
159
160    /// Get the JWK thumbprint for this key or keypair
161    pub fn to_jwk_thumbprint(&self, alg: Option<KeyAlg>) -> Result<String, Error> {
162        Ok(self.inner.to_jwk_thumbprint(alg)?)
163    }
164
165    /// Get the set of indexed JWK thumbprints for this key or keypair
166    pub fn to_jwk_thumbprints(&self) -> Result<Vec<String>, Error> {
167        Ok(vec![self.inner.to_jwk_thumbprint(None)?])
168    }
169
170    /// Map this key or keypair to its equivalent for another key algorithm
171    pub fn convert_key(&self, alg: KeyAlg) -> Result<Self, Error> {
172        let inner = self.inner.convert_key(alg)?;
173        Ok(Self {
174            inner,
175            ephemeral: self.ephemeral,
176        })
177    }
178
179    /// Fetch the AEAD parameter lengths
180    pub fn aead_params(&self) -> Result<KeyAeadParams, Error> {
181        let params = self.inner.aead_params();
182        if params.tag_length == 0 {
183            return Err(err_msg!(
184                Unsupported,
185                "AEAD is not supported for this key type"
186            ));
187        }
188        Ok(params)
189    }
190
191    /// Calculate the padding required for a message
192    pub fn aead_padding(&self, msg_len: usize) -> usize {
193        self.inner.aead_padding(msg_len)
194    }
195
196    /// Create a new random nonce for AEAD message encryption
197    pub fn aead_random_nonce(&self) -> Result<Vec<u8>, Error> {
198        let nonce_len = self.inner.aead_params().nonce_length;
199        if nonce_len == 0 {
200            return Ok(Vec::new());
201        }
202        let mut buf = vec![0; nonce_len];
203        fill_random(&mut buf);
204        Ok(buf)
205    }
206
207    /// Perform AEAD message encryption with this encryption key
208    pub fn aead_encrypt(
209        &self,
210        message: &[u8],
211        nonce: &[u8],
212        aad: &[u8],
213    ) -> Result<Encrypted, Error> {
214        let params = self.inner.aead_params();
215        let mut nonce = Cow::Borrowed(nonce);
216        if nonce.is_empty() && params.nonce_length > 0 {
217            nonce = Cow::Owned(self.aead_random_nonce()?);
218        }
219        let pad_len = self.inner.aead_padding(message.len());
220        let mut buf =
221            SecretBytes::from_slice_reserve(message, pad_len + params.tag_length + nonce.len());
222        let tag_pos = self.inner.encrypt_in_place(&mut buf, nonce.as_ref(), aad)?;
223        let nonce_pos = buf.len();
224        if !nonce.is_empty() {
225            buf.extend_from_slice(nonce.as_ref());
226        }
227        Ok(Encrypted::new(buf, tag_pos, nonce_pos))
228    }
229
230    /// Perform AEAD message decryption with this encryption key
231    pub fn aead_decrypt<'d>(
232        &'d self,
233        ciphertext: impl Into<ToDecrypt<'d>>,
234        nonce: &[u8],
235        aad: &[u8],
236    ) -> Result<SecretBytes, Error> {
237        let mut buf = ciphertext.into().into_secret();
238        self.inner.decrypt_in_place(&mut buf, nonce, aad)?;
239        Ok(buf)
240    }
241
242    /// Sign a message with this private signing key
243    pub fn sign_message(&self, message: &[u8], sig_type: Option<&str>) -> Result<Vec<u8>, Error> {
244        let mut sig = Vec::new();
245        self.inner.write_signature(
246            message,
247            sig_type.map(SignatureType::from_str).transpose()?,
248            &mut sig,
249        )?;
250        Ok(sig)
251    }
252
253    /// Verify a message signature with this private signing key or public verification key
254    pub fn verify_signature(
255        &self,
256        message: &[u8],
257        signature: &[u8],
258        sig_type: Option<&str>,
259    ) -> Result<bool, Error> {
260        Ok(self.inner.verify_signature(
261            message,
262            signature,
263            sig_type.map(SignatureType::from_str).transpose()?,
264        )?)
265    }
266
267    /// Wrap another key using this key
268    pub fn wrap_key(&self, key: &LocalKey, nonce: &[u8]) -> Result<Encrypted, Error> {
269        let params = self.inner.aead_params();
270        let mut buf = SecretBytes::with_capacity(
271            key.inner.secret_bytes_length()? + params.tag_length + params.nonce_length,
272        );
273        key.inner.write_secret_bytes(&mut buf)?;
274        let tag_pos = self.inner.encrypt_in_place(&mut buf, nonce, &[])?;
275        let nonce_pos = buf.len();
276        buf.extend_from_slice(nonce);
277        Ok(Encrypted::new(buf, tag_pos, nonce_pos))
278    }
279
280    /// Unwrap a key using this key
281    pub fn unwrap_key<'d>(
282        &'d self,
283        alg: KeyAlg,
284        ciphertext: impl Into<ToDecrypt<'d>>,
285        nonce: &[u8],
286    ) -> Result<LocalKey, Error> {
287        let mut buf = ciphertext.into().into_secret();
288        self.inner.decrypt_in_place(&mut buf, nonce, &[])?;
289        Self::from_secret_bytes(alg, buf.as_ref())
290    }
291
292    /// Check whether the key is hardware backed by checking the type id of the underlying
293    /// structure
294    pub fn is_hardware_backed(&self) -> bool {
295        #[cfg(feature = "mobile_secure_element")]
296        return self.inner.downcast_ref::<P256HardwareKeyPair>().is_some();
297
298        #[cfg(not(feature = "mobile_secure_element"))]
299        false
300    }
301}
302
303impl KeyExchange for LocalKey {
304    fn write_key_exchange(
305        &self,
306        other: &LocalKey,
307        out: &mut dyn WriteBuffer,
308    ) -> Result<(), CryptoError> {
309        self.inner.write_key_exchange(&other.inner, out)
310    }
311}