mirror of
https://github.com/denoland/deno.git
synced 2024-12-23 15:49:44 -05:00
refactor(ext/crypto): symmetric jwk decode in rust (#13047)
This commit is contained in:
parent
2bdb528eb8
commit
cbfc8dd59d
4 changed files with 54 additions and 23 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -767,6 +767,7 @@ name = "deno_crypto"
|
|||
version = "0.42.0"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"base64 0.13.0",
|
||||
"block-modes",
|
||||
"deno_core",
|
||||
"deno_web",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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()),
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue