summaryrefslogtreecommitdiff
path: root/ext/crypto/import_key.rs
diff options
context:
space:
mode:
authorLuca Casonato <hello@lcas.dev>2021-12-14 12:25:07 +0100
committerGitHub <noreply@github.com>2021-12-14 12:25:07 +0100
commit5fe4d5c818d598abfdfc9ef1db0b00f56cf03c20 (patch)
treebdc58af8544cd1c059e3fe86bbf230ebde0212a6 /ext/crypto/import_key.rs
parentc9d32e0581f9095e67433db688bdbedeb6b2a8c2 (diff)
feat(ext/crypto): support importing RSA JWKs (#13071)
This commit adds support for importing RSA JWKs in the Web Crypto API. Co-authored-by: Sean Michael Wykes <sean.wykes@nascent.com.br>
Diffstat (limited to 'ext/crypto/import_key.rs')
-rw-r--r--ext/crypto/import_key.rs114
1 files changed, 110 insertions, 4 deletions
diff --git a/ext/crypto/import_key.rs b/ext/crypto/import_key.rs
index c93e2a9bb..5b5a707a6 100644
--- a/ext/crypto/import_key.rs
+++ b/ext/crypto/import_key.rs
@@ -1,6 +1,7 @@
use deno_core::error::AnyError;
use deno_core::OpState;
use deno_core::ZeroCopyBuf;
+use rsa::pkcs1::UIntBytes;
use serde::Deserialize;
use serde::Serialize;
use spki::der::Decodable;
@@ -16,7 +17,23 @@ pub enum KeyData {
Spki(ZeroCopyBuf),
Pkcs8(ZeroCopyBuf),
Raw(ZeroCopyBuf),
- JwkSecret { k: String },
+ JwkSecret {
+ k: String,
+ },
+ JwkPublicRsa {
+ n: String,
+ e: String,
+ },
+ JwkPrivateRsa {
+ n: String,
+ e: String,
+ d: String,
+ p: String,
+ q: String,
+ dp: String,
+ dq: String,
+ qi: String,
+ },
}
#[derive(Deserialize)]
@@ -75,6 +92,89 @@ pub fn op_crypto_import_key(
}
}
+macro_rules! jwt_b64_int_or_err {
+ ($name:ident, $b64:expr, $err:expr) => {
+ let bytes = base64::decode_config($b64, base64::URL_SAFE)
+ .map_err(|_| data_error($err))?;
+ let $name = UIntBytes::new(&bytes).map_err(|_| data_error($err))?;
+ };
+}
+
+fn import_key_rsa_jwk(
+ key_data: KeyData,
+) -> Result<ImportKeyResult, deno_core::anyhow::Error> {
+ match key_data {
+ KeyData::JwkPublicRsa { n, e } => {
+ jwt_b64_int_or_err!(modulus, &n, "invalid modulus");
+ jwt_b64_int_or_err!(public_exponent, &e, "invalid public exponent");
+
+ let public_key = rsa::pkcs1::RsaPublicKey {
+ modulus,
+ public_exponent,
+ };
+
+ let data = public_key
+ .to_vec()
+ .map_err(|_| data_error("invalid rsa public key"))?;
+ let public_exponent =
+ public_key.public_exponent.as_bytes().to_vec().into();
+ let modulus_length = public_key.modulus.as_bytes().len() * 8;
+
+ Ok(ImportKeyResult::Rsa {
+ raw_data: RawKeyData::Public(data.into()),
+ modulus_length,
+ public_exponent,
+ })
+ }
+ KeyData::JwkPrivateRsa {
+ n,
+ e,
+ d,
+ p,
+ q,
+ dp,
+ dq,
+ qi,
+ } => {
+ jwt_b64_int_or_err!(modulus, &n, "invalid modulus");
+ jwt_b64_int_or_err!(public_exponent, &e, "invalid public exponent");
+ jwt_b64_int_or_err!(private_exponent, &d, "invalid private exponent");
+ jwt_b64_int_or_err!(prime1, &p, "invalid first prime factor");
+ jwt_b64_int_or_err!(prime2, &q, "invalid second prime factor");
+ jwt_b64_int_or_err!(exponent1, &dp, "invalid first CRT exponent");
+ jwt_b64_int_or_err!(exponent2, &dq, "invalid second CRT exponent");
+ jwt_b64_int_or_err!(coefficient, &qi, "invalid CRT coefficient");
+
+ let private_key = rsa::pkcs1::RsaPrivateKey {
+ version: rsa::pkcs1::Version::TwoPrime,
+ modulus,
+ public_exponent,
+ private_exponent,
+ prime1,
+ prime2,
+ exponent1,
+ exponent2,
+ coefficient,
+ };
+
+ let data = private_key
+ .to_vec()
+ .map_err(|_| data_error("invalid rsa private key"))?;
+
+ let public_exponent =
+ private_key.public_exponent.as_bytes().to_vec().into();
+ let modulus_length = private_key.modulus.as_bytes().len() * 8;
+
+ Ok(ImportKeyResult::Rsa {
+ raw_data: RawKeyData::Private(data.into()),
+ modulus_length,
+ public_exponent,
+ })
+ }
+ _ => unreachable!(),
+ }
+}
+
fn import_key_rsassa(
key_data: KeyData,
hash: ShaHash,
@@ -192,7 +292,9 @@ fn import_key_rsassa(
public_exponent,
})
}
- // TODO(lucacasonato): support JWK encoding
+ KeyData::JwkPublicRsa { .. } | KeyData::JwkPrivateRsa { .. } => {
+ import_key_rsa_jwk(key_data)
+ }
_ => Err(unsupported_format()),
}
}
@@ -369,7 +471,9 @@ fn import_key_rsapss(
public_exponent,
})
}
- // TODO(lucacasonato): support JWK encoding
+ KeyData::JwkPublicRsa { .. } | KeyData::JwkPrivateRsa { .. } => {
+ import_key_rsa_jwk(key_data)
+ }
_ => Err(unsupported_format()),
}
}
@@ -546,7 +650,9 @@ fn import_key_rsaoaep(
public_exponent,
})
}
- // TODO(lucacasonato): support JWK encoding
+ KeyData::JwkPublicRsa { .. } | KeyData::JwkPrivateRsa { .. } => {
+ import_key_rsa_jwk(key_data)
+ }
_ => Err(unsupported_format()),
}
}