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