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::str::FromStr;
6
7use dom_struct::dom_struct;
8use js::context::NoGC;
9use js::conversions::ToJSValConvertible;
10use js::jsapi::{Heap, JSObject, Value};
11use js::rust::MutableHandleObject;
12use malloc_size_of::MallocSizeOf;
13use rustc_hash::FxHashMap;
14use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
15use servo_base::id::{CryptoKeyId, CryptoKeyIndex};
16use servo_constellation_traits::{SerializableCryptoKey, SerializableCryptoKeyHandle};
17use strum::VariantArray;
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    X448PrivateKey(x448::StaticSecret),
55    X448PublicKey(x448::PublicKey),
56    Aes128Key(aes::cipher::common::Key<aes::Aes128>),
57    Aes192Key(aes::cipher::common::Key<aes::Aes192>),
58    Aes256Key(aes::cipher::common::Key<aes::Aes256>),
59    HkdfSecret(Zeroizing<Vec<u8>>),
60    Pbkdf2(Zeroizing<Vec<u8>>),
61    Hmac(Zeroizing<Vec<u8>>),
62    MlKem512PrivateKey(ml_kem::DecapsulationKey<ml_kem::MlKem512>),
63    MlKem768PrivateKey(ml_kem::DecapsulationKey<ml_kem::MlKem768>),
64    MlKem1024PrivateKey(ml_kem::DecapsulationKey<ml_kem::MlKem1024>),
65    MlKem512PublicKey(ml_kem::EncapsulationKey<ml_kem::MlKem512>),
66    MlKem768PublicKey(ml_kem::EncapsulationKey<ml_kem::MlKem768>),
67    MlKem1024PublicKey(ml_kem::EncapsulationKey<ml_kem::MlKem1024>),
68    MlDsa44PrivateKey(ml_dsa::SigningKey<ml_dsa::MlDsa44>),
69    MlDsa65PrivateKey(ml_dsa::SigningKey<ml_dsa::MlDsa65>),
70    MlDsa87PrivateKey(ml_dsa::SigningKey<ml_dsa::MlDsa87>),
71    MlDsa44PublicKey(ml_dsa::VerifyingKey<ml_dsa::MlDsa44>),
72    MlDsa65PublicKey(ml_dsa::VerifyingKey<ml_dsa::MlDsa65>),
73    MlDsa87PublicKey(ml_dsa::VerifyingKey<ml_dsa::MlDsa87>),
74    ChaCha20Poly1305Key(chacha20poly1305::Key),
75    KmacKey(Zeroizing<Vec<u8>>),
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: 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: 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,
127            algorithm,
128            algorithm_cached: Heap::default(),
129            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.to_jsval(cx, algorithm_object_value.handle_mut());
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.to_jsval(cx, usages_object_value.handle_mut());
166        crypto_key
167            .usages_cached
168            .set(usages_object_value.to_object());
169
170        crypto_key
171    }
172
173    pub(crate) fn algorithm(&self) -> &KeyAlgorithmAndDerivatives {
174        &self.algorithm
175    }
176
177    pub(crate) fn usages(&self) -> &[KeyUsage] {
178        &self.usages
179    }
180
181    pub(crate) fn handle(&self) -> &Handle {
182        &self.handle
183    }
184}
185
186impl CryptoKeyMethods<crate::DomTypeHolder> for CryptoKey {
187    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-type>
188    fn Type(&self) -> KeyType {
189        // Reflects the [[type]] internal slot, which contains the type of the underlying key.
190        self.key_type
191    }
192
193    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-extractable>
194    fn Extractable(&self) -> bool {
195        // Reflects the [[extractable]] internal slot, which indicates whether or not the raw
196        // keying material may be exported by the application.
197        self.extractable
198    }
199
200    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-algorithm>
201    fn Algorithm(&self, mut return_value: MutableHandleObject) {
202        // Returns the cached ECMAScript object associated with the [[algorithm]] internal slot.
203        return_value.set(self.algorithm_cached.get())
204    }
205
206    /// <https://w3c.github.io/webcrypto/#dom-cryptokey-usages>
207    fn Usages(&self, mut return_value: MutableHandleObject) {
208        // Returns the cached ECMAScript object associated with the [[usages]] internal slot, which
209        // indicates which cryptographic operations are permissible to be used with this key.
210        return_value.set(self.usages_cached.get())
211    }
212}
213
214impl Serializable for CryptoKey {
215    type Index = CryptoKeyIndex;
216    type Data = SerializableCryptoKey;
217
218    /// <https://w3c.github.io/webcrypto/#cryptokey-interface-serializable>
219    fn serialize(&self, _no_gc: &NoGC) -> Result<(CryptoKeyId, Self::Data), ()> {
220        // Step 1. Set serialized.[[Type]] to the [[type]] internal slot of value.
221        // Step 2. Set serialized.[[Extractable]] to the [[extractable]] internal slot of value.
222        // Step 3. Set serialized.[[Algorithm]] to the sub-serialization of the [[algorithm]]
223        // internal slot of value.
224        // Step 4. Set serialized.[[Usages]] to the sub-serialization of the [[usages]] internal
225        // slot of value.
226        // Step 5. Set serialized.[[Handle]] to the [[handle]] internal slot of value.
227        let serialized = SerializableCryptoKey {
228            key_type: self.key_type.as_str().into(),
229            extractable: self.extractable,
230            algorithm: (&self.algorithm).into(),
231            usages: self
232                .usages
233                .iter()
234                .map(|usage| usage.as_str().into())
235                .collect(),
236            handle: (&self.handle).try_into()?,
237        };
238        Ok((CryptoKeyId::new(), serialized))
239    }
240
241    /// <https://w3c.github.io/webcrypto/#cryptokey-interface-serializable>
242    fn deserialize(
243        cx: &mut js::context::JSContext,
244        owner: &GlobalScope,
245        serialized: Self::Data,
246    ) -> Result<DomRoot<Self>, ()> {
247        // Step 1. Initialize the [[type]] internal slot of value to serialized.[[Type]].
248        // Step 2. Initialize the [[extractable]] internal slot of value to
249        // serialized.[[Extractable]].
250        // Step 3. Initialize the [[algorithm]] internal slot of value to the sub-deserialization of
251        // serialized.[[Algorithm]].
252        // Step 4. Initialize the [[usages]] internal slot of value to the sub-deserialization of
253        // serialized.[[Usages]].
254        // Step 5. Initialize the [[handle]] internal slot of value to serialized.[[Handle]].
255        Ok(CryptoKey::new(
256            cx,
257            owner,
258            KeyType::from_str(&serialized.key_type)?,
259            serialized.extractable,
260            serialized.algorithm.try_into()?,
261            serialized
262                .usages
263                .iter()
264                .map(|usage| KeyUsage::from_str(usage))
265                .collect::<Result<Vec<_>, _>>()?,
266            serialized.handle.try_into()?,
267        ))
268    }
269
270    fn serialized_storage<'a>(
271        reader: StructuredData<'a, '_>,
272    ) -> &'a mut Option<FxHashMap<CryptoKeyId, Self::Data>> {
273        match reader {
274            StructuredData::Reader(reader) => &mut reader.crypto_keys,
275            StructuredData::Writer(writer) => &mut writer.crypto_keys,
276        }
277    }
278}
279
280impl Handle {
281    pub(crate) fn as_bytes(&self) -> &[u8] {
282        match self {
283            Self::Pbkdf2(bytes) => bytes,
284            Self::Hmac(bytes) => bytes,
285            _ => unreachable!(),
286        }
287    }
288}
289
290impl MallocSizeOf for Handle {
291    fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
292        match self {
293            Handle::RsaPrivateKey(private_key) => private_key.size_of(ops),
294            Handle::RsaPublicKey(public_key) => public_key.size_of(ops),
295            Handle::P256PrivateKey(private_key) => private_key.size_of(ops),
296            Handle::P384PrivateKey(private_key) => private_key.size_of(ops),
297            Handle::P521PrivateKey(private_key) => private_key.size_of(ops),
298            Handle::P256PublicKey(public_key) => public_key.size_of(ops),
299            Handle::P384PublicKey(public_key) => public_key.size_of(ops),
300            Handle::P521PublicKey(public_key) => public_key.size_of(ops),
301            Handle::Ed25519PrivateKey(bytes) => bytes.size_of(ops),
302            Handle::Ed25519PublicKey(bytes) => bytes.size_of(ops),
303            Handle::X25519PrivateKey(private_key) => private_key.size_of(ops),
304            Handle::X25519PublicKey(public_key) => public_key.size_of(ops),
305            Handle::Ed448PrivateKey(private_key) => private_key.size_of(ops),
306            Handle::Ed448PublicKey(public_key) => public_key.size_of(ops),
307            Handle::X448PrivateKey(private_key) => private_key.size_of(ops),
308            Handle::X448PublicKey(public_key) => public_key.size_of(ops),
309            Handle::Aes128Key(key) => key.size_of(ops),
310            Handle::Aes192Key(key) => key.size_of(ops),
311            Handle::Aes256Key(key) => key.size_of(ops),
312            Handle::HkdfSecret(secret) => secret.size_of(ops),
313            Handle::Pbkdf2(bytes) => bytes.size_of(ops),
314            Handle::Hmac(bytes) => bytes.size_of(ops),
315            Handle::MlKem512PrivateKey(private_key) => private_key.size_of(ops),
316            Handle::MlKem768PrivateKey(private_key) => private_key.size_of(ops),
317            Handle::MlKem1024PrivateKey(private_key) => private_key.size_of(ops),
318            Handle::MlKem512PublicKey(public_key) => public_key.size_of(ops),
319            Handle::MlKem768PublicKey(public_key) => public_key.size_of(ops),
320            Handle::MlKem1024PublicKey(public_key) => public_key.size_of(ops),
321            Handle::MlDsa44PrivateKey(private_key) => private_key.size_of(ops),
322            Handle::MlDsa65PrivateKey(private_key) => private_key.size_of(ops),
323            Handle::MlDsa87PrivateKey(private_key) => private_key.size_of(ops),
324            Handle::MlDsa44PublicKey(public_key) => public_key.size_of(ops),
325            Handle::MlDsa65PublicKey(public_key) => public_key.size_of(ops),
326            Handle::MlDsa87PublicKey(public_key) => public_key.size_of(ops),
327            Handle::ChaCha20Poly1305Key(key) => key.size_of(ops),
328            Handle::KmacKey(key) => key.size_of(ops),
329            Handle::Argon2Password(password) => password.size_of(ops),
330        }
331    }
332}
333
334impl TryFrom<SerializableCryptoKeyHandle> for Handle {
335    type Error = ();
336
337    fn try_from(value: SerializableCryptoKeyHandle) -> Result<Self, Self::Error> {
338        match &value {
339            SerializableCryptoKeyHandle::RsaPrivateKey(private_key) => Ok(Handle::RsaPrivateKey(
340                rsa::pkcs8::DecodePrivateKey::from_pkcs8_der(private_key).map_err(|_| ())?,
341            )),
342            SerializableCryptoKeyHandle::RsaPublicKey(public_key) => Ok(Handle::RsaPublicKey(
343                rsa::pkcs8::spki::DecodePublicKey::from_public_key_der(public_key)
344                    .map_err(|_| ())?,
345            )),
346            SerializableCryptoKeyHandle::P256PrivateKey(private_key) => Ok(Handle::P256PrivateKey(
347                p256::SecretKey::from_slice(private_key).map_err(|_| ())?,
348            )),
349            SerializableCryptoKeyHandle::P384PrivateKey(private_key) => Ok(Handle::P384PrivateKey(
350                p384::SecretKey::from_slice(private_key).map_err(|_| ())?,
351            )),
352            SerializableCryptoKeyHandle::P521PrivateKey(private_key) => Ok(Handle::P521PrivateKey(
353                p521::SecretKey::from_slice(private_key).map_err(|_| ())?,
354            )),
355            SerializableCryptoKeyHandle::P256PublicKey(public_key) => Ok(Handle::P256PublicKey(
356                p256::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
357            )),
358            SerializableCryptoKeyHandle::P384PublicKey(public_key) => Ok(Handle::P384PublicKey(
359                p384::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
360            )),
361            SerializableCryptoKeyHandle::P521PublicKey(public_key) => Ok(Handle::P521PublicKey(
362                p521::PublicKey::from_sec1_bytes(public_key).map_err(|_| ())?,
363            )),
364            SerializableCryptoKeyHandle::Ed25519PrivateKey(private_key) => Ok(
365                Handle::Ed25519PrivateKey(ed25519_dalek::SigningKey::from_bytes(private_key)),
366            ),
367            SerializableCryptoKeyHandle::Ed25519PublicKey(public_key) => {
368                Ok(Handle::Ed25519PublicKey(
369                    ed25519_dalek::VerifyingKey::from_bytes(public_key).map_err(|_| ())?,
370                ))
371            },
372            SerializableCryptoKeyHandle::X25519PrivateKey(private_key) => {
373                Ok(Handle::X25519PrivateKey((*private_key).into()))
374            },
375            SerializableCryptoKeyHandle::X25519PublicKey(public_key) => {
376                Ok(Handle::X25519PublicKey((*public_key).into()))
377            },
378            SerializableCryptoKeyHandle::Ed448PrivateKey(private_key) => {
379                Ok(Handle::Ed448PrivateKey(
380                    ed448_goldilocks::SigningKey::try_from(private_key).map_err(|_| ())?,
381                ))
382            },
383            SerializableCryptoKeyHandle::Ed448PublicKey(public_key) => Ok(Handle::Ed448PublicKey(
384                ed448_goldilocks::VerifyingKey::from_bytes(
385                    public_key.as_slice().try_into().map_err(|_| ())?,
386                )
387                .map_err(|_| ())?,
388            )),
389            SerializableCryptoKeyHandle::X448PrivateKey(private_key) => {
390                Ok(Handle::X448PrivateKey(x448::StaticSecret::from(
391                    <[u8; 56]>::try_from(private_key.as_slice()).map_err(|_| ())?,
392                )))
393            },
394            SerializableCryptoKeyHandle::X448PublicKey(public_key) => Ok(Handle::X448PublicKey(
395                x448::PublicKey::from_bytes_unchecked(public_key).ok_or(())?,
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::KmacKey(key) => Ok(Handle::KmacKey(key.clone().into())),
475            SerializableCryptoKeyHandle::Argon2Password(password) => {
476                Ok(Handle::Argon2Password(password.clone().into()))
477            },
478        }
479    }
480}
481
482/// To serialize the key in the `Handle`, we convert the key into byte sequences. For most
483/// cryptographic algorithms, this conversion is straightforward since the key can natually be
484/// expressed as a byte sequence. However, some cryptographic algorithms require preprocessing
485/// before their key can be represented in byte sequences. For example, an RSA private key needs to
486/// be first converted into DER-encoded PKCS#8 format before it can be expressed as a byte sequence.
487impl TryFrom<&Handle> for SerializableCryptoKeyHandle {
488    type Error = ();
489
490    fn try_from(value: &Handle) -> Result<Self, Self::Error> {
491        match value {
492            Handle::RsaPrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::RsaPrivateKey(
493                rsa::pkcs8::EncodePrivateKey::to_pkcs8_der(private_key)
494                    .map_err(|_| ())?
495                    .as_bytes()
496                    .to_vec(),
497            )),
498            Handle::RsaPublicKey(public_key) => Ok(SerializableCryptoKeyHandle::RsaPublicKey(
499                rsa::pkcs8::spki::EncodePublicKey::to_public_key_der(public_key)
500                    .map_err(|_| ())?
501                    .into_vec(),
502            )),
503            Handle::P256PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P256PrivateKey(
504                private_key.to_bytes().as_slice().to_vec(),
505            )),
506            Handle::P384PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P384PrivateKey(
507                private_key.to_bytes().as_slice().to_vec(),
508            )),
509            Handle::P521PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::P521PrivateKey(
510                private_key.to_bytes().as_slice().to_vec(),
511            )),
512            Handle::P256PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P256PublicKey(
513                public_key.to_sec1_bytes().to_vec(),
514            )),
515            Handle::P384PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P384PublicKey(
516                public_key.to_sec1_bytes().to_vec(),
517            )),
518            Handle::P521PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::P521PublicKey(
519                public_key.to_sec1_bytes().to_vec(),
520            )),
521            Handle::Ed25519PrivateKey(private_key) => Ok(
522                SerializableCryptoKeyHandle::Ed25519PrivateKey(private_key.to_bytes()),
523            ),
524            Handle::Ed25519PublicKey(public_key) => Ok(
525                SerializableCryptoKeyHandle::Ed25519PublicKey(public_key.to_bytes()),
526            ),
527            Handle::X25519PrivateKey(private_key) => Ok(
528                SerializableCryptoKeyHandle::X25519PrivateKey(private_key.to_bytes()),
529            ),
530            Handle::X25519PublicKey(public_key) => Ok(
531                SerializableCryptoKeyHandle::X25519PublicKey(public_key.to_bytes()),
532            ),
533            Handle::Ed448PrivateKey(private_key) => Ok(
534                SerializableCryptoKeyHandle::Ed448PrivateKey(private_key.as_bytes().to_vec()),
535            ),
536            Handle::Ed448PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::Ed448PublicKey(
537                public_key.as_bytes().to_vec(),
538            )),
539            Handle::X448PrivateKey(private_key) => Ok(SerializableCryptoKeyHandle::X448PrivateKey(
540                private_key.as_bytes().to_vec(),
541            )),
542            Handle::X448PublicKey(public_key) => Ok(SerializableCryptoKeyHandle::X448PublicKey(
543                public_key.as_bytes().to_vec(),
544            )),
545            Handle::Aes128Key(key) => Ok(SerializableCryptoKeyHandle::Aes128Key(key.to_vec())),
546            Handle::Aes192Key(key) => Ok(SerializableCryptoKeyHandle::Aes192Key(key.to_vec())),
547            Handle::Aes256Key(key) => Ok(SerializableCryptoKeyHandle::Aes256Key(key.to_vec())),
548            Handle::Hmac(bytes) => Ok(SerializableCryptoKeyHandle::Hmac(bytes.to_vec())),
549            Handle::HkdfSecret(bytes) => {
550                Ok(SerializableCryptoKeyHandle::HkdfSecret(bytes.to_vec()))
551            },
552            Handle::Pbkdf2(bytes) => Ok(SerializableCryptoKeyHandle::Pbkdf2(bytes.to_vec())),
553            Handle::MlKem512PrivateKey(private_key) => {
554                Ok(SerializableCryptoKeyHandle::MlKem512PrivateKey(
555                    private_key
556                        .to_seed()
557                        .expect("This decapsulation key should contain seed value")
558                        .as_slice()
559                        .to_vec(),
560                ))
561            },
562            Handle::MlKem768PrivateKey(private_key) => {
563                Ok(SerializableCryptoKeyHandle::MlKem768PrivateKey(
564                    private_key
565                        .to_seed()
566                        .expect("This decapsulation key should contain seed value")
567                        .as_slice()
568                        .to_vec(),
569                ))
570            },
571            Handle::MlKem1024PrivateKey(private_key) => {
572                Ok(SerializableCryptoKeyHandle::MlKem1024PrivateKey(
573                    private_key
574                        .to_seed()
575                        .expect("This decapsulation key should contain seed value")
576                        .as_slice()
577                        .to_vec(),
578                ))
579            },
580            Handle::MlKem512PublicKey(public_key) => {
581                Ok(SerializableCryptoKeyHandle::MlKem512PublicKey(
582                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
583                ))
584            },
585            Handle::MlKem768PublicKey(public_key) => {
586                Ok(SerializableCryptoKeyHandle::MlKem768PublicKey(
587                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
588                ))
589            },
590            Handle::MlKem1024PublicKey(public_key) => {
591                Ok(SerializableCryptoKeyHandle::MlKem1024PublicKey(
592                    ml_kem::KeyExport::to_bytes(public_key).as_slice().to_vec(),
593                ))
594            },
595            Handle::MlDsa44PrivateKey(private_key) => {
596                Ok(SerializableCryptoKeyHandle::MlDsa44PrivateKey(
597                    private_key.as_seed().as_slice().to_vec(),
598                ))
599            },
600            Handle::MlDsa65PrivateKey(private_key) => {
601                Ok(SerializableCryptoKeyHandle::MlDsa65PrivateKey(
602                    private_key.as_seed().as_slice().to_vec(),
603                ))
604            },
605            Handle::MlDsa87PrivateKey(private_key) => {
606                Ok(SerializableCryptoKeyHandle::MlDsa87PrivateKey(
607                    private_key.as_seed().as_slice().to_vec(),
608                ))
609            },
610            Handle::MlDsa44PublicKey(public_key) => {
611                Ok(SerializableCryptoKeyHandle::MlDsa44PublicKey(
612                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
613                ))
614            },
615            Handle::MlDsa65PublicKey(public_key) => {
616                Ok(SerializableCryptoKeyHandle::MlDsa65PublicKey(
617                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
618                ))
619            },
620            Handle::MlDsa87PublicKey(public_key) => {
621                Ok(SerializableCryptoKeyHandle::MlDsa87PublicKey(
622                    ml_dsa::KeyExport::to_bytes(public_key).as_slice().to_vec(),
623                ))
624            },
625            Handle::ChaCha20Poly1305Key(key) => Ok(
626                SerializableCryptoKeyHandle::ChaCha20Poly1305Key(key.as_slice().to_vec()),
627            ),
628            Handle::KmacKey(key) => Ok(SerializableCryptoKeyHandle::KmacKey(key.to_vec())),
629            Handle::Argon2Password(password) => Ok(SerializableCryptoKeyHandle::Argon2Password(
630                password.to_vec(),
631            )),
632        }
633    }
634}
635
636/// The trait providing helper functions for [`Vec<KeyUsage>`]
637pub(crate) trait KeyUsageVecHelper {
638    /// <https://w3c.github.io/webcrypto/#concept-usage-intersection>
639    fn usage_intersection(&self, other: &[KeyUsage]) -> Vec<KeyUsage>;
640
641    /// <https://w3c.github.io/webcrypto/#concept-normalized-usages>
642    fn normalized_value(&self) -> Vec<KeyUsage>;
643}
644
645impl KeyUsageVecHelper for Vec<KeyUsage> {
646    fn usage_intersection(&self, other: &[KeyUsage]) -> Vec<KeyUsage> {
647        // When this specification says to calculate the usage intersection of two sequences, a and
648        // b the result shall be a sequence containing each recognized key usage value that appears
649        // in both a and b, in the order listed in the list of recognized key usage values, where a
650        // value is said to appear in a sequence if an element of the sequence exists that is a
651        // case-sensitive string match for that value.
652        let mut intersection = self
653            .iter()
654            .filter(|usage| other.contains(usage))
655            .cloned()
656            .collect::<Vec<KeyUsage>>();
657        intersection.sort();
658        intersection.dedup();
659
660        intersection
661    }
662
663    fn normalized_value(&self) -> Vec<KeyUsage> {
664        // When this specification says to calculate the normalized value of a usages list, usages
665        // the result shall be the usage intersection of usages and a sequence containing all
666        // recognized key usage values.
667        self.usage_intersection(KeyUsage::VARIANTS)
668    }
669}