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