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