script_webcrypto/subtlecrypto/
rsassa_pkcs1_v1_5_operation.rs1use js::context::JSContext;
6use rsa::pkcs1v15::{Signature, SigningKey, VerifyingKey};
7use rsa::signature::{SignatureEncoding, Signer, Verifier};
8use script_bindings::codegen::GenericBindings::CryptoKeyBinding::{
9 CryptoKeyPair, KeyType, KeyUsage,
10};
11use script_bindings::codegen::GenericBindings::SubtleCryptoBinding::KeyFormat;
12use script_bindings::error::Error;
13use script_bindings::root::DomRoot;
14use sha1::Sha1;
15use sha2::{Sha256, Sha384, Sha512};
16
17use crate::cryptokey::{CryptoKey, Handle};
18use crate::subtlecrypto::rsa_common::{self, RsaAlgorithm};
19use crate::subtlecrypto::{
20 CryptoAlgorithm, ExportedKey, KeyAlgorithmAndDerivatives, NormalizedAlgorithm,
21 RsaHashedImportParams, RsaHashedKeyGenParams,
22};
23use crate::traits::Equivalence;
24
25pub(crate) fn sign<D: Equivalence>(key: &CryptoKey<D>, message: &[u8]) -> Result<Vec<u8>, Error> {
27 key.ensure_type(KeyType::Private)?;
30
31 let Handle::RsaPrivateKey(private_key) = key.handle() else {
39 return Err(Error::Operation(Some(
40 "[[handle]] internal slot of key is not an RSA private key".to_string(),
41 )));
42 };
43 let KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) = key.algorithm() else {
44 return Err(Error::Operation(Some(
45 "[[algorithm]] internal slot of key is not an RsaHashedKeyAlgorithm".to_string(),
46 )));
47 };
48 let signature = match algorithm.hash.name() {
49 CryptoAlgorithm::Sha1 => {
50 let signing_key = SigningKey::<Sha1>::new(private_key.clone());
51 signing_key.try_sign(message)
52 },
53 CryptoAlgorithm::Sha256 => {
54 let signing_key = SigningKey::<Sha256>::new(private_key.clone());
55 signing_key.try_sign(message)
56 },
57 CryptoAlgorithm::Sha384 => {
58 let signing_key = SigningKey::<Sha384>::new(private_key.clone());
59 signing_key.try_sign(message)
60 },
61 CryptoAlgorithm::Sha512 => {
62 let signing_key = SigningKey::<Sha512>::new(private_key.clone());
63 signing_key.try_sign(message)
64 },
65 _ => {
66 return Err(Error::Operation(Some(format!(
67 "Unsupported \"{}\" hash for RSASSA-PKCS1-v1_5",
68 algorithm.hash.name().as_str()
69 ))));
70 },
71 }
72 .map_err(|_| Error::Operation(Some("RSASSA-PKCS1-v1_5 failed to sign message".to_string())))?;
73
74 Ok(signature.to_vec())
76}
77
78pub(crate) fn verify<D: Equivalence>(
80 key: &CryptoKey<D>,
81 message: &[u8],
82 signature: &[u8],
83) -> Result<bool, Error> {
84 key.ensure_type(KeyType::Public)?;
87
88 let Handle::RsaPublicKey(public_key) = key.handle() else {
96 return Err(Error::Operation(Some(
97 "[[handle]] internal slot of key is not an RSA public key".to_string(),
98 )));
99 };
100 let KeyAlgorithmAndDerivatives::RsaHashedKeyAlgorithm(algorithm) = key.algorithm() else {
101 return Err(Error::Operation(Some(
102 "[[algorithm]] internal slot of key is not an RsaHashedKeyAlgorithm".to_string(),
103 )));
104 };
105 let signature = Signature::try_from(signature)
106 .map_err(|_| Error::Operation(Some("Failed to parse RSA signature".to_string())))?;
107 let result = match algorithm.hash.name() {
108 CryptoAlgorithm::Sha1 => {
109 let verifying_key = VerifyingKey::<Sha1>::new(public_key.clone());
110 verifying_key.verify(message, &signature)
111 },
112 CryptoAlgorithm::Sha256 => {
113 let verifying_key = VerifyingKey::<Sha256>::new(public_key.clone());
114 verifying_key.verify(message, &signature)
115 },
116 CryptoAlgorithm::Sha384 => {
117 let verifying_key = VerifyingKey::<Sha384>::new(public_key.clone());
118 verifying_key.verify(message, &signature)
119 },
120 CryptoAlgorithm::Sha512 => {
121 let verifying_key = VerifyingKey::<Sha512>::new(public_key.clone());
122 verifying_key.verify(message, &signature)
123 },
124 _ => {
125 return Err(Error::Operation(Some(format!(
126 "Unsupported \"{}\" hash for RSASSA-PKCS1-v1_5",
127 algorithm.hash.name().as_str()
128 ))));
129 },
130 }
131 .is_ok();
132
133 Ok(result)
135}
136
137pub(crate) fn generate_key<D: Equivalence>(
139 cx: &mut JSContext,
140 global: &D::GlobalScope,
141 normalized_algorithm: &RsaHashedKeyGenParams,
142 extractable: bool,
143 usages: Vec<KeyUsage>,
144) -> Result<CryptoKeyPair<D>, Error> {
145 rsa_common::generate_key(
146 cx,
147 global,
148 RsaAlgorithm::RsassaPkcs1v1_5,
149 normalized_algorithm,
150 extractable,
151 usages,
152 )
153}
154
155pub(crate) fn import_key<D: Equivalence>(
157 cx: &mut JSContext,
158 global: &D::GlobalScope,
159 normalized_algorithm: &RsaHashedImportParams,
160 format: KeyFormat,
161 key_data: &[u8],
162 extractable: bool,
163 usages: Vec<KeyUsage>,
164) -> Result<DomRoot<CryptoKey<D>>, Error> {
165 rsa_common::import_key(
166 cx,
167 global,
168 RsaAlgorithm::RsassaPkcs1v1_5,
169 normalized_algorithm,
170 format,
171 key_data,
172 extractable,
173 usages,
174 )
175}
176
177pub(crate) fn export_key<D: Equivalence>(
179 format: KeyFormat,
180 key: &CryptoKey<D>,
181) -> Result<ExportedKey, Error> {
182 rsa_common::export_key(RsaAlgorithm::RsassaPkcs1v1_5, format, key)
183}
184
185pub(crate) fn get_public_key<D: Equivalence>(
188 cx: &mut JSContext,
189 global: &D::GlobalScope,
190 key: &CryptoKey<D>,
191 algorithm: &KeyAlgorithmAndDerivatives,
192 usages: Vec<KeyUsage>,
193) -> Result<DomRoot<CryptoKey<D>>, Error> {
194 rsa_common::get_public_key(
195 cx,
196 global,
197 RsaAlgorithm::RsassaPkcs1v1_5,
198 key,
199 algorithm,
200 usages,
201 )
202}