summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Casonato <hello@lcas.dev>2021-12-10 22:23:19 +0100
committerGitHub <noreply@github.com>2021-12-10 22:23:19 +0100
commitcbfc8dd59d79fa6e8c5a59ca97508ea4285ff155 (patch)
tree586ff050dc320de8cdb68d38e58a481d505c2bcc
parent2bdb528eb89bae468b802a65338001ac95f8f563 (diff)
refactor(ext/crypto): symmetric jwk decode in rust (#13047)
-rw-r--r--Cargo.lock1
-rw-r--r--ext/crypto/00_crypto.js35
-rw-r--r--ext/crypto/Cargo.toml1
-rw-r--r--ext/crypto/import_key.rs40
4 files changed, 54 insertions, 23 deletions
diff --git a/Cargo.lock b/Cargo.lock
index de0095e96..05af039c8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -767,6 +767,7 @@ name = "deno_crypto"
version = "0.42.0"
dependencies = [
"aes",
+ "base64 0.13.0",
"block-modes",
"deno_core",
"deno_web",
diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js
index 16c862829..4e2a90f3b 100644
--- a/ext/crypto/00_crypto.js
+++ b/ext/crypto/00_crypto.js
@@ -12,7 +12,7 @@
const core = window.Deno.core;
const webidl = window.__bootstrap.webidl;
const { DOMException } = window.__bootstrap.domException;
- const { atob, btoa } = window.__bootstrap.base64;
+ const { btoa } = window.__bootstrap.base64;
const {
ArrayPrototypeFind,
@@ -23,7 +23,6 @@
BigInt64Array,
StringPrototypeToUpperCase,
StringPrototypeReplace,
- StringPrototypeCharCodeAt,
StringFromCharCode,
Symbol,
SymbolFor,
@@ -169,23 +168,6 @@
},
};
- // Decodes the unpadded base64 to the octet sequence containing key value `k` defined in RFC7518 Section 6.4
- function decodeSymmetricKey(key) {
- // Decode from base64url without `=` padding.
- const base64 = StringPrototypeReplace(
- StringPrototypeReplace(key, /\-/g, "+"),
- /\_/g,
- "/",
- );
- const decodedKey = atob(base64);
- const keyLength = decodedKey.length;
- const keyBytes = new Uint8Array(keyLength);
- for (let i = 0; i < keyLength; i++) {
- keyBytes[i] = StringPrototypeCharCodeAt(decodedKey, i);
- }
- return keyBytes;
- }
-
function unpaddedBase64(bytes) {
let binaryString = "";
for (let i = 0; i < bytes.length; i++) {
@@ -1901,7 +1883,12 @@
}
// 4.
- data = decodeSymmetricKey(jwk.k);
+ const { rawData } = core.opSync(
+ "op_crypto_import_key",
+ { algorithm: "AES" },
+ { jwkSecret: jwk },
+ );
+ data = rawData.data;
// 5.
switch (data.byteLength * 8) {
@@ -2038,6 +2025,7 @@
case "jwk": {
// TODO(@littledivy): Why does the spec validate JWK twice?
const jwk = keyData;
+
// 2.
if (jwk.kty !== "oct") {
throw new DOMException(
@@ -2055,7 +2043,12 @@
}
// 4.
- data = decodeSymmetricKey(jwk.k);
+ const { rawData } = core.opSync(
+ "op_crypto_import_key",
+ { algorithm: "HMAC" },
+ { jwkSecret: jwk },
+ );
+ data = rawData.data;
// 5.
hash = normalizedAlgorithm.hash;
diff --git a/ext/crypto/Cargo.toml b/ext/crypto/Cargo.toml
index a9b37ba2d..daa809422 100644
--- a/ext/crypto/Cargo.toml
+++ b/ext/crypto/Cargo.toml
@@ -15,6 +15,7 @@ path = "lib.rs"
[dependencies]
aes = "0.7.5"
+base64 = "0.13.0"
block-modes = "0.8.1"
deno_core = { version = "0.110.0", path = "../../core" }
deno_web = { version = "0.59.0", path = "../web" }
diff --git a/ext/crypto/import_key.rs b/ext/crypto/import_key.rs
index 16a8d155f..c93e2a9bb 100644
--- a/ext/crypto/import_key.rs
+++ b/ext/crypto/import_key.rs
@@ -11,12 +11,12 @@ use crate::OaepPrivateKeyParameters;
use crate::PssPrivateKeyParameters;
#[derive(Deserialize)]
-#[serde(rename_all = "lowercase")]
+#[serde(rename_all = "camelCase")]
pub enum KeyData {
Spki(ZeroCopyBuf),
Pkcs8(ZeroCopyBuf),
Raw(ZeroCopyBuf),
- Jwk { k: String },
+ JwkSecret { k: String },
}
#[derive(Deserialize)]
@@ -32,6 +32,10 @@ pub enum ImportKeyOptions {
Ecdsa { named_curve: EcNamedCurve },
#[serde(rename = "ECDH", rename_all = "camelCase")]
Ecdh { named_curve: EcNamedCurve },
+ #[serde(rename = "AES", rename_all = "camelCase")]
+ Aes {},
+ #[serde(rename = "HMAC", rename_all = "camelCase")]
+ Hmac {},
}
#[derive(Serialize)]
@@ -45,6 +49,10 @@ pub enum ImportKeyResult {
},
#[serde(rename_all = "camelCase")]
Ec { raw_data: RawKeyData },
+ #[serde(rename_all = "camelCase")]
+ Aes { raw_data: RawKeyData },
+ #[serde(rename_all = "camelCase")]
+ Hmac { raw_data: RawKeyData },
}
pub fn op_crypto_import_key(
@@ -62,6 +70,8 @@ pub fn op_crypto_import_key(
| ImportKeyOptions::Ecdh { named_curve } => {
import_key_ec(key_data, named_curve)
}
+ ImportKeyOptions::Aes {} => import_key_aes(key_data),
+ ImportKeyOptions::Hmac {} => import_key_hmac(key_data),
}
}
@@ -576,3 +586,29 @@ fn import_key_ec(
_ => return Err(unsupported_format()),
})
}
+
+fn import_key_aes(key_data: KeyData) -> Result<ImportKeyResult, AnyError> {
+ Ok(match key_data {
+ KeyData::JwkSecret { k } => {
+ let data = base64::decode_config(k, base64::URL_SAFE)
+ .map_err(|_| data_error("invalid key data"))?;
+ ImportKeyResult::Hmac {
+ raw_data: RawKeyData::Secret(data.into()),
+ }
+ }
+ _ => return Err(unsupported_format()),
+ })
+}
+
+fn import_key_hmac(key_data: KeyData) -> Result<ImportKeyResult, AnyError> {
+ Ok(match key_data {
+ KeyData::JwkSecret { k } => {
+ let data = base64::decode_config(k, base64::URL_SAFE)
+ .map_err(|_| data_error("invalid key data"))?;
+ ImportKeyResult::Hmac {
+ raw_data: RawKeyData::Secret(data.into()),
+ }
+ }
+ _ => return Err(unsupported_format()),
+ })
+}