Skip to main content

script/dom/webcrypto/
cryptokey.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::cell::Cell;
6use std::str::FromStr;
7
8use dom_struct::dom_struct;
9use js::context::NoGC;
10use js::jsapi::{Heap, JSObject, Value};
11use js::rust::MutableHandleObject;
12use malloc_size_of::MallocSizeOf;
13use rustc_hash::FxHashMap;
14use script_bindings::cell::{DomRefCell, Ref};
15use script_bindings::conversions::SafeToJSValConvertible;
16use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
17use servo_base::id::{CryptoKeyId, CryptoKeyIndex};
18use servo_constellation_traits::{SerializableCryptoKey, SerializableCryptoKeyHandle};
19use zeroize::Zeroizing;
20
21use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
22    CryptoKeyMethods, CryptoKeyPair, KeyType, KeyUsage,
23};
24use crate::dom::bindings::root::DomRoot;
25use crate::dom::bindings::serializable::Serializable;
26use crate::dom::bindings::structuredclone::StructuredData;
27use crate::dom::globalscope::GlobalScope;
28use crate::dom::subtlecrypto::KeyAlgorithmAndDerivatives;
29
30pub(crate) enum CryptoKeyOrCryptoKeyPair {
31    CryptoKey(DomRoot<CryptoKey>),
32    CryptoKeyPair(CryptoKeyPair),
33}
34
35/// The underlying cryptographic data this key represents.
36///
37/// Please make sure the inner types for secret variants implement the `zeroize::ZeroizeOnDrop`
38/// trait, which signifies that the type will call `Zeroize::zeroize` on `Drop` to securely erase
39/// the secret from memory.
40pub(crate) enum Handle {
41    RsaPrivateKey(rsa::RsaPrivateKey),
42    RsaPublicKey(rsa::RsaPublicKey),
43    P256PrivateKey(p256::SecretKey),
44    P384PrivateKey(p384::SecretKey),
45    P521PrivateKey(p521::SecretKey),
46    P256PublicKey(p256::PublicKey),
47    P384PublicKey(p384::PublicKey),
48    P521PublicKey(p521::PublicKey),
49    Ed25519PrivateKey(ed25519_dalek::SigningKey),
50    Ed25519PublicKey(ed25519_dalek::VerifyingKey),
51    X25519PrivateKey(x25519_dalek::StaticSecret),
52    X25519PublicKey(x25519_dalek::PublicKey),
53    Ed448PrivateKey(ed448_goldilocks::SigningKey),
54    Ed448PublicKey(ed448_goldilocks::VerifyingKey),
55    X448PrivateKey(x448::StaticSecret),
56    X448PublicKey(x448::PublicKey),
57    Aes128Key(aes::cipher::common::Key<aes::Aes128>),
58    Aes192Key(aes::cipher::common::Key<aes::Aes192>),
59    Aes256Key(aes::cipher::common::Key<aes::Aes256>),
60    HkdfSecret(Zeroizing<Vec<u8>>),
61    Pbkdf2(Zeroizing<Vec<u8>>),
62    Hmac(Zeroizing<Vec<u8>>),
63    MlKem512PrivateKey(ml_kem::DecapsulationKey<ml_kem::MlKem512>),
64    MlKem768PrivateKey(ml_kem::DecapsulationKey<ml_kem::MlKem768>),
65    MlKem1024PrivateKey(ml_kem::DecapsulationKey<ml_kem::MlKem1024>),
66    MlKem512PublicKey(ml_kem::EncapsulationKey<ml_kem::MlKem512>),
67    MlKem768PublicKey(ml_kem::EncapsulationKey<ml_kem::MlKem768>),
68    MlKem1024PublicKey(ml_kem::EncapsulationKey<ml_kem::MlKem1024>),
69    MlDsa44PrivateKey(ml_dsa::SigningKey<ml_dsa::MlDsa44>),
70    MlDsa65PrivateKey(ml_dsa::SigningKey<ml_dsa::MlDsa65>),
71    MlDsa87PrivateKey(ml_dsa::SigningKey<ml_dsa::MlDsa87>),
72    MlDsa44PublicKey(ml_dsa::VerifyingKey<ml_dsa::MlDsa44>),
73    MlDsa65PublicKey(ml_dsa::VerifyingKey<ml_dsa::MlDsa65>),
74    MlDsa87PublicKey(ml_dsa::VerifyingKey<ml_dsa::MlDsa87>),
75    ChaCha20Poly1305Key(chacha20poly1305::Key),
76    KmacKey(Zeroizing<Vec<u8>>),
77    Argon2Password(Zeroizing<Vec<u8>>),
78}
79
80/// <https://w3c.github.io/webcrypto/#cryptokey-interface>
81#[dom_struct]
82pub(crate) struct CryptoKey {
83    reflector_: Reflector,
84
85    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-type>
86    key_type: KeyType,
87
88    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-extractable>
89    extractable: Cell<bool>,
90
91    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-algorithm>
92    ///
93    /// The contents of the [[algorithm]] internal slot shall be, or be derived from, a
94    /// KeyAlgorithm.
95    #[no_trace]
96    algorithm: KeyAlgorithmAndDerivatives,
97
98    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-algorithm_cached>
99    #[ignore_malloc_size_of = "Defined in mozjs"]
100    algorithm_cached: Heap<*mut JSObject>,
101
102    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-usages>
103    ///
104    /// The contents of the [[usages]] internal slot shall be of type Sequence<KeyUsage>.
105    usages: DomRefCell<Vec<KeyUsage>>,
106
107    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-usages_cached>
108    #[ignore_malloc_size_of = "Defined in mozjs"]
109    usages_cached: Heap<*mut JSObject>,
110
111    /// <https://w3c.github.io/webcrypto/#dfn-CryptoKey-slot-handle>
112    #[no_trace]
113    handle: Handle,
114}
115
116impl CryptoKey {
117    fn new_inherited(
118        key_type: KeyType,
119        extractable: bool,
120        algorithm: KeyAlgorithmAndDerivatives,
121        usages: Vec<KeyUsage>,
122        handle: Handle,
123    ) -> CryptoKey {
124        CryptoKey {
125            reflector_: Reflector::new(),
126            key_type,
127            extractable: Cell::new(extractable),
128            algorithm,
129            algorithm_cached: Heap::default(),
130            usages: DomRefCell::new(usages),
131            usages_cached: Heap::default(),
132            handle,
133        }
134    }
135
136    pub(crate) fn new(
137        cx: &mut js::context::JSContext,
138        global: &GlobalScope,
139        key_type: KeyType,
140        extractable: bool,
141        algorithm: KeyAlgorithmAndDerivatives,
142        usages: Vec<KeyUsage>,
143        handle: Handle,
144    ) -> DomRoot<CryptoKey> {
145        let crypto_key = reflect_dom_object_with_cx(
146            Box::new(CryptoKey::new_inherited(
147                key_type,
148                extractable,
149                algorithm.clone(),
150                usages.clone(),
151                handle,
152            )),
153            global,
154            cx,
155        );
156
157        // Create and store a cached object of algorithm
158        rooted!(&in(cx) let mut algorithm_object_value: Value);
159        algorithm.safe_to_jsval(cx, algorithm_object_value.handle_mut());
160        crypto_key
161            .algorithm_cached
162            .set(algorithm_object_value.to_object());
163
164        // Create and store a cached object of usages
165        rooted!(&in(cx) let mut usages_object_value: Value);
166        usages.safe_to_jsval(cx, usages_object_value.handle_mut());
167        crypto_key
168            .usages_cached
169            .set(usages_object_value.to_object());
170
171        crypto_key
172    }
173
174    pub(crate) fn algorithm(&self) -> &KeyAlgorithmAndDerivatives {
175        &self.algorithm
176    }
177
178    pub(crate) fn usages(&self) -> Ref<'_, Vec<KeyUsage>> {
179        self.usages.borrow()
180    }
181
182    pub(crate) fn handle(&self) -> &Handle {
183        &self.handle
184    }
185
186    pub(crate) fn set_extractable(&self, extractable: bool) {
187        self.extractable.set(extractable);
188    }
189
190    pub(crate) fn set_usages(&self, cx: &mut js::context::JSContext, usages: &[KeyUsage]) {
191        *self.usages.borrow_mut() = usages.to_owned();
192
193        // Create and store a cached object of usages
194        rooted!(&in(cx) let mut usages_object_value: Value);
195        usages.safe_to_jsval(cx, usages_object_value.handle_mut());
196        self.usages_cached.set(usages_object_value.to_object());
197    }
198}
199
200impl CryptoKeyMethods<crate::DomTypeHolder> for CryptoKey {
201    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-type>
202    fn Type(&self) -> KeyType {
203        // Reflects the [[type]] internal slot, which contains the type of the underlying key.
204        self.key_type
205    }
206
207    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-extractable>
208    fn Extractable(&self) -> bool {
209        // Reflects the [[extractable]] internal slot, which indicates whether or not the raw
210        // keying material may be exported by the application.
211        self.extractable.get()
212    }
213
214    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-algorithm>
215    fn Algorithm(&self, mut return_value: MutableHandleObject) {
216        // Returns the cached ECMAScript object associated with the [[algorithm]] internal slot.
217        return_value.set(self.algorithm_cached.get())
218    }
219
220    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
221    fn Usages(&self, mut return_value: MutableHandleObject) {
222        // Returns the cached ECMAScript object associated with the [[usages]] internal slot, which
223        // indicates which cryptographic operations are permissible to be used with this key.
224        return_value.set(self.usages_cached.get())
225    }
226}
227
228impl Serializable for CryptoKey {
229    type Index = CryptoKeyIndex;
230    type Data = SerializableCryptoKey;
231
232    /// <https://w3c.github.io/webcrypto/#cryptokey-interface-serializable>
233    fn serialize(&self, _no_gc: &NoGC) -> Result<(CryptoKeyId, Self::Data), ()> {
234        // Step 1. Set serialized.[[Type]] to the [[type]] internal slot of value.
235        // Step 2. Set serialized.[[Extractable]] to the [[extractable]] internal slot of value.
236        // Step 3. Set serialized.[[Algorithm]] to the sub-serialization of the [[algorithm]]
237        // internal slot of value.
238        // Step 4. Set serialized.[[Usages]] to the sub-serialization of the [[usages]] internal
239        // slot of value.
240        // Step 5. Set serialized.[[Handle]] to the [[handle]] internal slot of value.
241        let serialized = SerializableCryptoKey {
242            key_type: self.key_type.as_str().into(),
243            extractable: self.extractable.get(),
244            algorithm: (&self.algorithm).into(),
245            usages: self
246                .usages
247                .borrow()
248                .iter()
249                .map(|usage| usage.as_str().into())
250                .collect(),
251            handle: (&self.handle).try_into()?,
252        };
253        Ok((CryptoKeyId::new(), serialized))
254    }
255
256    /// <https://w3c.github.io/webcrypto/#cryptokey-interface-serializable>
257    fn deserialize(
258        cx: &mut js::context::JSContext,
259        owner: &GlobalScope,
260        serialized: Self::Data,
261    ) -> Result<DomRoot<Self>, ()> {
262        // Step 1. Initialize the [[type]] internal slot of value to serialized.[[Type]].
263        // Step 2. Initialize the [[extractable]] internal slot of value to
264        // serialized.[[Extractable]].
265        // Step 3. Initialize the [[algorithm]] internal slot of value to the sub-deserialization of
266        // serialized.[[Algorithm]].
267        // Step 4. Initialize the [[usages]] internal slot of value to the sub-deserialization of
268        // serialized.[[Usages]].
269        // Step 5. Initialize the [[handle]] internal slot of value to serialized.[[Handle]].
270        Ok(CryptoKey::new(
271            cx,
272            owner,
273            KeyType::from_str(&serialized.key_type)?,
274            serialized.extractable,
275            serialized.algorithm.try_into()?,
276            serialized
277                .usages
278                .iter()
279                .map(|usage| KeyUsage::from_str(usage))
280                .collect::<Result<Vec<_>, _>>()?,
281            serialized.handle.try_into()?,
282        ))
283    }
284
285    fn serialized_storage<'a>(
286        reader: StructuredData<'a, '_>,
287    ) -> &'a mut Option<FxHashMap<CryptoKeyId, Self::Data>> {
288        match reader {
289            StructuredData::Reader(reader) => &mut reader.crypto_keys,
290            StructuredData::Writer(writer) => &mut writer.crypto_keys,
291        }
292    }
293}
294
295impl Handle {
296    pub(crate) fn as_bytes(&self) -> &[u8] {
297        match self {
298            Self::Pbkdf2(bytes) => bytes,
299            Self::Hmac(bytes) => bytes,
300            _ => unreachable!(),
301        }
302    }
303}
304
305impl MallocSizeOf for Handle {
306    fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
307        match self {
308            Handle::RsaPrivateKey(private_key) => private_key.size_of(ops),
309            Handle::RsaPublicKey(public_key) => public_key.size_of(ops),
310            Handle::P256PrivateKey(private_key) => private_key.size_of(ops),
311            Handle::P384PrivateKey(private_key) => private_key.size_of(ops),
312            Handle::P521PrivateKey(private_key) => private_key.size_of(ops),
313            Handle::P256PublicKey(public_key) => public_key.size_of(ops),
314            Handle::P384PublicKey(public_key) => public_key.size_of(ops),
315            Handle::P521PublicKey(public_key) => public_key.size_of(ops),
316            Handle::Ed25519PrivateKey(bytes) => bytes.size_of(ops),
317            Handle::Ed25519PublicKey(bytes) => bytes.size_of(ops),
318            Handle::X25519PrivateKey(private_key) => private_key.size_of(ops),
319            Handle::X25519PublicKey(public_key) => public_key.size_of(ops),
320            Handle::Ed448PrivateKey(private_key) => private_key.size_of(ops),
321            Handle::Ed448PublicKey(public_key) => public_key.size_of(ops),
322            Handle::X448PrivateKey(private_key) => private_key.size_of(ops),
323            Handle::X448PublicKey(public_key) => public_key.size_of(ops),
324            Handle::Aes128Key(key) => key.size_of(ops),
325            Handle::Aes192Key(key) => key.size_of(ops),
326            Handle::Aes256Key(key) => key.size_of(ops),
327            Handle::HkdfSecret(secret) => secret.size_of(ops),
328            Handle::Pbkdf2(bytes) => bytes.size_of(ops),
329            Handle::Hmac(bytes) => bytes.size_of(ops),
330            Handle::MlKem512PrivateKey(private_key) => private_key.size_of(ops),
331            Handle::MlKem768PrivateKey(private_key) => private_key.size_of(ops),
332            Handle::MlKem1024PrivateKey(private_key) => private_key.size_of(ops),
333            Handle::MlKem512PublicKey(public_key) => public_key.size_of(ops),
334            Handle::MlKem768PublicKey(public_key) => public_key.size_of(ops),
335            Handle::MlKem1024PublicKey(public_key) => public_key.size_of(ops),
336            Handle::MlDsa44PrivateKey(private_key) => private_key.size_of(ops),
337            Handle::MlDsa65PrivateKey(private_key) => private_key.size_of(ops),
338            Handle::MlDsa87PrivateKey(private_key) => private_key.size_of(ops),
339            Handle::MlDsa44PublicKey(public_key) => public_key.size_of(ops),
340            Handle::MlDsa65PublicKey(public_key) => public_key.size_of(ops),
341            Handle::MlDsa87PublicKey(public_key) => public_key.size_of(ops),
342            Handle::ChaCha20Poly1305Key(key) => key.size_of(ops),
343            Handle::KmacKey(key) => key.size_of(ops),
344            Handle::Argon2Password(password) => password.size_of(ops),
345        }
346    }
347}
348
349impl TryFrom<SerializableCryptoKeyHandle> for Handle {
350    type Error = ();
351
352    fn try_from(value: SerializableCryptoKeyHandle) -> Result<Self, Self::Error> {
353        match &value {
354            SerializableCryptoKeyHandle::RsaPrivateKey(private_key) => Ok(Handle::RsaPrivateKey(
355                rsa::pkcs8::DecodePrivateKey::from_pkcs8_der(private_key).map_err(|_| ())?,
356            )),
357            SerializableCryptoKeyHandle::RsaPublicKey(public_key) => Ok(Handle::RsaPublicKey(
358                rsa::pkcs8::spki::DecodePublicKey::from_public_key_der(public_key)
359                    .map_err(|_| ())?,
360            )),
361            SerializableCryptoKeyHandle::P256PrivateKey(private_key) => Ok(Handle::P256PrivateKey(
362                p256::SecretKey::from_slice(private_key).map_err(|_| ())?,
363            )),
364            SerializableCryptoKeyHandle::P384PrivateKey(private_key) => Ok(Handle::P384PrivateKey(
365                p384::SecretKey::from_slice(private_key).map_err(|_| ())?,
366            )),
367            SerializableCryptoKeyHandle::P521PrivateKey(private_key) => Ok(Handle::P521PrivateKey(
368                p521::SecretKey::from_slice(private_key).map_err(|_| ())?,
369            )),
370            SerializableCryptoKeyHandle::P256PublicKey(public_key) => Ok(Handle::P256PublicKey(
371                p256::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
372            )),
373            SerializableCryptoKeyHandle::P384PublicKey(public_key) => Ok(Handle::P384PublicKey(
374                p384::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
375            )),
376            SerializableCryptoKeyHandle::P521PublicKey(public_key) => Ok(Handle::P521PublicKey(
377                p521::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
378            )),
379            SerializableCryptoKeyHandle::Ed25519PrivateKey(private_key) => Ok(
380                Handle::Ed25519PrivateKey(ed25519_dalek::SigningKey::from_bytes(private_key)),
381            ),
382            SerializableCryptoKeyHandle::Ed25519PublicKey(public_key) => {
383                Ok(Handle::Ed25519PublicKey(
384                    ed25519_dalek::VerifyingKey::from_bytes(public_key).map_err(|_| ())?,
385                ))
386            },
387            SerializableCryptoKeyHandle::X25519PrivateKey(private_key) => {
388                Ok(Handle::X25519PrivateKey((*private_key).into()))
389            },
390            SerializableCryptoKeyHandle::X25519PublicKey(public_key) => {
391                Ok(Handle::X25519PublicKey((*public_key).into()))
392            },
393            SerializableCryptoKeyHandle::Ed448PrivateKey(private_key) => {
394                Ok(Handle::Ed448PrivateKey(
395                    ed448_goldilocks::SigningKey::try_from(private_key).map_err(|_| ())?,
396                ))
397            },
398            SerializableCryptoKeyHandle::Ed448PublicKey(public_key) => Ok(Handle::Ed448PublicKey(
399                ed448_goldilocks::VerifyingKey::from_bytes(
400                    public_key.as_slice().try_into().map_err(|_| ())?,
401                )
402                .map_err(|_| ())?,
403            )),
404            SerializableCryptoKeyHandle::X448PrivateKey(private_key) => {
405                Ok(Handle::X448PrivateKey(x448::StaticSecret::from(
406                    <[u8; 56]>::try_from(private_key.as_slice()).map_err(|_| ())?,
407                )))
408            },
409            SerializableCryptoKeyHandle::X448PublicKey(public_key) => Ok(Handle::X448PublicKey(
410                x448::PublicKey::from_bytes_unchecked(public_key).ok_or(())?,
411            )),
412            SerializableCryptoKeyHandle::Aes128Key(key) => Ok(Handle::Aes128Key(
413                aes::cipher::common::Key::<aes::Aes128>::try_from(key).map_err(|_| ())?,
414            )),
415            SerializableCryptoKeyHandle::Aes192Key(key) => Ok(Handle::Aes192Key(
416                aes::cipher::common::Key::<aes::Aes192>::try_from(key).map_err(|_| ())?,
417            )),
418            SerializableCryptoKeyHandle::Aes256Key(key) => Ok(Handle::Aes256Key(
419                aes::cipher::common::Key::<aes::Aes256>::try_from(key).map_err(|_| ())?,
420            )),
421            SerializableCryptoKeyHandle::Hmac(bytes) => Ok(Handle::Hmac(bytes.clone().into())),
422            SerializableCryptoKeyHandle::HkdfSecret(bytes) => {
423                Ok(Handle::HkdfSecret(bytes.clone().into()))
424            },
425            SerializableCryptoKeyHandle::Pbkdf2(bytes) => Ok(Handle::Pbkdf2(bytes.clone().into())),
426            SerializableCryptoKeyHandle::MlKem512PrivateKey(private_key) => {
427                Ok(Handle::MlKem512PrivateKey(
428                    ml_kem::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
429                ))
430            },
431            SerializableCryptoKeyHandle::MlKem768PrivateKey(private_key) => {
432                Ok(Handle::MlKem768PrivateKey(
433                    ml_kem::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
434                ))
435            },
436            SerializableCryptoKeyHandle::MlKem1024PrivateKey(private_key) => {
437                Ok(Handle::MlKem1024PrivateKey(
438                    ml_kem::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
439                ))
440            },
441            SerializableCryptoKeyHandle::MlKem512PublicKey(public_key) => {
442                Ok(Handle::MlKem512PublicKey(
443                    ml_kem::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
444                ))
445            },
446            SerializableCryptoKeyHandle::MlKem768PublicKey(public_key) => {
447                Ok(Handle::MlKem768PublicKey(
448                    ml_kem::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
449                ))
450            },
451            SerializableCryptoKeyHandle::MlKem1024PublicKey(public_key) => {
452                Ok(Handle::MlKem1024PublicKey(
453                    ml_kem::TryKeyInit::new_from_slice(public_key).map_err(|_| ())?,
454                ))
455            },
456            SerializableCryptoKeyHandle::MlDsa44PrivateKey(private_key) => {
457                Ok(Handle::MlDsa44PrivateKey(
458                    ml_dsa::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
459                ))
460            },
461            SerializableCryptoKeyHandle::MlDsa65PrivateKey(private_key) => {
462                Ok(Handle::MlDsa65PrivateKey(
463                    ml_dsa::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
464                ))
465            },
466            SerializableCryptoKeyHandle::MlDsa87PrivateKey(private_key) => {
467                Ok(Handle::MlDsa87PrivateKey(
468                    ml_dsa::KeyInit::new_from_slice(private_key).map_err(|_| ())?,
469                ))
470            },
471            SerializableCryptoKeyHandle::MlDsa44PublicKey(public_key) => {
472                Ok(Handle::MlDsa44PublicKey(
473                    ml_dsa::KeyInit::new_from_slice(public_key).map_err(|_| ())?,
474                ))
475            },
476            SerializableCryptoKeyHandle::MlDsa65PublicKey(public_key) => {
477                Ok(Handle::MlDsa65PublicKey(
478                    ml_dsa::KeyInit::new_from_slice(public_key).map_err(|_| ())?,
479                ))
480            },
481            SerializableCryptoKeyHandle::MlDsa87PublicKey(public_key) => {
482                Ok(Handle::MlDsa87PublicKey(
483                    ml_dsa::KeyInit::new_from_slice(public_key).map_err(|_| ())?,
484                ))
485            },
486            SerializableCryptoKeyHandle::ChaCha20Poly1305Key(key) => Ok(
487                Handle::ChaCha20Poly1305Key(chacha20poly1305::Key::try_from(key).map_err(|_| ())?),
488            ),
489            SerializableCryptoKeyHandle::KmacKey(key) => Ok(Handle::KmacKey(key.clone().into())),
490            SerializableCryptoKeyHandle::Argon2Password(password) => {
491                Ok(Handle::Argon2Password(password.clone().into()))
492            },
493        }
494    }
495}
496
497/// To serialize the key in the `Handle`, we convert the key into byte sequences. For most
498/// cryptographic algorithms, this conversion is straightforward since the key can natually be
499/// expressed as a byte sequence. However, some cryptographic algorithms require preprocessing
500/// before their key can be represented in byte sequences. For example, an RSA private key needs to
501/// be first converted into DER-encoded PKCS#8 format before it can be expressed as a byte sequence.
502impl TryFrom<&Handle> for SerializableCryptoKeyHandle {
503    type Error = ();
504
505    fn try_from(value: &Handle) -> Result<Self, Self::Error> {
506        match value {
507            Handle::RsaPrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::RsaPrivateKey(
508                rsa::pkcs8::EncodePrivateKey::to_pkcs8_der(private_key)
509                    .map_err(|_| ())?
510                    .as_bytes()
511                    .to_vec(),
512            )),
513            Handle::RsaPublicKey(public_key) => Ok(SerializableCryptoKeyHandle::RsaPublicKey(
514                rsa::pkcs8::spki::EncodePublicKey::to_public_key_der(public_key)
515                    .map_err(|_| ())?
516                    .into_vec(),
517            )),
518            Handle::P256PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P256PrivateKey(
519                private_key.to_bytes().as_slice().to_vec(),
520            )),
521            Handle::P384PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P384PrivateKey(
522                private_key.to_bytes().as_slice().to_vec(),
523            )),
524            Handle::P521PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P521PrivateKey(
525                private_key.to_bytes().as_slice().to_vec(),
526            )),
527            Handle::P256PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P256PublicKey(
528                public_key.to_sec1_bytes().to_vec(),
529            )),
530            Handle::P384PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P384PublicKey(
531                public_key.to_sec1_bytes().to_vec(),
532            )),
533            Handle::P521PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P521PublicKey(
534                public_key.to_sec1_bytes().to_vec(),
535            )),
536            Handle::Ed25519PrivateKey(private_key) => Ok(
537                SerializableCryptoKeyHandle::Ed25519PrivateKey(private_key.to_bytes()),
538            ),
539            Handle::Ed25519PublicKey(public_key) => Ok(
540                SerializableCryptoKeyHandle::Ed25519PublicKey(public_key.to_bytes()),
541            ),
542            Handle::X25519PrivateKey(private_key) => Ok(
543                SerializableCryptoKeyHandle::X25519PrivateKey(private_key.to_bytes()),
544            ),
545            Handle::X25519PublicKey(public_key) => Ok(
546                SerializableCryptoKeyHandle::X25519PublicKey(public_key.to_bytes()),
547            ),
548            Handle::Ed448PrivateKey(private_key) => Ok(
549                SerializableCryptoKeyHandle::Ed448PrivateKey(private_key.as_bytes().to_vec()),
550            ),
551            Handle::Ed448PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::Ed448PublicKey(
552                public_key.as_bytes().to_vec(),
553            )),
554            Handle::X448PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::X448PrivateKey(
555                private_key.as_bytes().to_vec(),
556            )),
557            Handle::X448PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::X448PublicKey(
558                public_key.as_bytes().to_vec(),
559            )),
560            Handle::Aes128Key(key) => Ok(SerializableCryptoKeyHandle::Aes128Key(key.to_vec())),
561            Handle::Aes192Key(key) => Ok(SerializableCryptoKeyHandle::Aes192Key(key.to_vec())),
562            Handle::Aes256Key(key) => Ok(SerializableCryptoKeyHandle::Aes256Key(key.to_vec())),
563            Handle::Hmac(bytes) => Ok(SerializableCryptoKeyHandle::Hmac(bytes.to_vec())),
564            Handle::HkdfSecret(bytes) => {
565                Ok(SerializableCryptoKeyHandle::HkdfSecret(bytes.to_vec()))
566            },
567            Handle::Pbkdf2(bytes) => Ok(SerializableCryptoKeyHandle::Pbkdf2(bytes.to_vec())),
568            Handle::MlKem512PrivateKey(private_key) => {
569                Ok(SerializableCryptoKeyHandle::MlKem512PrivateKey(
570                    private_key
571                        .to_seed()
572                        .expect("This decapsulation key should contain seed value")
573                        .as_slice()
574                        .to_vec(),
575                ))
576            },
577            Handle::MlKem768PrivateKey(private_key) => {
578                Ok(SerializableCryptoKeyHandle::MlKem768PrivateKey(
579                    private_key
580                        .to_seed()
581                        .expect("This decapsulation key should contain seed value")
582                        .as_slice()
583                        .to_vec(),
584                ))
585            },
586            Handle::MlKem1024PrivateKey(private_key) => {
587                Ok(SerializableCryptoKeyHandle::MlKem1024PrivateKey(
588                    private_key
589                        .to_seed()
590                        .expect("This decapsulation key should contain seed value")
591                        .as_slice()
592                        .to_vec(),
593                ))
594            },
595            Handle::MlKem512PublicKey(public_key) => {
596                Ok(SerializableCryptoKeyHandle::MlKem512PublicKey(
597                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
598                ))
599            },
600            Handle::MlKem768PublicKey(public_key) => {
601                Ok(SerializableCryptoKeyHandle::MlKem768PublicKey(
602                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
603                ))
604            },
605            Handle::MlKem1024PublicKey(public_key) => {
606                Ok(SerializableCryptoKeyHandle::MlKem1024PublicKey(
607                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
608                ))
609            },
610            Handle::MlDsa44PrivateKey(private_key) => {
611                Ok(SerializableCryptoKeyHandle::MlDsa44PrivateKey(
612                    private_key.as_seed().as_slice().to_vec(),
613                ))
614            },
615            Handle::MlDsa65PrivateKey(private_key) => {
616                Ok(SerializableCryptoKeyHandle::MlDsa65PrivateKey(
617                    private_key.as_seed().as_slice().to_vec(),
618                ))
619            },
620            Handle::MlDsa87PrivateKey(private_key) => {
621                Ok(SerializableCryptoKeyHandle::MlDsa87PrivateKey(
622                    private_key.as_seed().as_slice().to_vec(),
623                ))
624            },
625            Handle::MlDsa44PublicKey(public_key) => {
626                Ok(SerializableCryptoKeyHandle::MlDsa44PublicKey(
627                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
628                ))
629            },
630            Handle::MlDsa65PublicKey(public_key) => {
631                Ok(SerializableCryptoKeyHandle::MlDsa65PublicKey(
632                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
633                ))
634            },
635            Handle::MlDsa87PublicKey(public_key) => {
636                Ok(SerializableCryptoKeyHandle::MlDsa87PublicKey(
637                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
638                ))
639            },
640            Handle::ChaCha20Poly1305Key(key) => Ok(
641                SerializableCryptoKeyHandle::ChaCha20Poly1305Key(key.as_slice().to_vec()),
642            ),
643            Handle::KmacKey(key) => Ok(SerializableCryptoKeyHandle::KmacKey(key.to_vec())),
644            Handle::Argon2Password(password) => Ok(SerializableCryptoKeyHandle::Argon2Password(
645                password.to_vec(),
646            )),
647        }
648    }
649}