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