mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 07:14:47 -05:00
refactor(ext/crypto): use concrete error types (#26167)
This commit is contained in:
parent
e22d0e91ef
commit
8ca8174c81
13 changed files with 783 additions and 457 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1503,6 +1503,8 @@ dependencies = [
|
|||
"sha2",
|
||||
"signature",
|
||||
"spki",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"uuid",
|
||||
"x25519-dalek",
|
||||
]
|
||||
|
|
|
@ -41,5 +41,7 @@ sha1.workspace = true
|
|||
sha2.workspace = true
|
||||
signature.workspace = true
|
||||
spki.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
uuid.workspace = true
|
||||
x25519-dalek = "2.0.0"
|
||||
|
|
|
@ -16,9 +16,6 @@ use ctr::cipher::StreamCipher;
|
|||
use ctr::Ctr128BE;
|
||||
use ctr::Ctr32BE;
|
||||
use ctr::Ctr64BE;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::type_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op2;
|
||||
use deno_core::unsync::spawn_blocking;
|
||||
use deno_core::JsBuffer;
|
||||
|
@ -73,12 +70,36 @@ pub enum DecryptAlgorithm {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum DecryptError {
|
||||
#[error(transparent)]
|
||||
General(#[from] SharedError),
|
||||
#[error(transparent)]
|
||||
Pkcs1(#[from] rsa::pkcs1::Error),
|
||||
#[error("Decryption failed")]
|
||||
Failed,
|
||||
#[error("invalid length")]
|
||||
InvalidLength,
|
||||
#[error("invalid counter length. Currently supported 32/64/128 bits")]
|
||||
InvalidCounterLength,
|
||||
#[error("tag length not equal to 128")]
|
||||
InvalidTagLength,
|
||||
#[error("invalid key or iv")]
|
||||
InvalidKeyOrIv,
|
||||
#[error("tried to decrypt too much data")]
|
||||
TooMuchData,
|
||||
#[error("iv length not equal to 12 or 16")]
|
||||
InvalidIvLength,
|
||||
#[error("{0}")]
|
||||
Rsa(rsa::Error),
|
||||
}
|
||||
|
||||
#[op2(async)]
|
||||
#[serde]
|
||||
pub async fn op_crypto_decrypt(
|
||||
#[serde] opts: DecryptOptions,
|
||||
#[buffer] data: JsBuffer,
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, DecryptError> {
|
||||
let key = opts.key;
|
||||
let fun = move || match opts.algorithm {
|
||||
DecryptAlgorithm::RsaOaep { hash, label } => {
|
||||
|
@ -108,7 +129,7 @@ fn decrypt_rsa_oaep(
|
|||
hash: ShaHash,
|
||||
label: Vec<u8>,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, deno_core::anyhow::Error> {
|
||||
) -> Result<Vec<u8>, DecryptError> {
|
||||
let key = key.as_rsa_private_key()?;
|
||||
|
||||
let private_key = rsa::RsaPrivateKey::from_pkcs1_der(key)?;
|
||||
|
@ -139,7 +160,7 @@ fn decrypt_rsa_oaep(
|
|||
|
||||
private_key
|
||||
.decrypt(padding, data)
|
||||
.map_err(|e| custom_error("DOMExceptionOperationError", e.to_string()))
|
||||
.map_err(DecryptError::Rsa)
|
||||
}
|
||||
|
||||
fn decrypt_aes_cbc(
|
||||
|
@ -147,7 +168,7 @@ fn decrypt_aes_cbc(
|
|||
length: usize,
|
||||
iv: Vec<u8>,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, deno_core::anyhow::Error> {
|
||||
) -> Result<Vec<u8>, DecryptError> {
|
||||
let key = key.as_secret_key()?;
|
||||
|
||||
// 2.
|
||||
|
@ -155,53 +176,32 @@ fn decrypt_aes_cbc(
|
|||
128 => {
|
||||
// Section 10.3 Step 2 of RFC 2315 https://www.rfc-editor.org/rfc/rfc2315
|
||||
type Aes128CbcDec = cbc::Decryptor<aes::Aes128>;
|
||||
let cipher = Aes128CbcDec::new_from_slices(key, &iv).map_err(|_| {
|
||||
custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"Invalid key or iv".to_string(),
|
||||
)
|
||||
})?;
|
||||
let cipher = Aes128CbcDec::new_from_slices(key, &iv)
|
||||
.map_err(|_| DecryptError::InvalidKeyOrIv)?;
|
||||
|
||||
cipher.decrypt_padded_vec_mut::<Pkcs7>(data).map_err(|_| {
|
||||
custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"Decryption failed".to_string(),
|
||||
)
|
||||
})?
|
||||
cipher
|
||||
.decrypt_padded_vec_mut::<Pkcs7>(data)
|
||||
.map_err(|_| DecryptError::Failed)?
|
||||
}
|
||||
192 => {
|
||||
// Section 10.3 Step 2 of RFC 2315 https://www.rfc-editor.org/rfc/rfc2315
|
||||
type Aes192CbcDec = cbc::Decryptor<aes::Aes192>;
|
||||
let cipher = Aes192CbcDec::new_from_slices(key, &iv).map_err(|_| {
|
||||
custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"Invalid key or iv".to_string(),
|
||||
)
|
||||
})?;
|
||||
let cipher = Aes192CbcDec::new_from_slices(key, &iv)
|
||||
.map_err(|_| DecryptError::InvalidKeyOrIv)?;
|
||||
|
||||
cipher.decrypt_padded_vec_mut::<Pkcs7>(data).map_err(|_| {
|
||||
custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"Decryption failed".to_string(),
|
||||
)
|
||||
})?
|
||||
cipher
|
||||
.decrypt_padded_vec_mut::<Pkcs7>(data)
|
||||
.map_err(|_| DecryptError::Failed)?
|
||||
}
|
||||
256 => {
|
||||
// Section 10.3 Step 2 of RFC 2315 https://www.rfc-editor.org/rfc/rfc2315
|
||||
type Aes256CbcDec = cbc::Decryptor<aes::Aes256>;
|
||||
let cipher = Aes256CbcDec::new_from_slices(key, &iv).map_err(|_| {
|
||||
custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"Invalid key or iv".to_string(),
|
||||
)
|
||||
})?;
|
||||
let cipher = Aes256CbcDec::new_from_slices(key, &iv)
|
||||
.map_err(|_| DecryptError::InvalidKeyOrIv)?;
|
||||
|
||||
cipher.decrypt_padded_vec_mut::<Pkcs7>(data).map_err(|_| {
|
||||
custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"Decryption failed".to_string(),
|
||||
)
|
||||
})?
|
||||
cipher
|
||||
.decrypt_padded_vec_mut::<Pkcs7>(data)
|
||||
.map_err(|_| DecryptError::Failed)?
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -214,7 +214,7 @@ fn decrypt_aes_ctr_gen<B>(
|
|||
key: &[u8],
|
||||
counter: &[u8],
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, AnyError>
|
||||
) -> Result<Vec<u8>, DecryptError>
|
||||
where
|
||||
B: KeyIvInit + StreamCipher,
|
||||
{
|
||||
|
@ -223,7 +223,7 @@ where
|
|||
let mut plaintext = data.to_vec();
|
||||
cipher
|
||||
.try_apply_keystream(&mut plaintext)
|
||||
.map_err(|_| operation_error("tried to decrypt too much data"))?;
|
||||
.map_err(|_| DecryptError::TooMuchData)?;
|
||||
|
||||
Ok(plaintext)
|
||||
}
|
||||
|
@ -235,12 +235,12 @@ fn decrypt_aes_gcm_gen<N: ArrayLength<u8>>(
|
|||
length: usize,
|
||||
additional_data: Vec<u8>,
|
||||
plaintext: &mut [u8],
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), DecryptError> {
|
||||
let nonce = Nonce::from_slice(nonce);
|
||||
match length {
|
||||
128 => {
|
||||
let cipher = aes_gcm::AesGcm::<Aes128, N>::new_from_slice(key)
|
||||
.map_err(|_| operation_error("Decryption failed"))?;
|
||||
.map_err(|_| DecryptError::Failed)?;
|
||||
cipher
|
||||
.decrypt_in_place_detached(
|
||||
nonce,
|
||||
|
@ -248,11 +248,11 @@ fn decrypt_aes_gcm_gen<N: ArrayLength<u8>>(
|
|||
plaintext,
|
||||
tag,
|
||||
)
|
||||
.map_err(|_| operation_error("Decryption failed"))?
|
||||
.map_err(|_| DecryptError::Failed)?
|
||||
}
|
||||
192 => {
|
||||
let cipher = aes_gcm::AesGcm::<Aes192, N>::new_from_slice(key)
|
||||
.map_err(|_| operation_error("Decryption failed"))?;
|
||||
.map_err(|_| DecryptError::Failed)?;
|
||||
cipher
|
||||
.decrypt_in_place_detached(
|
||||
nonce,
|
||||
|
@ -260,11 +260,11 @@ fn decrypt_aes_gcm_gen<N: ArrayLength<u8>>(
|
|||
plaintext,
|
||||
tag,
|
||||
)
|
||||
.map_err(|_| operation_error("Decryption failed"))?
|
||||
.map_err(|_| DecryptError::Failed)?
|
||||
}
|
||||
256 => {
|
||||
let cipher = aes_gcm::AesGcm::<Aes256, N>::new_from_slice(key)
|
||||
.map_err(|_| operation_error("Decryption failed"))?;
|
||||
.map_err(|_| DecryptError::Failed)?;
|
||||
cipher
|
||||
.decrypt_in_place_detached(
|
||||
nonce,
|
||||
|
@ -272,9 +272,9 @@ fn decrypt_aes_gcm_gen<N: ArrayLength<u8>>(
|
|||
plaintext,
|
||||
tag,
|
||||
)
|
||||
.map_err(|_| operation_error("Decryption failed"))?
|
||||
.map_err(|_| DecryptError::Failed)?
|
||||
}
|
||||
_ => return Err(type_error("invalid length")),
|
||||
_ => return Err(DecryptError::InvalidLength),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
@ -286,7 +286,7 @@ fn decrypt_aes_ctr(
|
|||
counter: &[u8],
|
||||
ctr_length: usize,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, deno_core::anyhow::Error> {
|
||||
) -> Result<Vec<u8>, DecryptError> {
|
||||
let key = key.as_secret_key()?;
|
||||
|
||||
match ctr_length {
|
||||
|
@ -294,23 +294,21 @@ fn decrypt_aes_ctr(
|
|||
128 => decrypt_aes_ctr_gen::<Ctr32BE<aes::Aes128>>(key, counter, data),
|
||||
192 => decrypt_aes_ctr_gen::<Ctr32BE<aes::Aes192>>(key, counter, data),
|
||||
256 => decrypt_aes_ctr_gen::<Ctr32BE<aes::Aes256>>(key, counter, data),
|
||||
_ => Err(type_error("invalid length")),
|
||||
_ => Err(DecryptError::InvalidLength),
|
||||
},
|
||||
64 => match key_length {
|
||||
128 => decrypt_aes_ctr_gen::<Ctr64BE<aes::Aes128>>(key, counter, data),
|
||||
192 => decrypt_aes_ctr_gen::<Ctr64BE<aes::Aes192>>(key, counter, data),
|
||||
256 => decrypt_aes_ctr_gen::<Ctr64BE<aes::Aes256>>(key, counter, data),
|
||||
_ => Err(type_error("invalid length")),
|
||||
_ => Err(DecryptError::InvalidLength),
|
||||
},
|
||||
128 => match key_length {
|
||||
128 => decrypt_aes_ctr_gen::<Ctr128BE<aes::Aes128>>(key, counter, data),
|
||||
192 => decrypt_aes_ctr_gen::<Ctr128BE<aes::Aes192>>(key, counter, data),
|
||||
256 => decrypt_aes_ctr_gen::<Ctr128BE<aes::Aes256>>(key, counter, data),
|
||||
_ => Err(type_error("invalid length")),
|
||||
_ => Err(DecryptError::InvalidLength),
|
||||
},
|
||||
_ => Err(type_error(
|
||||
"invalid counter length. Currently supported 32/64/128 bits",
|
||||
)),
|
||||
_ => Err(DecryptError::InvalidCounterLength),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -321,7 +319,7 @@ fn decrypt_aes_gcm(
|
|||
iv: Vec<u8>,
|
||||
additional_data: Option<Vec<u8>>,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, AnyError> {
|
||||
) -> Result<Vec<u8>, DecryptError> {
|
||||
let key = key.as_secret_key()?;
|
||||
let additional_data = additional_data.unwrap_or_default();
|
||||
|
||||
|
@ -330,7 +328,7 @@ fn decrypt_aes_gcm(
|
|||
// Note that encryption won't fail, it instead truncates the tag
|
||||
// to the specified tag length as specified in the spec.
|
||||
if tag_length != 128 {
|
||||
return Err(type_error("tag length not equal to 128"));
|
||||
return Err(DecryptError::InvalidTagLength);
|
||||
}
|
||||
|
||||
let sep = data.len() - (tag_length / 8);
|
||||
|
@ -357,7 +355,7 @@ fn decrypt_aes_gcm(
|
|||
additional_data,
|
||||
&mut plaintext,
|
||||
)?,
|
||||
_ => return Err(type_error("iv length not equal to 12 or 16")),
|
||||
_ => return Err(DecryptError::InvalidIvLength),
|
||||
}
|
||||
|
||||
Ok(plaintext)
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
use base64::prelude::BASE64_URL_SAFE_NO_PAD;
|
||||
use base64::Engine;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op2;
|
||||
use deno_core::ToJsBuffer;
|
||||
use elliptic_curve::pkcs8::PrivateKeyInfo;
|
||||
|
@ -15,6 +13,16 @@ use spki::der::asn1::BitString;
|
|||
use spki::der::Decode;
|
||||
use spki::der::Encode;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Ed25519Error {
|
||||
#[error("Failed to export key")]
|
||||
FailedExport,
|
||||
#[error(transparent)]
|
||||
Der(#[from] rsa::pkcs1::der::Error),
|
||||
#[error(transparent)]
|
||||
KeyRejected(#[from] ring::error::KeyRejected),
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
pub fn op_crypto_generate_ed25519_keypair(
|
||||
#[buffer] pkey: &mut [u8],
|
||||
|
@ -116,7 +124,7 @@ pub fn op_crypto_import_pkcs8_ed25519(
|
|||
#[serde]
|
||||
pub fn op_crypto_export_spki_ed25519(
|
||||
#[buffer] pubkey: &[u8],
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, Ed25519Error> {
|
||||
let key_info = spki::SubjectPublicKeyInfo {
|
||||
algorithm: spki::AlgorithmIdentifierOwned {
|
||||
// id-Ed25519
|
||||
|
@ -128,9 +136,7 @@ pub fn op_crypto_export_spki_ed25519(
|
|||
Ok(
|
||||
key_info
|
||||
.to_der()
|
||||
.map_err(|_| {
|
||||
custom_error("DOMExceptionOperationError", "Failed to export key")
|
||||
})?
|
||||
.map_err(|_| Ed25519Error::FailedExport)?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
@ -139,7 +145,7 @@ pub fn op_crypto_export_spki_ed25519(
|
|||
#[serde]
|
||||
pub fn op_crypto_export_pkcs8_ed25519(
|
||||
#[buffer] pkey: &[u8],
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, Ed25519Error> {
|
||||
use rsa::pkcs1::der::Encode;
|
||||
|
||||
// This should probably use OneAsymmetricKey instead
|
||||
|
@ -164,7 +170,7 @@ pub fn op_crypto_export_pkcs8_ed25519(
|
|||
#[string]
|
||||
pub fn op_crypto_jwk_x_ed25519(
|
||||
#[buffer] pkey: &[u8],
|
||||
) -> Result<String, AnyError> {
|
||||
) -> Result<String, Ed25519Error> {
|
||||
let pair = Ed25519KeyPair::from_seed_unchecked(pkey)?;
|
||||
Ok(BASE64_URL_SAFE_NO_PAD.encode(pair.public_key().as_ref()))
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@ use aes_gcm::Nonce;
|
|||
use ctr::Ctr128BE;
|
||||
use ctr::Ctr32BE;
|
||||
use ctr::Ctr64BE;
|
||||
use deno_core::error::type_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op2;
|
||||
use deno_core::unsync::spawn_blocking;
|
||||
use deno_core::JsBuffer;
|
||||
|
@ -73,12 +71,30 @@ pub enum EncryptAlgorithm {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum EncryptError {
|
||||
#[error(transparent)]
|
||||
General(#[from] SharedError),
|
||||
#[error("invalid length")]
|
||||
InvalidLength,
|
||||
#[error("invalid key or iv")]
|
||||
InvalidKeyOrIv,
|
||||
#[error("iv length not equal to 12 or 16")]
|
||||
InvalidIvLength,
|
||||
#[error("invalid counter length. Currently supported 32/64/128 bits")]
|
||||
InvalidCounterLength,
|
||||
#[error("tried to encrypt too much data")]
|
||||
TooMuchData,
|
||||
#[error("Encryption failed")]
|
||||
Failed,
|
||||
}
|
||||
|
||||
#[op2(async)]
|
||||
#[serde]
|
||||
pub async fn op_crypto_encrypt(
|
||||
#[serde] opts: EncryptOptions,
|
||||
#[buffer] data: JsBuffer,
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, EncryptError> {
|
||||
let key = opts.key;
|
||||
let fun = move || match opts.algorithm {
|
||||
EncryptAlgorithm::RsaOaep { hash, label } => {
|
||||
|
@ -108,12 +124,12 @@ fn encrypt_rsa_oaep(
|
|||
hash: ShaHash,
|
||||
label: Vec<u8>,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, AnyError> {
|
||||
) -> Result<Vec<u8>, EncryptError> {
|
||||
let label = String::from_utf8_lossy(&label).to_string();
|
||||
|
||||
let public_key = key.as_rsa_public_key()?;
|
||||
let public_key = rsa::RsaPublicKey::from_pkcs1_der(&public_key)
|
||||
.map_err(|_| operation_error("failed to decode public key"))?;
|
||||
.map_err(|_| SharedError::FailedDecodePublicKey)?;
|
||||
let mut rng = OsRng;
|
||||
let padding = match hash {
|
||||
ShaHash::Sha1 => rsa::Oaep {
|
||||
|
@ -139,7 +155,7 @@ fn encrypt_rsa_oaep(
|
|||
};
|
||||
let encrypted = public_key
|
||||
.encrypt(&mut rng, padding, data)
|
||||
.map_err(|_| operation_error("Encryption failed"))?;
|
||||
.map_err(|_| EncryptError::Failed)?;
|
||||
Ok(encrypted)
|
||||
}
|
||||
|
||||
|
@ -148,7 +164,7 @@ fn encrypt_aes_cbc(
|
|||
length: usize,
|
||||
iv: Vec<u8>,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, AnyError> {
|
||||
) -> Result<Vec<u8>, EncryptError> {
|
||||
let key = key.as_secret_key()?;
|
||||
let ciphertext = match length {
|
||||
128 => {
|
||||
|
@ -156,7 +172,7 @@ fn encrypt_aes_cbc(
|
|||
type Aes128CbcEnc = cbc::Encryptor<aes::Aes128>;
|
||||
|
||||
let cipher = Aes128CbcEnc::new_from_slices(key, &iv)
|
||||
.map_err(|_| operation_error("invalid key or iv".to_string()))?;
|
||||
.map_err(|_| EncryptError::InvalidKeyOrIv)?;
|
||||
cipher.encrypt_padded_vec_mut::<Pkcs7>(data)
|
||||
}
|
||||
192 => {
|
||||
|
@ -164,7 +180,7 @@ fn encrypt_aes_cbc(
|
|||
type Aes192CbcEnc = cbc::Encryptor<aes::Aes192>;
|
||||
|
||||
let cipher = Aes192CbcEnc::new_from_slices(key, &iv)
|
||||
.map_err(|_| operation_error("invalid key or iv".to_string()))?;
|
||||
.map_err(|_| EncryptError::InvalidKeyOrIv)?;
|
||||
cipher.encrypt_padded_vec_mut::<Pkcs7>(data)
|
||||
}
|
||||
256 => {
|
||||
|
@ -172,10 +188,10 @@ fn encrypt_aes_cbc(
|
|||
type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>;
|
||||
|
||||
let cipher = Aes256CbcEnc::new_from_slices(key, &iv)
|
||||
.map_err(|_| operation_error("invalid key or iv".to_string()))?;
|
||||
.map_err(|_| EncryptError::InvalidKeyOrIv)?;
|
||||
cipher.encrypt_padded_vec_mut::<Pkcs7>(data)
|
||||
}
|
||||
_ => return Err(type_error("invalid length")),
|
||||
_ => return Err(EncryptError::InvalidLength),
|
||||
};
|
||||
Ok(ciphertext)
|
||||
}
|
||||
|
@ -186,31 +202,31 @@ fn encrypt_aes_gcm_general<N: ArrayLength<u8>>(
|
|||
length: usize,
|
||||
ciphertext: &mut [u8],
|
||||
additional_data: Vec<u8>,
|
||||
) -> Result<aes_gcm::Tag, AnyError> {
|
||||
) -> Result<aes_gcm::Tag, EncryptError> {
|
||||
let nonce = Nonce::<N>::from_slice(&iv);
|
||||
let tag = match length {
|
||||
128 => {
|
||||
let cipher = aes_gcm::AesGcm::<Aes128, N>::new_from_slice(key)
|
||||
.map_err(|_| operation_error("Encryption failed"))?;
|
||||
.map_err(|_| EncryptError::Failed)?;
|
||||
cipher
|
||||
.encrypt_in_place_detached(nonce, &additional_data, ciphertext)
|
||||
.map_err(|_| operation_error("Encryption failed"))?
|
||||
.map_err(|_| EncryptError::Failed)?
|
||||
}
|
||||
192 => {
|
||||
let cipher = aes_gcm::AesGcm::<Aes192, N>::new_from_slice(key)
|
||||
.map_err(|_| operation_error("Encryption failed"))?;
|
||||
.map_err(|_| EncryptError::Failed)?;
|
||||
cipher
|
||||
.encrypt_in_place_detached(nonce, &additional_data, ciphertext)
|
||||
.map_err(|_| operation_error("Encryption failed"))?
|
||||
.map_err(|_| EncryptError::Failed)?
|
||||
}
|
||||
256 => {
|
||||
let cipher = aes_gcm::AesGcm::<Aes256, N>::new_from_slice(key)
|
||||
.map_err(|_| operation_error("Encryption failed"))?;
|
||||
.map_err(|_| EncryptError::Failed)?;
|
||||
cipher
|
||||
.encrypt_in_place_detached(nonce, &additional_data, ciphertext)
|
||||
.map_err(|_| operation_error("Encryption failed"))?
|
||||
.map_err(|_| EncryptError::Failed)?
|
||||
}
|
||||
_ => return Err(type_error("invalid length")),
|
||||
_ => return Err(EncryptError::InvalidLength),
|
||||
};
|
||||
|
||||
Ok(tag)
|
||||
|
@ -223,7 +239,7 @@ fn encrypt_aes_gcm(
|
|||
iv: Vec<u8>,
|
||||
additional_data: Option<Vec<u8>>,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, AnyError> {
|
||||
) -> Result<Vec<u8>, EncryptError> {
|
||||
let key = key.as_secret_key()?;
|
||||
let additional_data = additional_data.unwrap_or_default();
|
||||
|
||||
|
@ -244,7 +260,7 @@ fn encrypt_aes_gcm(
|
|||
&mut ciphertext,
|
||||
additional_data,
|
||||
)?,
|
||||
_ => return Err(type_error("iv length not equal to 12 or 16")),
|
||||
_ => return Err(EncryptError::InvalidIvLength),
|
||||
};
|
||||
|
||||
// Truncated tag to the specified tag length.
|
||||
|
@ -261,7 +277,7 @@ fn encrypt_aes_ctr_gen<B>(
|
|||
key: &[u8],
|
||||
counter: &[u8],
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, AnyError>
|
||||
) -> Result<Vec<u8>, EncryptError>
|
||||
where
|
||||
B: KeyIvInit + StreamCipher,
|
||||
{
|
||||
|
@ -270,7 +286,7 @@ where
|
|||
let mut ciphertext = data.to_vec();
|
||||
cipher
|
||||
.try_apply_keystream(&mut ciphertext)
|
||||
.map_err(|_| operation_error("tried to encrypt too much data"))?;
|
||||
.map_err(|_| EncryptError::TooMuchData)?;
|
||||
|
||||
Ok(ciphertext)
|
||||
}
|
||||
|
@ -281,7 +297,7 @@ fn encrypt_aes_ctr(
|
|||
counter: &[u8],
|
||||
ctr_length: usize,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, AnyError> {
|
||||
) -> Result<Vec<u8>, EncryptError> {
|
||||
let key = key.as_secret_key()?;
|
||||
|
||||
match ctr_length {
|
||||
|
@ -289,22 +305,20 @@ fn encrypt_aes_ctr(
|
|||
128 => encrypt_aes_ctr_gen::<Ctr32BE<aes::Aes128>>(key, counter, data),
|
||||
192 => encrypt_aes_ctr_gen::<Ctr32BE<aes::Aes192>>(key, counter, data),
|
||||
256 => encrypt_aes_ctr_gen::<Ctr32BE<aes::Aes256>>(key, counter, data),
|
||||
_ => Err(type_error("invalid length")),
|
||||
_ => Err(EncryptError::InvalidLength),
|
||||
},
|
||||
64 => match key_length {
|
||||
128 => encrypt_aes_ctr_gen::<Ctr64BE<aes::Aes128>>(key, counter, data),
|
||||
192 => encrypt_aes_ctr_gen::<Ctr64BE<aes::Aes192>>(key, counter, data),
|
||||
256 => encrypt_aes_ctr_gen::<Ctr64BE<aes::Aes256>>(key, counter, data),
|
||||
_ => Err(type_error("invalid length")),
|
||||
_ => Err(EncryptError::InvalidLength),
|
||||
},
|
||||
128 => match key_length {
|
||||
128 => encrypt_aes_ctr_gen::<Ctr128BE<aes::Aes128>>(key, counter, data),
|
||||
192 => encrypt_aes_ctr_gen::<Ctr128BE<aes::Aes192>>(key, counter, data),
|
||||
256 => encrypt_aes_ctr_gen::<Ctr128BE<aes::Aes256>>(key, counter, data),
|
||||
_ => Err(type_error("invalid length")),
|
||||
_ => Err(EncryptError::InvalidLength),
|
||||
},
|
||||
_ => Err(type_error(
|
||||
"invalid counter length. Currently supported 32/64/128 bits",
|
||||
)),
|
||||
_ => Err(EncryptError::InvalidCounterLength),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ use base64::prelude::BASE64_URL_SAFE_NO_PAD;
|
|||
use base64::Engine;
|
||||
use const_oid::AssociatedOid;
|
||||
use const_oid::ObjectIdentifier;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op2;
|
||||
use deno_core::ToJsBuffer;
|
||||
use elliptic_curve::sec1::ToEncodedPoint;
|
||||
|
@ -22,6 +20,16 @@ use spki::AlgorithmIdentifierOwned;
|
|||
|
||||
use crate::shared::*;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ExportKeyError {
|
||||
#[error(transparent)]
|
||||
General(#[from] SharedError),
|
||||
#[error(transparent)]
|
||||
Der(#[from] spki::der::Error),
|
||||
#[error("Unsupported named curve")]
|
||||
UnsupportedNamedCurve,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExportKeyOptions {
|
||||
|
@ -99,7 +107,7 @@ pub enum ExportKeyResult {
|
|||
pub fn op_crypto_export_key(
|
||||
#[serde] opts: ExportKeyOptions,
|
||||
#[serde] key_data: V8RawKeyData,
|
||||
) -> Result<ExportKeyResult, AnyError> {
|
||||
) -> Result<ExportKeyResult, ExportKeyError> {
|
||||
match opts.algorithm {
|
||||
ExportKeyAlgorithm::RsassaPkcs1v15 {}
|
||||
| ExportKeyAlgorithm::RsaPss {}
|
||||
|
@ -125,7 +133,7 @@ fn bytes_to_b64(bytes: &[u8]) -> String {
|
|||
fn export_key_rsa(
|
||||
format: ExportKeyFormat,
|
||||
key_data: V8RawKeyData,
|
||||
) -> Result<ExportKeyResult, deno_core::anyhow::Error> {
|
||||
) -> Result<ExportKeyResult, ExportKeyError> {
|
||||
match format {
|
||||
ExportKeyFormat::Spki => {
|
||||
let subject_public_key = &key_data.as_rsa_public_key()?;
|
||||
|
@ -181,12 +189,7 @@ fn export_key_rsa(
|
|||
ExportKeyFormat::JwkPublic => {
|
||||
let public_key = key_data.as_rsa_public_key()?;
|
||||
let public_key = rsa::pkcs1::RsaPublicKey::from_der(&public_key)
|
||||
.map_err(|_| {
|
||||
custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"failed to decode public key",
|
||||
)
|
||||
})?;
|
||||
.map_err(|_| SharedError::FailedDecodePublicKey)?;
|
||||
|
||||
Ok(ExportKeyResult::JwkPublicRsa {
|
||||
n: uint_to_b64(public_key.modulus),
|
||||
|
@ -196,12 +199,7 @@ fn export_key_rsa(
|
|||
ExportKeyFormat::JwkPrivate => {
|
||||
let private_key = key_data.as_rsa_private_key()?;
|
||||
let private_key = rsa::pkcs1::RsaPrivateKey::from_der(private_key)
|
||||
.map_err(|_| {
|
||||
custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"failed to decode private key",
|
||||
)
|
||||
})?;
|
||||
.map_err(|_| SharedError::FailedDecodePrivateKey)?;
|
||||
|
||||
Ok(ExportKeyResult::JwkPrivateRsa {
|
||||
n: uint_to_b64(private_key.modulus),
|
||||
|
@ -214,14 +212,14 @@ fn export_key_rsa(
|
|||
qi: uint_to_b64(private_key.coefficient),
|
||||
})
|
||||
}
|
||||
_ => Err(unsupported_format()),
|
||||
_ => Err(SharedError::UnsupportedFormat.into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn export_key_symmetric(
|
||||
format: ExportKeyFormat,
|
||||
key_data: V8RawKeyData,
|
||||
) -> Result<ExportKeyResult, deno_core::anyhow::Error> {
|
||||
) -> Result<ExportKeyResult, ExportKeyError> {
|
||||
match format {
|
||||
ExportKeyFormat::JwkSecret => {
|
||||
let bytes = key_data.as_secret_key()?;
|
||||
|
@ -230,7 +228,7 @@ fn export_key_symmetric(
|
|||
k: bytes_to_b64(bytes),
|
||||
})
|
||||
}
|
||||
_ => Err(unsupported_format()),
|
||||
_ => Err(SharedError::UnsupportedFormat.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,7 +237,7 @@ fn export_key_ec(
|
|||
key_data: V8RawKeyData,
|
||||
algorithm: ExportKeyAlgorithm,
|
||||
named_curve: EcNamedCurve,
|
||||
) -> Result<ExportKeyResult, deno_core::anyhow::Error> {
|
||||
) -> Result<ExportKeyResult, ExportKeyError> {
|
||||
match format {
|
||||
ExportKeyFormat::Raw => {
|
||||
let subject_public_key = match named_curve {
|
||||
|
@ -332,10 +330,7 @@ fn export_key_ec(
|
|||
y: bytes_to_b64(y),
|
||||
})
|
||||
} else {
|
||||
Err(custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"failed to decode public key",
|
||||
))
|
||||
Err(SharedError::FailedDecodePublicKey.into())
|
||||
}
|
||||
}
|
||||
EcNamedCurve::P384 => {
|
||||
|
@ -350,10 +345,7 @@ fn export_key_ec(
|
|||
y: bytes_to_b64(y),
|
||||
})
|
||||
} else {
|
||||
Err(custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"failed to decode public key",
|
||||
))
|
||||
Err(SharedError::FailedDecodePublicKey.into())
|
||||
}
|
||||
}
|
||||
EcNamedCurve::P521 => {
|
||||
|
@ -368,10 +360,7 @@ fn export_key_ec(
|
|||
y: bytes_to_b64(y),
|
||||
})
|
||||
} else {
|
||||
Err(custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"failed to decode public key",
|
||||
))
|
||||
Err(SharedError::FailedDecodePublicKey.into())
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -380,13 +369,8 @@ fn export_key_ec(
|
|||
|
||||
match named_curve {
|
||||
EcNamedCurve::P256 => {
|
||||
let ec_key =
|
||||
p256::SecretKey::from_pkcs8_der(private_key).map_err(|_| {
|
||||
custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"failed to decode private key",
|
||||
)
|
||||
})?;
|
||||
let ec_key = p256::SecretKey::from_pkcs8_der(private_key)
|
||||
.map_err(|_| SharedError::FailedDecodePrivateKey)?;
|
||||
|
||||
let point = ec_key.public_key().to_encoded_point(false);
|
||||
if let elliptic_curve::sec1::Coordinates::Uncompressed { x, y } =
|
||||
|
@ -398,18 +382,13 @@ fn export_key_ec(
|
|||
d: bytes_to_b64(&ec_key.to_bytes()),
|
||||
})
|
||||
} else {
|
||||
Err(data_error("expected valid public EC key"))
|
||||
Err(SharedError::ExpectedValidPublicECKey.into())
|
||||
}
|
||||
}
|
||||
|
||||
EcNamedCurve::P384 => {
|
||||
let ec_key =
|
||||
p384::SecretKey::from_pkcs8_der(private_key).map_err(|_| {
|
||||
custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"failed to decode private key",
|
||||
)
|
||||
})?;
|
||||
let ec_key = p384::SecretKey::from_pkcs8_der(private_key)
|
||||
.map_err(|_| SharedError::FailedDecodePrivateKey)?;
|
||||
|
||||
let point = ec_key.public_key().to_encoded_point(false);
|
||||
if let elliptic_curve::sec1::Coordinates::Uncompressed { x, y } =
|
||||
|
@ -421,12 +400,12 @@ fn export_key_ec(
|
|||
d: bytes_to_b64(&ec_key.to_bytes()),
|
||||
})
|
||||
} else {
|
||||
Err(data_error("expected valid public EC key"))
|
||||
Err(SharedError::ExpectedValidPublicECKey.into())
|
||||
}
|
||||
}
|
||||
_ => Err(not_supported_error("Unsupported namedCurve")),
|
||||
_ => Err(ExportKeyError::UnsupportedNamedCurve),
|
||||
}
|
||||
}
|
||||
ExportKeyFormat::JwkSecret => Err(unsupported_format()),
|
||||
ExportKeyFormat::JwkSecret => Err(SharedError::UnsupportedFormat.into()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op2;
|
||||
use deno_core::unsync::spawn_blocking;
|
||||
use deno_core::ToJsBuffer;
|
||||
|
@ -16,6 +15,26 @@ use serde::Deserialize;
|
|||
|
||||
use crate::shared::*;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum GenerateKeyError {
|
||||
#[error(transparent)]
|
||||
General(#[from] SharedError),
|
||||
#[error("Bad public exponent")]
|
||||
BadPublicExponent,
|
||||
#[error("Invalid HMAC key length")]
|
||||
InvalidHMACKeyLength,
|
||||
#[error("Failed to serialize RSA key")]
|
||||
FailedRSAKeySerialization,
|
||||
#[error("Invalid AES key length")]
|
||||
InvalidAESKeyLength,
|
||||
#[error("Failed to generate RSA key")]
|
||||
FailedRSAKeyGeneration,
|
||||
#[error("Failed to generate EC key")]
|
||||
FailedECKeyGeneration,
|
||||
#[error("Failed to generate key")]
|
||||
FailedKeyGeneration,
|
||||
}
|
||||
|
||||
// Allowlist for RSA public exponents.
|
||||
static PUB_EXPONENT_1: Lazy<BigUint> =
|
||||
Lazy::new(|| BigUint::from_u64(3).unwrap());
|
||||
|
@ -46,7 +65,7 @@ pub enum GenerateKeyOptions {
|
|||
#[serde]
|
||||
pub async fn op_crypto_generate_key(
|
||||
#[serde] opts: GenerateKeyOptions,
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, GenerateKeyError> {
|
||||
let fun = || match opts {
|
||||
GenerateKeyOptions::Rsa {
|
||||
modulus_length,
|
||||
|
@ -65,21 +84,21 @@ pub async fn op_crypto_generate_key(
|
|||
fn generate_key_rsa(
|
||||
modulus_length: u32,
|
||||
public_exponent: &[u8],
|
||||
) -> Result<Vec<u8>, AnyError> {
|
||||
) -> Result<Vec<u8>, GenerateKeyError> {
|
||||
let exponent = BigUint::from_bytes_be(public_exponent);
|
||||
if exponent != *PUB_EXPONENT_1 && exponent != *PUB_EXPONENT_2 {
|
||||
return Err(operation_error("Bad public exponent"));
|
||||
return Err(GenerateKeyError::BadPublicExponent);
|
||||
}
|
||||
|
||||
let mut rng = OsRng;
|
||||
|
||||
let private_key =
|
||||
RsaPrivateKey::new_with_exp(&mut rng, modulus_length as usize, &exponent)
|
||||
.map_err(|_| operation_error("Failed to generate RSA key"))?;
|
||||
.map_err(|_| GenerateKeyError::FailedRSAKeyGeneration)?;
|
||||
|
||||
let private_key = private_key
|
||||
.to_pkcs1_der()
|
||||
.map_err(|_| operation_error("Failed to serialize RSA key"))?;
|
||||
.map_err(|_| GenerateKeyError::FailedRSAKeySerialization)?;
|
||||
|
||||
Ok(private_key.as_bytes().to_vec())
|
||||
}
|
||||
|
@ -90,7 +109,9 @@ fn generate_key_ec_p521() -> Vec<u8> {
|
|||
key.to_nonzero_scalar().to_bytes().to_vec()
|
||||
}
|
||||
|
||||
fn generate_key_ec(named_curve: EcNamedCurve) -> Result<Vec<u8>, AnyError> {
|
||||
fn generate_key_ec(
|
||||
named_curve: EcNamedCurve,
|
||||
) -> Result<Vec<u8>, GenerateKeyError> {
|
||||
let curve = match named_curve {
|
||||
EcNamedCurve::P256 => &ring::signature::ECDSA_P256_SHA256_FIXED_SIGNING,
|
||||
EcNamedCurve::P384 => &ring::signature::ECDSA_P384_SHA384_FIXED_SIGNING,
|
||||
|
@ -100,21 +121,21 @@ fn generate_key_ec(named_curve: EcNamedCurve) -> Result<Vec<u8>, AnyError> {
|
|||
let rng = ring::rand::SystemRandom::new();
|
||||
|
||||
let pkcs8 = EcdsaKeyPair::generate_pkcs8(curve, &rng)
|
||||
.map_err(|_| operation_error("Failed to generate EC key"))?;
|
||||
.map_err(|_| GenerateKeyError::FailedECKeyGeneration)?;
|
||||
|
||||
Ok(pkcs8.as_ref().to_vec())
|
||||
}
|
||||
|
||||
fn generate_key_aes(length: usize) -> Result<Vec<u8>, AnyError> {
|
||||
fn generate_key_aes(length: usize) -> Result<Vec<u8>, GenerateKeyError> {
|
||||
if length % 8 != 0 || length > 256 {
|
||||
return Err(operation_error("Invalid AES key length"));
|
||||
return Err(GenerateKeyError::InvalidAESKeyLength);
|
||||
}
|
||||
|
||||
let mut key = vec![0u8; length / 8];
|
||||
let rng = ring::rand::SystemRandom::new();
|
||||
rng
|
||||
.fill(&mut key)
|
||||
.map_err(|_| operation_error("Failed to generate key"))?;
|
||||
.map_err(|_| GenerateKeyError::FailedKeyGeneration)?;
|
||||
|
||||
Ok(key)
|
||||
}
|
||||
|
@ -122,7 +143,7 @@ fn generate_key_aes(length: usize) -> Result<Vec<u8>, AnyError> {
|
|||
fn generate_key_hmac(
|
||||
hash: ShaHash,
|
||||
length: Option<usize>,
|
||||
) -> Result<Vec<u8>, AnyError> {
|
||||
) -> Result<Vec<u8>, GenerateKeyError> {
|
||||
let hash = match hash {
|
||||
ShaHash::Sha1 => &ring::hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY,
|
||||
ShaHash::Sha256 => &ring::hmac::HMAC_SHA256,
|
||||
|
@ -132,12 +153,12 @@ fn generate_key_hmac(
|
|||
|
||||
let length = if let Some(length) = length {
|
||||
if length % 8 != 0 {
|
||||
return Err(operation_error("Invalid HMAC key length"));
|
||||
return Err(GenerateKeyError::InvalidHMACKeyLength);
|
||||
}
|
||||
|
||||
let length = length / 8;
|
||||
if length > ring::digest::MAX_BLOCK_LEN {
|
||||
return Err(operation_error("Invalid HMAC key length"));
|
||||
return Err(GenerateKeyError::InvalidHMACKeyLength);
|
||||
}
|
||||
|
||||
length
|
||||
|
@ -149,7 +170,7 @@ fn generate_key_hmac(
|
|||
let mut key = vec![0u8; length];
|
||||
rng
|
||||
.fill(&mut key)
|
||||
.map_err(|_| operation_error("Failed to generate key"))?;
|
||||
.map_err(|_| GenerateKeyError::FailedKeyGeneration)?;
|
||||
|
||||
Ok(key)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use base64::Engine;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op2;
|
||||
use deno_core::JsBuffer;
|
||||
use deno_core::ToJsBuffer;
|
||||
|
@ -15,6 +14,70 @@ use spki::der::Decode;
|
|||
|
||||
use crate::shared::*;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ImportKeyError {
|
||||
#[error(transparent)]
|
||||
General(#[from] SharedError),
|
||||
#[error("invalid modulus")]
|
||||
InvalidModulus,
|
||||
#[error("invalid public exponent")]
|
||||
InvalidPublicExponent,
|
||||
#[error("invalid private exponent")]
|
||||
InvalidPrivateExponent,
|
||||
#[error("invalid first prime factor")]
|
||||
InvalidFirstPrimeFactor,
|
||||
#[error("invalid second prime factor")]
|
||||
InvalidSecondPrimeFactor,
|
||||
#[error("invalid first CRT exponent")]
|
||||
InvalidFirstCRTExponent,
|
||||
#[error("invalid second CRT exponent")]
|
||||
InvalidSecondCRTExponent,
|
||||
#[error("invalid CRT coefficient")]
|
||||
InvalidCRTCoefficient,
|
||||
#[error("invalid b64 coordinate")]
|
||||
InvalidB64Coordinate,
|
||||
#[error("invalid RSA public key")]
|
||||
InvalidRSAPublicKey,
|
||||
#[error("invalid RSA private key")]
|
||||
InvalidRSAPrivateKey,
|
||||
#[error("unsupported algorithm")]
|
||||
UnsupportedAlgorithm,
|
||||
#[error("public key is invalid (too long)")]
|
||||
PublicKeyTooLong,
|
||||
#[error("private key is invalid (too long)")]
|
||||
PrivateKeyTooLong,
|
||||
#[error("invalid P-256 elliptic curve point")]
|
||||
InvalidP256ECPoint,
|
||||
#[error("invalid P-384 elliptic curve point")]
|
||||
InvalidP384ECPoint,
|
||||
#[error("invalid P-521 elliptic curve point")]
|
||||
InvalidP521ECPoint,
|
||||
#[error("invalid P-256 elliptic curve SPKI data")]
|
||||
InvalidP256ECSPKIData,
|
||||
#[error("invalid P-384 elliptic curve SPKI data")]
|
||||
InvalidP384ECSPKIData,
|
||||
#[error("invalid P-521 elliptic curve SPKI data")]
|
||||
InvalidP521ECSPKIData,
|
||||
#[error("curve mismatch")]
|
||||
CurveMismatch,
|
||||
#[error("Unsupported named curve")]
|
||||
UnsupportedNamedCurve,
|
||||
#[error("invalid key data")]
|
||||
InvalidKeyData,
|
||||
#[error("invalid JWK private key")]
|
||||
InvalidJWKPrivateKey,
|
||||
#[error(transparent)]
|
||||
EllipticCurve(#[from] elliptic_curve::Error),
|
||||
#[error("expected valid PKCS#8 data")]
|
||||
ExpectedValidPkcs8Data,
|
||||
#[error("malformed parameters")]
|
||||
MalformedParameters,
|
||||
#[error(transparent)]
|
||||
Spki(#[from] spki::Error),
|
||||
#[error(transparent)]
|
||||
Der(#[from] rsa::pkcs1::der::Error),
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum KeyData {
|
||||
|
@ -93,7 +156,7 @@ pub enum ImportKeyResult {
|
|||
pub fn op_crypto_import_key(
|
||||
#[serde] opts: ImportKeyOptions,
|
||||
#[serde] key_data: KeyData,
|
||||
) -> Result<ImportKeyResult, AnyError> {
|
||||
) -> Result<ImportKeyResult, ImportKeyError> {
|
||||
match opts {
|
||||
ImportKeyOptions::RsassaPkcs1v15 {} => import_key_rsassa(key_data),
|
||||
ImportKeyOptions::RsaPss {} => import_key_rsapss(key_data),
|
||||
|
@ -117,21 +180,21 @@ const BASE64_URL_SAFE_FORGIVING:
|
|||
);
|
||||
|
||||
macro_rules! jwt_b64_int_or_err {
|
||||
($name:ident, $b64:expr, $err:expr) => {
|
||||
($name:ident, $b64:expr, $err:tt) => {
|
||||
let bytes = BASE64_URL_SAFE_FORGIVING
|
||||
.decode($b64)
|
||||
.map_err(|_| data_error($err))?;
|
||||
let $name = UintRef::new(&bytes).map_err(|_| data_error($err))?;
|
||||
.map_err(|_| ImportKeyError::$err)?;
|
||||
let $name = UintRef::new(&bytes).map_err(|_| ImportKeyError::$err)?;
|
||||
};
|
||||
}
|
||||
|
||||
fn import_key_rsa_jwk(
|
||||
key_data: KeyData,
|
||||
) -> Result<ImportKeyResult, deno_core::anyhow::Error> {
|
||||
) -> Result<ImportKeyResult, ImportKeyError> {
|
||||
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");
|
||||
jwt_b64_int_or_err!(modulus, &n, InvalidModulus);
|
||||
jwt_b64_int_or_err!(public_exponent, &e, InvalidPublicExponent);
|
||||
|
||||
let public_key = rsa::pkcs1::RsaPublicKey {
|
||||
modulus,
|
||||
|
@ -141,7 +204,7 @@ fn import_key_rsa_jwk(
|
|||
let mut data = Vec::new();
|
||||
public_key
|
||||
.encode_to_vec(&mut data)
|
||||
.map_err(|_| data_error("invalid rsa public key"))?;
|
||||
.map_err(|_| ImportKeyError::InvalidRSAPublicKey)?;
|
||||
|
||||
let public_exponent =
|
||||
public_key.public_exponent.as_bytes().to_vec().into();
|
||||
|
@ -163,14 +226,14 @@ fn import_key_rsa_jwk(
|
|||
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");
|
||||
jwt_b64_int_or_err!(modulus, &n, InvalidModulus);
|
||||
jwt_b64_int_or_err!(public_exponent, &e, InvalidPublicExponent);
|
||||
jwt_b64_int_or_err!(private_exponent, &d, InvalidPrivateExponent);
|
||||
jwt_b64_int_or_err!(prime1, &p, InvalidFirstPrimeFactor);
|
||||
jwt_b64_int_or_err!(prime2, &q, InvalidSecondPrimeFactor);
|
||||
jwt_b64_int_or_err!(exponent1, &dp, InvalidFirstCRTExponent);
|
||||
jwt_b64_int_or_err!(exponent2, &dq, InvalidSecondCRTExponent);
|
||||
jwt_b64_int_or_err!(coefficient, &qi, InvalidCRTCoefficient);
|
||||
|
||||
let private_key = rsa::pkcs1::RsaPrivateKey {
|
||||
modulus,
|
||||
|
@ -187,7 +250,7 @@ fn import_key_rsa_jwk(
|
|||
let mut data = Vec::new();
|
||||
private_key
|
||||
.encode_to_vec(&mut data)
|
||||
.map_err(|_| data_error("invalid rsa private key"))?;
|
||||
.map_err(|_| ImportKeyError::InvalidRSAPrivateKey)?;
|
||||
|
||||
let public_exponent =
|
||||
private_key.public_exponent.as_bytes().to_vec().into();
|
||||
|
@ -205,37 +268,33 @@ fn import_key_rsa_jwk(
|
|||
|
||||
fn import_key_rsassa(
|
||||
key_data: KeyData,
|
||||
) -> Result<ImportKeyResult, deno_core::anyhow::Error> {
|
||||
) -> Result<ImportKeyResult, ImportKeyError> {
|
||||
match key_data {
|
||||
KeyData::Spki(data) => {
|
||||
// 2-3.
|
||||
let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data)?;
|
||||
|
||||
// 4-5.
|
||||
let alg = pk_info.algorithm.oid;
|
||||
|
||||
// 6-7. (skipped, only support rsaEncryption for interoperability)
|
||||
if alg != RSA_ENCRYPTION_OID {
|
||||
return Err(data_error("unsupported algorithm"));
|
||||
return Err(ImportKeyError::UnsupportedAlgorithm);
|
||||
}
|
||||
|
||||
// 8-9.
|
||||
let public_key = rsa::pkcs1::RsaPublicKey::from_der(
|
||||
pk_info.subject_public_key.raw_bytes(),
|
||||
)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
)?;
|
||||
|
||||
let bytes_consumed = public_key
|
||||
.encoded_len()
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let bytes_consumed = public_key.encoded_len()?;
|
||||
|
||||
if bytes_consumed
|
||||
!= rsa::pkcs1::der::Length::new(
|
||||
pk_info.subject_public_key.raw_bytes().len() as u16,
|
||||
)
|
||||
{
|
||||
return Err(data_error("public key is invalid (too long)"));
|
||||
return Err(ImportKeyError::PublicKeyTooLong);
|
||||
}
|
||||
|
||||
let data = pk_info.subject_public_key.raw_bytes().to_vec().into();
|
||||
|
@ -251,30 +310,26 @@ fn import_key_rsassa(
|
|||
}
|
||||
KeyData::Pkcs8(data) => {
|
||||
// 2-3.
|
||||
let pk_info = PrivateKeyInfo::from_der(&data)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let pk_info = PrivateKeyInfo::from_der(&data)?;
|
||||
|
||||
// 4-5.
|
||||
let alg = pk_info.algorithm.oid;
|
||||
|
||||
// 6-7. (skipped, only support rsaEncryption for interoperability)
|
||||
if alg != RSA_ENCRYPTION_OID {
|
||||
return Err(data_error("unsupported algorithm"));
|
||||
return Err(ImportKeyError::UnsupportedAlgorithm);
|
||||
}
|
||||
|
||||
// 8-9.
|
||||
let private_key =
|
||||
rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)?;
|
||||
|
||||
let bytes_consumed = private_key
|
||||
.encoded_len()
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let bytes_consumed = private_key.encoded_len()?;
|
||||
|
||||
if bytes_consumed
|
||||
!= rsa::pkcs1::der::Length::new(pk_info.private_key.len() as u16)
|
||||
{
|
||||
return Err(data_error("private key is invalid (too long)"));
|
||||
return Err(ImportKeyError::PrivateKeyTooLong);
|
||||
}
|
||||
|
||||
let data = pk_info.private_key.to_vec().into();
|
||||
|
@ -291,43 +346,39 @@ fn import_key_rsassa(
|
|||
KeyData::JwkPublicRsa { .. } | KeyData::JwkPrivateRsa { .. } => {
|
||||
import_key_rsa_jwk(key_data)
|
||||
}
|
||||
_ => Err(unsupported_format()),
|
||||
_ => Err(SharedError::UnsupportedFormat.into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn import_key_rsapss(
|
||||
key_data: KeyData,
|
||||
) -> Result<ImportKeyResult, deno_core::anyhow::Error> {
|
||||
) -> Result<ImportKeyResult, ImportKeyError> {
|
||||
match key_data {
|
||||
KeyData::Spki(data) => {
|
||||
// 2-3.
|
||||
let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data)?;
|
||||
|
||||
// 4-5.
|
||||
let alg = pk_info.algorithm.oid;
|
||||
|
||||
// 6-7. (skipped, only support rsaEncryption for interoperability)
|
||||
if alg != RSA_ENCRYPTION_OID {
|
||||
return Err(data_error("unsupported algorithm"));
|
||||
return Err(ImportKeyError::UnsupportedAlgorithm);
|
||||
}
|
||||
|
||||
// 8-9.
|
||||
let public_key = rsa::pkcs1::RsaPublicKey::from_der(
|
||||
pk_info.subject_public_key.raw_bytes(),
|
||||
)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
)?;
|
||||
|
||||
let bytes_consumed = public_key
|
||||
.encoded_len()
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let bytes_consumed = public_key.encoded_len()?;
|
||||
|
||||
if bytes_consumed
|
||||
!= rsa::pkcs1::der::Length::new(
|
||||
pk_info.subject_public_key.raw_bytes().len() as u16,
|
||||
)
|
||||
{
|
||||
return Err(data_error("public key is invalid (too long)"));
|
||||
return Err(ImportKeyError::PublicKeyTooLong);
|
||||
}
|
||||
|
||||
let data = pk_info.subject_public_key.raw_bytes().to_vec().into();
|
||||
|
@ -343,30 +394,26 @@ fn import_key_rsapss(
|
|||
}
|
||||
KeyData::Pkcs8(data) => {
|
||||
// 2-3.
|
||||
let pk_info = PrivateKeyInfo::from_der(&data)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let pk_info = PrivateKeyInfo::from_der(&data)?;
|
||||
|
||||
// 4-5.
|
||||
let alg = pk_info.algorithm.oid;
|
||||
|
||||
// 6-7. (skipped, only support rsaEncryption for interoperability)
|
||||
if alg != RSA_ENCRYPTION_OID {
|
||||
return Err(data_error("unsupported algorithm"));
|
||||
return Err(ImportKeyError::UnsupportedAlgorithm);
|
||||
}
|
||||
|
||||
// 8-9.
|
||||
let private_key =
|
||||
rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)?;
|
||||
|
||||
let bytes_consumed = private_key
|
||||
.encoded_len()
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let bytes_consumed = private_key.encoded_len()?;
|
||||
|
||||
if bytes_consumed
|
||||
!= rsa::pkcs1::der::Length::new(pk_info.private_key.len() as u16)
|
||||
{
|
||||
return Err(data_error("private key is invalid (too long)"));
|
||||
return Err(ImportKeyError::PrivateKeyTooLong);
|
||||
}
|
||||
|
||||
let data = pk_info.private_key.to_vec().into();
|
||||
|
@ -383,43 +430,39 @@ fn import_key_rsapss(
|
|||
KeyData::JwkPublicRsa { .. } | KeyData::JwkPrivateRsa { .. } => {
|
||||
import_key_rsa_jwk(key_data)
|
||||
}
|
||||
_ => Err(unsupported_format()),
|
||||
_ => Err(SharedError::UnsupportedFormat.into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn import_key_rsaoaep(
|
||||
key_data: KeyData,
|
||||
) -> Result<ImportKeyResult, deno_core::anyhow::Error> {
|
||||
) -> Result<ImportKeyResult, ImportKeyError> {
|
||||
match key_data {
|
||||
KeyData::Spki(data) => {
|
||||
// 2-3.
|
||||
let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data)?;
|
||||
|
||||
// 4-5.
|
||||
let alg = pk_info.algorithm.oid;
|
||||
|
||||
// 6-7. (skipped, only support rsaEncryption for interoperability)
|
||||
if alg != RSA_ENCRYPTION_OID {
|
||||
return Err(data_error("unsupported algorithm"));
|
||||
return Err(ImportKeyError::UnsupportedAlgorithm);
|
||||
}
|
||||
|
||||
// 8-9.
|
||||
let public_key = rsa::pkcs1::RsaPublicKey::from_der(
|
||||
pk_info.subject_public_key.raw_bytes(),
|
||||
)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
)?;
|
||||
|
||||
let bytes_consumed = public_key
|
||||
.encoded_len()
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let bytes_consumed = public_key.encoded_len()?;
|
||||
|
||||
if bytes_consumed
|
||||
!= rsa::pkcs1::der::Length::new(
|
||||
pk_info.subject_public_key.raw_bytes().len() as u16,
|
||||
)
|
||||
{
|
||||
return Err(data_error("public key is invalid (too long)"));
|
||||
return Err(ImportKeyError::PublicKeyTooLong);
|
||||
}
|
||||
|
||||
let data = pk_info.subject_public_key.raw_bytes().to_vec().into();
|
||||
|
@ -435,30 +478,26 @@ fn import_key_rsaoaep(
|
|||
}
|
||||
KeyData::Pkcs8(data) => {
|
||||
// 2-3.
|
||||
let pk_info = PrivateKeyInfo::from_der(&data)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let pk_info = PrivateKeyInfo::from_der(&data)?;
|
||||
|
||||
// 4-5.
|
||||
let alg = pk_info.algorithm.oid;
|
||||
|
||||
// 6-7. (skipped, only support rsaEncryption for interoperability)
|
||||
if alg != RSA_ENCRYPTION_OID {
|
||||
return Err(data_error("unsupported algorithm"));
|
||||
return Err(ImportKeyError::UnsupportedAlgorithm);
|
||||
}
|
||||
|
||||
// 8-9.
|
||||
let private_key =
|
||||
rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
rsa::pkcs1::RsaPrivateKey::from_der(pk_info.private_key)?;
|
||||
|
||||
let bytes_consumed = private_key
|
||||
.encoded_len()
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let bytes_consumed = private_key.encoded_len()?;
|
||||
|
||||
if bytes_consumed
|
||||
!= rsa::pkcs1::der::Length::new(pk_info.private_key.len() as u16)
|
||||
{
|
||||
return Err(data_error("private key is invalid (too long)"));
|
||||
return Err(ImportKeyError::PrivateKeyTooLong);
|
||||
}
|
||||
|
||||
let data = pk_info.private_key.to_vec().into();
|
||||
|
@ -475,14 +514,14 @@ fn import_key_rsaoaep(
|
|||
KeyData::JwkPublicRsa { .. } | KeyData::JwkPrivateRsa { .. } => {
|
||||
import_key_rsa_jwk(key_data)
|
||||
}
|
||||
_ => Err(unsupported_format()),
|
||||
_ => Err(SharedError::UnsupportedFormat.into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_b64url_to_field_bytes<C: elliptic_curve::Curve>(
|
||||
b64: &str,
|
||||
) -> Result<elliptic_curve::FieldBytes<C>, deno_core::anyhow::Error> {
|
||||
jwt_b64_int_or_err!(val, b64, "invalid b64 coordinate");
|
||||
) -> Result<elliptic_curve::FieldBytes<C>, ImportKeyError> {
|
||||
jwt_b64_int_or_err!(val, b64, InvalidB64Coordinate);
|
||||
|
||||
let mut bytes = elliptic_curve::FieldBytes::<C>::default();
|
||||
let original_bytes = val.as_bytes();
|
||||
|
@ -495,7 +534,7 @@ fn decode_b64url_to_field_bytes<C: elliptic_curve::Curve>(
|
|||
let val = new_bytes.as_slice();
|
||||
|
||||
if val.len() != bytes.len() {
|
||||
return Err(data_error("invalid b64 coordinate"));
|
||||
return Err(ImportKeyError::InvalidB64Coordinate);
|
||||
}
|
||||
bytes.copy_from_slice(val);
|
||||
|
||||
|
@ -506,7 +545,7 @@ fn import_key_ec_jwk_to_point(
|
|||
x: String,
|
||||
y: String,
|
||||
named_curve: EcNamedCurve,
|
||||
) -> Result<Vec<u8>, deno_core::anyhow::Error> {
|
||||
) -> Result<Vec<u8>, ImportKeyError> {
|
||||
let point_bytes = match named_curve {
|
||||
EcNamedCurve::P256 => {
|
||||
let x = decode_b64url_to_field_bytes::<p256::NistP256>(&x)?;
|
||||
|
@ -534,7 +573,7 @@ fn import_key_ec_jwk_to_point(
|
|||
fn import_key_ec_jwk(
|
||||
key_data: KeyData,
|
||||
named_curve: EcNamedCurve,
|
||||
) -> Result<ImportKeyResult, deno_core::anyhow::Error> {
|
||||
) -> Result<ImportKeyResult, ImportKeyError> {
|
||||
match key_data {
|
||||
KeyData::JwkPublicEc { x, y } => {
|
||||
let point_bytes = import_key_ec_jwk_to_point(x, y, named_curve)?;
|
||||
|
@ -550,21 +589,21 @@ fn import_key_ec_jwk(
|
|||
let pk = p256::SecretKey::from_bytes(&d)?;
|
||||
|
||||
pk.to_pkcs8_der()
|
||||
.map_err(|_| data_error("invalid JWK private key"))?
|
||||
.map_err(|_| ImportKeyError::InvalidJWKPrivateKey)?
|
||||
}
|
||||
EcNamedCurve::P384 => {
|
||||
let d = decode_b64url_to_field_bytes::<p384::NistP384>(&d)?;
|
||||
let pk = p384::SecretKey::from_bytes(&d)?;
|
||||
|
||||
pk.to_pkcs8_der()
|
||||
.map_err(|_| data_error("invalid JWK private key"))?
|
||||
.map_err(|_| ImportKeyError::InvalidJWKPrivateKey)?
|
||||
}
|
||||
EcNamedCurve::P521 => {
|
||||
let d = decode_b64url_to_field_bytes::<p521::NistP521>(&d)?;
|
||||
let pk = p521::SecretKey::from_bytes(&d)?;
|
||||
|
||||
pk.to_pkcs8_der()
|
||||
.map_err(|_| data_error("invalid JWK private key"))?
|
||||
.map_err(|_| ImportKeyError::InvalidJWKPrivateKey)?
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -595,7 +634,7 @@ impl<'a> TryFrom<spki::der::asn1::AnyRef<'a>> for ECParametersSpki {
|
|||
fn import_key_ec(
|
||||
key_data: KeyData,
|
||||
named_curve: EcNamedCurve,
|
||||
) -> Result<ImportKeyResult, AnyError> {
|
||||
) -> Result<ImportKeyResult, ImportKeyError> {
|
||||
match key_data {
|
||||
KeyData::Raw(data) => {
|
||||
// The point is parsed and validated, ultimately the original data is
|
||||
|
@ -604,28 +643,28 @@ fn import_key_ec(
|
|||
EcNamedCurve::P256 => {
|
||||
// 1-2.
|
||||
let point = p256::EncodedPoint::from_bytes(&data)
|
||||
.map_err(|_| data_error("invalid P-256 elliptic curve point"))?;
|
||||
.map_err(|_| ImportKeyError::InvalidP256ECPoint)?;
|
||||
// 3.
|
||||
if point.is_identity() {
|
||||
return Err(data_error("invalid P-256 elliptic curve point"));
|
||||
return Err(ImportKeyError::InvalidP256ECPoint);
|
||||
}
|
||||
}
|
||||
EcNamedCurve::P384 => {
|
||||
// 1-2.
|
||||
let point = p384::EncodedPoint::from_bytes(&data)
|
||||
.map_err(|_| data_error("invalid P-384 elliptic curve point"))?;
|
||||
.map_err(|_| ImportKeyError::InvalidP384ECPoint)?;
|
||||
// 3.
|
||||
if point.is_identity() {
|
||||
return Err(data_error("invalid P-384 elliptic curve point"));
|
||||
return Err(ImportKeyError::InvalidP384ECPoint);
|
||||
}
|
||||
}
|
||||
EcNamedCurve::P521 => {
|
||||
// 1-2.
|
||||
let point = p521::EncodedPoint::from_bytes(&data)
|
||||
.map_err(|_| data_error("invalid P-521 elliptic curve point"))?;
|
||||
.map_err(|_| ImportKeyError::InvalidP521ECPoint)?;
|
||||
// 3.
|
||||
if point.is_identity() {
|
||||
return Err(data_error("invalid P-521 elliptic curve point"));
|
||||
return Err(ImportKeyError::InvalidP521ECPoint);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -635,11 +674,11 @@ fn import_key_ec(
|
|||
}
|
||||
KeyData::Pkcs8(data) => {
|
||||
let pk = PrivateKeyInfo::from_der(data.as_ref())
|
||||
.map_err(|_| data_error("expected valid PKCS#8 data"))?;
|
||||
.map_err(|_| ImportKeyError::ExpectedValidPkcs8Data)?;
|
||||
let named_curve_alg = pk
|
||||
.algorithm
|
||||
.parameters
|
||||
.ok_or_else(|| data_error("malformed parameters"))?
|
||||
.ok_or(ImportKeyError::MalformedParameters)?
|
||||
.try_into()
|
||||
.unwrap();
|
||||
|
||||
|
@ -654,7 +693,7 @@ fn import_key_ec(
|
|||
};
|
||||
|
||||
if pk_named_curve != Some(named_curve) {
|
||||
return Err(data_error("curve mismatch"));
|
||||
return Err(ImportKeyError::CurveMismatch);
|
||||
}
|
||||
|
||||
Ok(ImportKeyResult::Ec {
|
||||
|
@ -663,14 +702,13 @@ fn import_key_ec(
|
|||
}
|
||||
KeyData::Spki(data) => {
|
||||
// 2-3.
|
||||
let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data)
|
||||
.map_err(|e| data_error(e.to_string()))?;
|
||||
let pk_info = spki::SubjectPublicKeyInfoRef::try_from(&*data)?;
|
||||
|
||||
// 4.
|
||||
let alg = pk_info.algorithm.oid;
|
||||
// id-ecPublicKey
|
||||
if alg != elliptic_curve::ALGORITHM_OID {
|
||||
return Err(data_error("unsupported algorithm"));
|
||||
return Err(ImportKeyError::UnsupportedAlgorithm);
|
||||
}
|
||||
|
||||
// 5-7.
|
||||
|
@ -678,9 +716,9 @@ fn import_key_ec(
|
|||
pk_info
|
||||
.algorithm
|
||||
.parameters
|
||||
.ok_or_else(|| data_error("malformed parameters"))?,
|
||||
.ok_or(ImportKeyError::MalformedParameters)?,
|
||||
)
|
||||
.map_err(|_| data_error("malformed parameters"))?;
|
||||
.map_err(|_| ImportKeyError::MalformedParameters)?;
|
||||
|
||||
// 8-9.
|
||||
let named_curve_alg = params.named_curve_alg;
|
||||
|
@ -704,36 +742,30 @@ fn import_key_ec(
|
|||
|
||||
let bytes_consumed = match named_curve {
|
||||
EcNamedCurve::P256 => {
|
||||
let point =
|
||||
p256::EncodedPoint::from_bytes(&*encoded_key).map_err(|_| {
|
||||
data_error("invalid P-256 elliptic curve SPKI data")
|
||||
})?;
|
||||
let point = p256::EncodedPoint::from_bytes(&*encoded_key)
|
||||
.map_err(|_| ImportKeyError::InvalidP256ECSPKIData)?;
|
||||
if point.is_identity() {
|
||||
return Err(data_error("invalid P-256 elliptic curve point"));
|
||||
return Err(ImportKeyError::InvalidP256ECPoint);
|
||||
}
|
||||
|
||||
point.as_bytes().len()
|
||||
}
|
||||
EcNamedCurve::P384 => {
|
||||
let point =
|
||||
p384::EncodedPoint::from_bytes(&*encoded_key).map_err(|_| {
|
||||
data_error("invalid P-384 elliptic curve SPKI data")
|
||||
})?;
|
||||
let point = p384::EncodedPoint::from_bytes(&*encoded_key)
|
||||
.map_err(|_| ImportKeyError::InvalidP384ECSPKIData)?;
|
||||
|
||||
if point.is_identity() {
|
||||
return Err(data_error("invalid P-384 elliptic curve point"));
|
||||
return Err(ImportKeyError::InvalidP384ECPoint);
|
||||
}
|
||||
|
||||
point.as_bytes().len()
|
||||
}
|
||||
EcNamedCurve::P521 => {
|
||||
let point =
|
||||
p521::EncodedPoint::from_bytes(&*encoded_key).map_err(|_| {
|
||||
data_error("invalid P-521 elliptic curve SPKI data")
|
||||
})?;
|
||||
let point = p521::EncodedPoint::from_bytes(&*encoded_key)
|
||||
.map_err(|_| ImportKeyError::InvalidP521ECSPKIData)?;
|
||||
|
||||
if point.is_identity() {
|
||||
return Err(data_error("invalid P-521 elliptic curve point"));
|
||||
return Err(ImportKeyError::InvalidP521ECPoint);
|
||||
}
|
||||
|
||||
point.as_bytes().len()
|
||||
|
@ -741,15 +773,15 @@ fn import_key_ec(
|
|||
};
|
||||
|
||||
if bytes_consumed != pk_info.subject_public_key.raw_bytes().len() {
|
||||
return Err(data_error("public key is invalid (too long)"));
|
||||
return Err(ImportKeyError::PublicKeyTooLong);
|
||||
}
|
||||
|
||||
// 11.
|
||||
if named_curve != pk_named_curve {
|
||||
return Err(data_error("curve mismatch"));
|
||||
return Err(ImportKeyError::CurveMismatch);
|
||||
}
|
||||
} else {
|
||||
return Err(data_error("Unsupported named curve"));
|
||||
return Err(ImportKeyError::UnsupportedNamedCurve);
|
||||
}
|
||||
|
||||
Ok(ImportKeyResult::Ec {
|
||||
|
@ -759,34 +791,38 @@ fn import_key_ec(
|
|||
KeyData::JwkPublicEc { .. } | KeyData::JwkPrivateEc { .. } => {
|
||||
import_key_ec_jwk(key_data, named_curve)
|
||||
}
|
||||
_ => Err(unsupported_format()),
|
||||
_ => Err(SharedError::UnsupportedFormat.into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn import_key_aes(key_data: KeyData) -> Result<ImportKeyResult, AnyError> {
|
||||
fn import_key_aes(
|
||||
key_data: KeyData,
|
||||
) -> Result<ImportKeyResult, ImportKeyError> {
|
||||
Ok(match key_data {
|
||||
KeyData::JwkSecret { k } => {
|
||||
let data = BASE64_URL_SAFE_FORGIVING
|
||||
.decode(k)
|
||||
.map_err(|_| data_error("invalid key data"))?;
|
||||
.map_err(|_| ImportKeyError::InvalidKeyData)?;
|
||||
ImportKeyResult::Hmac {
|
||||
raw_data: RustRawKeyData::Secret(data.into()),
|
||||
}
|
||||
}
|
||||
_ => return Err(unsupported_format()),
|
||||
_ => return Err(SharedError::UnsupportedFormat.into()),
|
||||
})
|
||||
}
|
||||
|
||||
fn import_key_hmac(key_data: KeyData) -> Result<ImportKeyResult, AnyError> {
|
||||
fn import_key_hmac(
|
||||
key_data: KeyData,
|
||||
) -> Result<ImportKeyResult, ImportKeyError> {
|
||||
Ok(match key_data {
|
||||
KeyData::JwkSecret { k } => {
|
||||
let data = BASE64_URL_SAFE_FORGIVING
|
||||
.decode(k)
|
||||
.map_err(|_| data_error("invalid key data"))?;
|
||||
.map_err(|_| ImportKeyError::InvalidKeyData)?;
|
||||
ImportKeyResult::Hmac {
|
||||
raw_data: RustRawKeyData::Secret(data.into()),
|
||||
}
|
||||
}
|
||||
_ => return Err(unsupported_format()),
|
||||
_ => return Err(SharedError::UnsupportedFormat.into()),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,10 +6,7 @@ use aes_kw::KekAes256;
|
|||
|
||||
use base64::prelude::BASE64_URL_SAFE_NO_PAD;
|
||||
use base64::Engine;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::not_supported;
|
||||
use deno_core::error::type_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op2;
|
||||
use deno_core::ToJsBuffer;
|
||||
|
||||
|
@ -17,7 +14,6 @@ use deno_core::unsync::spawn_blocking;
|
|||
use deno_core::JsBuffer;
|
||||
use deno_core::OpState;
|
||||
use serde::Deserialize;
|
||||
use shared::operation_error;
|
||||
|
||||
use p256::elliptic_curve::sec1::FromEncodedPoint;
|
||||
use p256::pkcs8::DecodePrivateKey;
|
||||
|
@ -67,15 +63,24 @@ mod x25519;
|
|||
mod x448;
|
||||
|
||||
pub use crate::decrypt::op_crypto_decrypt;
|
||||
pub use crate::decrypt::DecryptError;
|
||||
pub use crate::ed25519::Ed25519Error;
|
||||
pub use crate::encrypt::op_crypto_encrypt;
|
||||
pub use crate::encrypt::EncryptError;
|
||||
pub use crate::export_key::op_crypto_export_key;
|
||||
pub use crate::export_key::ExportKeyError;
|
||||
pub use crate::generate_key::op_crypto_generate_key;
|
||||
pub use crate::generate_key::GenerateKeyError;
|
||||
pub use crate::import_key::op_crypto_import_key;
|
||||
pub use crate::import_key::ImportKeyError;
|
||||
use crate::key::Algorithm;
|
||||
use crate::key::CryptoHash;
|
||||
use crate::key::CryptoNamedCurve;
|
||||
use crate::key::HkdfOutput;
|
||||
pub use crate::shared::SharedError;
|
||||
use crate::shared::V8RawKeyData;
|
||||
pub use crate::x25519::X25519Error;
|
||||
pub use crate::x448::X448Error;
|
||||
|
||||
deno_core::extension!(deno_crypto,
|
||||
deps = [ deno_webidl, deno_web ],
|
||||
|
@ -127,11 +132,63 @@ deno_core::extension!(deno_crypto,
|
|||
},
|
||||
);
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
General(#[from] SharedError),
|
||||
#[error(transparent)]
|
||||
JoinError(#[from] tokio::task::JoinError),
|
||||
#[error(transparent)]
|
||||
Der(#[from] rsa::pkcs1::der::Error),
|
||||
#[error("Missing argument hash")]
|
||||
MissingArgumentHash,
|
||||
#[error("Missing argument saltLength")]
|
||||
MissingArgumentSaltLength,
|
||||
#[error("unsupported algorithm")]
|
||||
UnsupportedAlgorithm,
|
||||
#[error(transparent)]
|
||||
KeyRejected(#[from] ring::error::KeyRejected),
|
||||
#[error(transparent)]
|
||||
RSA(#[from] rsa::Error),
|
||||
#[error(transparent)]
|
||||
Pkcs1(#[from] rsa::pkcs1::Error),
|
||||
#[error(transparent)]
|
||||
Unspecified(#[from] ring::error::Unspecified),
|
||||
#[error("Invalid key format")]
|
||||
InvalidKeyFormat,
|
||||
#[error(transparent)]
|
||||
P256Ecdsa(#[from] p256::ecdsa::Error),
|
||||
#[error("Unexpected error decoding private key")]
|
||||
DecodePrivateKey,
|
||||
#[error("Missing argument publicKey")]
|
||||
MissingArgumentPublicKey,
|
||||
#[error("Missing argument namedCurve")]
|
||||
MissingArgumentNamedCurve,
|
||||
#[error("Missing argument info")]
|
||||
MissingArgumentInfo,
|
||||
#[error("The length provided for HKDF is too large")]
|
||||
HKDFLengthTooLarge,
|
||||
#[error(transparent)]
|
||||
Base64Decode(#[from] base64::DecodeError),
|
||||
#[error("Data must be multiple of 8 bytes")]
|
||||
DataInvalidSize,
|
||||
#[error("Invalid key length")]
|
||||
InvalidKeyLength,
|
||||
#[error("encryption error")]
|
||||
EncryptionError,
|
||||
#[error("decryption error - integrity check failed")]
|
||||
DecryptionError,
|
||||
#[error("The ArrayBufferView's byte length ({0}) exceeds the number of bytes of entropy available via this API (65536)")]
|
||||
ArrayBufferViewLengthExceeded(usize),
|
||||
#[error(transparent)]
|
||||
Other(deno_core::error::AnyError),
|
||||
}
|
||||
|
||||
#[op2]
|
||||
#[serde]
|
||||
pub fn op_crypto_base64url_decode(
|
||||
#[string] data: String,
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, Error> {
|
||||
let data: Vec<u8> = BASE64_URL_SAFE_NO_PAD.decode(data)?;
|
||||
Ok(data.into())
|
||||
}
|
||||
|
@ -147,9 +204,9 @@ pub fn op_crypto_base64url_encode(#[buffer] data: JsBuffer) -> String {
|
|||
pub fn op_crypto_get_random_values(
|
||||
state: &mut OpState,
|
||||
#[buffer] out: &mut [u8],
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), Error> {
|
||||
if out.len() > 65536 {
|
||||
return Err(custom_error("DOMExceptionQuotaExceededError", format!("The ArrayBufferView's byte length ({}) exceeds the number of bytes of entropy available via this API (65536)", out.len())));
|
||||
return Err(Error::ArrayBufferViewLengthExceeded(out.len()));
|
||||
}
|
||||
|
||||
let maybe_seeded_rng = state.try_borrow_mut::<StdRng>();
|
||||
|
@ -201,7 +258,7 @@ pub struct SignArg {
|
|||
pub async fn op_crypto_sign_key(
|
||||
#[serde] args: SignArg,
|
||||
#[buffer] zero_copy: JsBuffer,
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, Error> {
|
||||
deno_core::unsync::spawn_blocking(move || {
|
||||
let data = &*zero_copy;
|
||||
let algorithm = args.algorithm;
|
||||
|
@ -210,10 +267,7 @@ pub async fn op_crypto_sign_key(
|
|||
Algorithm::RsassaPkcs1v15 => {
|
||||
use rsa::pkcs1v15::SigningKey;
|
||||
let private_key = RsaPrivateKey::from_pkcs1_der(&args.key.data)?;
|
||||
match args
|
||||
.hash
|
||||
.ok_or_else(|| type_error("Missing argument hash".to_string()))?
|
||||
{
|
||||
match args.hash.ok_or_else(|| Error::MissingArgumentHash)? {
|
||||
CryptoHash::Sha1 => {
|
||||
let signing_key = SigningKey::<Sha1>::new(private_key);
|
||||
signing_key.sign(data)
|
||||
|
@ -236,15 +290,13 @@ pub async fn op_crypto_sign_key(
|
|||
Algorithm::RsaPss => {
|
||||
let private_key = RsaPrivateKey::from_pkcs1_der(&args.key.data)?;
|
||||
|
||||
let salt_len = args.salt_length.ok_or_else(|| {
|
||||
type_error("Missing argument saltLength".to_string())
|
||||
})? as usize;
|
||||
let salt_len = args
|
||||
.salt_length
|
||||
.ok_or_else(|| Error::MissingArgumentSaltLength)?
|
||||
as usize;
|
||||
|
||||
let mut rng = OsRng;
|
||||
match args
|
||||
.hash
|
||||
.ok_or_else(|| type_error("Missing argument hash".to_string()))?
|
||||
{
|
||||
match args.hash.ok_or_else(|| Error::MissingArgumentHash)? {
|
||||
CryptoHash::Sha1 => {
|
||||
let signing_key = Pss::new_with_salt::<Sha1>(salt_len);
|
||||
let hashed = Sha1::digest(data);
|
||||
|
@ -269,8 +321,10 @@ pub async fn op_crypto_sign_key(
|
|||
.to_vec()
|
||||
}
|
||||
Algorithm::Ecdsa => {
|
||||
let curve: &EcdsaSigningAlgorithm =
|
||||
args.named_curve.ok_or_else(not_supported)?.into();
|
||||
let curve: &EcdsaSigningAlgorithm = args
|
||||
.named_curve
|
||||
.ok_or_else(|| Error::Other(not_supported()))?
|
||||
.into();
|
||||
|
||||
let rng = RingRand::SystemRandom::new();
|
||||
let key_pair = EcdsaKeyPair::from_pkcs8(curve, &args.key.data, &rng)?;
|
||||
|
@ -279,7 +333,7 @@ pub async fn op_crypto_sign_key(
|
|||
if let Some(hash) = args.hash {
|
||||
match hash {
|
||||
CryptoHash::Sha256 | CryptoHash::Sha384 => (),
|
||||
_ => return Err(type_error("Unsupported algorithm")),
|
||||
_ => return Err(Error::UnsupportedAlgorithm),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -289,14 +343,17 @@ pub async fn op_crypto_sign_key(
|
|||
signature.as_ref().to_vec()
|
||||
}
|
||||
Algorithm::Hmac => {
|
||||
let hash: HmacAlgorithm = args.hash.ok_or_else(not_supported)?.into();
|
||||
let hash: HmacAlgorithm = args
|
||||
.hash
|
||||
.ok_or_else(|| Error::Other(not_supported()))?
|
||||
.into();
|
||||
|
||||
let key = HmacKey::new(hash, &args.key.data);
|
||||
|
||||
let signature = ring::hmac::sign(&key, data);
|
||||
signature.as_ref().to_vec()
|
||||
}
|
||||
_ => return Err(type_error("Unsupported algorithm".to_string())),
|
||||
_ => return Err(Error::UnsupportedAlgorithm),
|
||||
};
|
||||
|
||||
Ok(signature.into())
|
||||
|
@ -319,7 +376,7 @@ pub struct VerifyArg {
|
|||
pub async fn op_crypto_verify_key(
|
||||
#[serde] args: VerifyArg,
|
||||
#[buffer] zero_copy: JsBuffer,
|
||||
) -> Result<bool, AnyError> {
|
||||
) -> Result<bool, Error> {
|
||||
deno_core::unsync::spawn_blocking(move || {
|
||||
let data = &*zero_copy;
|
||||
let algorithm = args.algorithm;
|
||||
|
@ -330,10 +387,7 @@ pub async fn op_crypto_verify_key(
|
|||
use rsa::pkcs1v15::VerifyingKey;
|
||||
let public_key = read_rsa_public_key(args.key)?;
|
||||
let signature: Signature = args.signature.as_ref().try_into()?;
|
||||
match args
|
||||
.hash
|
||||
.ok_or_else(|| type_error("Missing argument hash".to_string()))?
|
||||
{
|
||||
match args.hash.ok_or_else(|| Error::MissingArgumentHash)? {
|
||||
CryptoHash::Sha1 => {
|
||||
let verifying_key = VerifyingKey::<Sha1>::new(public_key);
|
||||
verifying_key.verify(data, &signature).is_ok()
|
||||
|
@ -356,14 +410,12 @@ pub async fn op_crypto_verify_key(
|
|||
let public_key = read_rsa_public_key(args.key)?;
|
||||
let signature = args.signature.as_ref();
|
||||
|
||||
let salt_len = args.salt_length.ok_or_else(|| {
|
||||
type_error("Missing argument saltLength".to_string())
|
||||
})? as usize;
|
||||
let salt_len = args
|
||||
.salt_length
|
||||
.ok_or_else(|| Error::MissingArgumentSaltLength)?
|
||||
as usize;
|
||||
|
||||
match args
|
||||
.hash
|
||||
.ok_or_else(|| type_error("Missing argument hash".to_string()))?
|
||||
{
|
||||
match args.hash.ok_or_else(|| Error::MissingArgumentHash)? {
|
||||
CryptoHash::Sha1 => {
|
||||
let pss = Pss::new_with_salt::<Sha1>(salt_len);
|
||||
let hashed = Sha1::digest(data);
|
||||
|
@ -387,15 +439,22 @@ pub async fn op_crypto_verify_key(
|
|||
}
|
||||
}
|
||||
Algorithm::Hmac => {
|
||||
let hash: HmacAlgorithm = args.hash.ok_or_else(not_supported)?.into();
|
||||
let hash: HmacAlgorithm = args
|
||||
.hash
|
||||
.ok_or_else(|| Error::Other(not_supported()))?
|
||||
.into();
|
||||
let key = HmacKey::new(hash, &args.key.data);
|
||||
ring::hmac::verify(&key, data, &args.signature).is_ok()
|
||||
}
|
||||
Algorithm::Ecdsa => {
|
||||
let signing_alg: &EcdsaSigningAlgorithm =
|
||||
args.named_curve.ok_or_else(not_supported)?.into();
|
||||
let verify_alg: &EcdsaVerificationAlgorithm =
|
||||
args.named_curve.ok_or_else(not_supported)?.into();
|
||||
let signing_alg: &EcdsaSigningAlgorithm = args
|
||||
.named_curve
|
||||
.ok_or_else(|| Error::Other(not_supported()))?
|
||||
.into();
|
||||
let verify_alg: &EcdsaVerificationAlgorithm = args
|
||||
.named_curve
|
||||
.ok_or_else(|| Error::Other(not_supported()))?
|
||||
.into();
|
||||
|
||||
let private_key;
|
||||
|
||||
|
@ -408,7 +467,7 @@ pub async fn op_crypto_verify_key(
|
|||
private_key.public_key().as_ref()
|
||||
}
|
||||
KeyType::Public => &*args.key.data,
|
||||
_ => return Err(type_error("Invalid Key format".to_string())),
|
||||
_ => return Err(Error::InvalidKeyFormat),
|
||||
};
|
||||
|
||||
let public_key =
|
||||
|
@ -416,7 +475,7 @@ pub async fn op_crypto_verify_key(
|
|||
|
||||
public_key.verify(data, &args.signature).is_ok()
|
||||
}
|
||||
_ => return Err(type_error("Unsupported algorithm".to_string())),
|
||||
_ => return Err(Error::UnsupportedAlgorithm),
|
||||
};
|
||||
|
||||
Ok(verification)
|
||||
|
@ -444,70 +503,68 @@ pub struct DeriveKeyArg {
|
|||
pub async fn op_crypto_derive_bits(
|
||||
#[serde] args: DeriveKeyArg,
|
||||
#[buffer] zero_copy: Option<JsBuffer>,
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, Error> {
|
||||
deno_core::unsync::spawn_blocking(move || {
|
||||
let algorithm = args.algorithm;
|
||||
match algorithm {
|
||||
Algorithm::Pbkdf2 => {
|
||||
let zero_copy = zero_copy.ok_or_else(not_supported)?;
|
||||
let zero_copy =
|
||||
zero_copy.ok_or_else(|| Error::Other(not_supported()))?;
|
||||
let salt = &*zero_copy;
|
||||
// The caller must validate these cases.
|
||||
assert!(args.length > 0);
|
||||
assert!(args.length % 8 == 0);
|
||||
|
||||
let algorithm = match args.hash.ok_or_else(not_supported)? {
|
||||
CryptoHash::Sha1 => pbkdf2::PBKDF2_HMAC_SHA1,
|
||||
CryptoHash::Sha256 => pbkdf2::PBKDF2_HMAC_SHA256,
|
||||
CryptoHash::Sha384 => pbkdf2::PBKDF2_HMAC_SHA384,
|
||||
CryptoHash::Sha512 => pbkdf2::PBKDF2_HMAC_SHA512,
|
||||
};
|
||||
let algorithm =
|
||||
match args.hash.ok_or_else(|| Error::Other(not_supported()))? {
|
||||
CryptoHash::Sha1 => pbkdf2::PBKDF2_HMAC_SHA1,
|
||||
CryptoHash::Sha256 => pbkdf2::PBKDF2_HMAC_SHA256,
|
||||
CryptoHash::Sha384 => pbkdf2::PBKDF2_HMAC_SHA384,
|
||||
CryptoHash::Sha512 => pbkdf2::PBKDF2_HMAC_SHA512,
|
||||
};
|
||||
|
||||
// This will never panic. We have already checked length earlier.
|
||||
let iterations =
|
||||
NonZeroU32::new(args.iterations.ok_or_else(not_supported)?).unwrap();
|
||||
let iterations = NonZeroU32::new(
|
||||
args
|
||||
.iterations
|
||||
.ok_or_else(|| Error::Other(not_supported()))?,
|
||||
)
|
||||
.unwrap();
|
||||
let secret = args.key.data;
|
||||
let mut out = vec![0; args.length / 8];
|
||||
pbkdf2::derive(algorithm, iterations, salt, &secret, &mut out);
|
||||
Ok(out.into())
|
||||
}
|
||||
Algorithm::Ecdh => {
|
||||
let named_curve = args.named_curve.ok_or_else(|| {
|
||||
type_error("Missing argument namedCurve".to_string())
|
||||
})?;
|
||||
let named_curve = args
|
||||
.named_curve
|
||||
.ok_or_else(|| Error::MissingArgumentNamedCurve)?;
|
||||
|
||||
let public_key = args
|
||||
.public_key
|
||||
.ok_or_else(|| type_error("Missing argument publicKey"))?;
|
||||
.ok_or_else(|| Error::MissingArgumentPublicKey)?;
|
||||
|
||||
match named_curve {
|
||||
CryptoNamedCurve::P256 => {
|
||||
let secret_key = p256::SecretKey::from_pkcs8_der(&args.key.data)
|
||||
.map_err(|_| {
|
||||
type_error("Unexpected error decoding private key")
|
||||
})?;
|
||||
.map_err(|_| Error::DecodePrivateKey)?;
|
||||
|
||||
let public_key = match public_key.r#type {
|
||||
KeyType::Private => {
|
||||
p256::SecretKey::from_pkcs8_der(&public_key.data)
|
||||
.map_err(|_| {
|
||||
type_error("Unexpected error decoding private key")
|
||||
})?
|
||||
.map_err(|_| Error::DecodePrivateKey)?
|
||||
.public_key()
|
||||
}
|
||||
KeyType::Public => {
|
||||
let point = p256::EncodedPoint::from_bytes(public_key.data)
|
||||
.map_err(|_| {
|
||||
type_error("Unexpected error decoding private key")
|
||||
})?;
|
||||
.map_err(|_| Error::DecodePrivateKey)?;
|
||||
|
||||
let pk = p256::PublicKey::from_encoded_point(&point);
|
||||
// pk is a constant time Option.
|
||||
if pk.is_some().into() {
|
||||
pk.unwrap()
|
||||
} else {
|
||||
return Err(type_error(
|
||||
"Unexpected error decoding private key",
|
||||
));
|
||||
return Err(Error::DecodePrivateKey);
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
@ -523,32 +580,24 @@ pub async fn op_crypto_derive_bits(
|
|||
}
|
||||
CryptoNamedCurve::P384 => {
|
||||
let secret_key = p384::SecretKey::from_pkcs8_der(&args.key.data)
|
||||
.map_err(|_| {
|
||||
type_error("Unexpected error decoding private key")
|
||||
})?;
|
||||
.map_err(|_| Error::DecodePrivateKey)?;
|
||||
|
||||
let public_key = match public_key.r#type {
|
||||
KeyType::Private => {
|
||||
p384::SecretKey::from_pkcs8_der(&public_key.data)
|
||||
.map_err(|_| {
|
||||
type_error("Unexpected error decoding private key")
|
||||
})?
|
||||
.map_err(|_| Error::DecodePrivateKey)?
|
||||
.public_key()
|
||||
}
|
||||
KeyType::Public => {
|
||||
let point = p384::EncodedPoint::from_bytes(public_key.data)
|
||||
.map_err(|_| {
|
||||
type_error("Unexpected error decoding private key")
|
||||
})?;
|
||||
.map_err(|_| Error::DecodePrivateKey)?;
|
||||
|
||||
let pk = p384::PublicKey::from_encoded_point(&point);
|
||||
// pk is a constant time Option.
|
||||
if pk.is_some().into() {
|
||||
pk.unwrap()
|
||||
} else {
|
||||
return Err(type_error(
|
||||
"Unexpected error decoding private key",
|
||||
));
|
||||
return Err(Error::DecodePrivateKey);
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
@ -565,18 +614,18 @@ pub async fn op_crypto_derive_bits(
|
|||
}
|
||||
}
|
||||
Algorithm::Hkdf => {
|
||||
let zero_copy = zero_copy.ok_or_else(not_supported)?;
|
||||
let zero_copy =
|
||||
zero_copy.ok_or_else(|| Error::Other(not_supported()))?;
|
||||
let salt = &*zero_copy;
|
||||
let algorithm = match args.hash.ok_or_else(not_supported)? {
|
||||
CryptoHash::Sha1 => hkdf::HKDF_SHA1_FOR_LEGACY_USE_ONLY,
|
||||
CryptoHash::Sha256 => hkdf::HKDF_SHA256,
|
||||
CryptoHash::Sha384 => hkdf::HKDF_SHA384,
|
||||
CryptoHash::Sha512 => hkdf::HKDF_SHA512,
|
||||
};
|
||||
let algorithm =
|
||||
match args.hash.ok_or_else(|| Error::Other(not_supported()))? {
|
||||
CryptoHash::Sha1 => hkdf::HKDF_SHA1_FOR_LEGACY_USE_ONLY,
|
||||
CryptoHash::Sha256 => hkdf::HKDF_SHA256,
|
||||
CryptoHash::Sha384 => hkdf::HKDF_SHA384,
|
||||
CryptoHash::Sha512 => hkdf::HKDF_SHA512,
|
||||
};
|
||||
|
||||
let info = args
|
||||
.info
|
||||
.ok_or_else(|| type_error("Missing argument info".to_string()))?;
|
||||
let info = args.info.ok_or_else(|| Error::MissingArgumentInfo)?;
|
||||
// IKM
|
||||
let secret = args.key.data;
|
||||
// L
|
||||
|
@ -585,23 +634,20 @@ pub async fn op_crypto_derive_bits(
|
|||
let salt = hkdf::Salt::new(algorithm, salt);
|
||||
let prk = salt.extract(&secret);
|
||||
let info = &[&*info];
|
||||
let okm = prk.expand(info, HkdfOutput(length)).map_err(|_e| {
|
||||
custom_error(
|
||||
"DOMExceptionOperationError",
|
||||
"The length provided for HKDF is too large",
|
||||
)
|
||||
})?;
|
||||
let okm = prk
|
||||
.expand(info, HkdfOutput(length))
|
||||
.map_err(|_e| Error::HKDFLengthTooLarge)?;
|
||||
let mut r = vec![0u8; length];
|
||||
okm.fill(&mut r)?;
|
||||
Ok(r.into())
|
||||
}
|
||||
_ => Err(type_error("Unsupported algorithm".to_string())),
|
||||
_ => Err(Error::UnsupportedAlgorithm),
|
||||
}
|
||||
})
|
||||
.await?
|
||||
}
|
||||
|
||||
fn read_rsa_public_key(key_data: KeyData) -> Result<RsaPublicKey, AnyError> {
|
||||
fn read_rsa_public_key(key_data: KeyData) -> Result<RsaPublicKey, Error> {
|
||||
let public_key = match key_data.r#type {
|
||||
KeyType::Private => {
|
||||
RsaPrivateKey::from_pkcs1_der(&key_data.data)?.to_public_key()
|
||||
|
@ -614,7 +660,7 @@ fn read_rsa_public_key(key_data: KeyData) -> Result<RsaPublicKey, AnyError> {
|
|||
|
||||
#[op2]
|
||||
#[string]
|
||||
pub fn op_crypto_random_uuid(state: &mut OpState) -> Result<String, AnyError> {
|
||||
pub fn op_crypto_random_uuid(state: &mut OpState) -> Result<String, Error> {
|
||||
let maybe_seeded_rng = state.try_borrow_mut::<StdRng>();
|
||||
let uuid = if let Some(seeded_rng) = maybe_seeded_rng {
|
||||
let mut bytes = [0u8; 16];
|
||||
|
@ -635,7 +681,7 @@ pub fn op_crypto_random_uuid(state: &mut OpState) -> Result<String, AnyError> {
|
|||
pub async fn op_crypto_subtle_digest(
|
||||
#[serde] algorithm: CryptoHash,
|
||||
#[buffer] data: JsBuffer,
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, Error> {
|
||||
let output = spawn_blocking(move || {
|
||||
digest::digest(algorithm.into(), &data)
|
||||
.as_ref()
|
||||
|
@ -659,7 +705,7 @@ pub struct WrapUnwrapKeyArg {
|
|||
pub fn op_crypto_wrap_key(
|
||||
#[serde] args: WrapUnwrapKeyArg,
|
||||
#[buffer] data: JsBuffer,
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, Error> {
|
||||
let algorithm = args.algorithm;
|
||||
|
||||
match algorithm {
|
||||
|
@ -667,20 +713,20 @@ pub fn op_crypto_wrap_key(
|
|||
let key = args.key.as_secret_key()?;
|
||||
|
||||
if data.len() % 8 != 0 {
|
||||
return Err(type_error("Data must be multiple of 8 bytes"));
|
||||
return Err(Error::DataInvalidSize);
|
||||
}
|
||||
|
||||
let wrapped_key = match key.len() {
|
||||
16 => KekAes128::new(key.into()).wrap_vec(&data),
|
||||
24 => KekAes192::new(key.into()).wrap_vec(&data),
|
||||
32 => KekAes256::new(key.into()).wrap_vec(&data),
|
||||
_ => return Err(type_error("Invalid key length")),
|
||||
_ => return Err(Error::InvalidKeyLength),
|
||||
}
|
||||
.map_err(|_| operation_error("encryption error"))?;
|
||||
.map_err(|_| Error::EncryptionError)?;
|
||||
|
||||
Ok(wrapped_key.into())
|
||||
}
|
||||
_ => Err(type_error("Unsupported algorithm")),
|
||||
_ => Err(Error::UnsupportedAlgorithm),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -689,29 +735,27 @@ pub fn op_crypto_wrap_key(
|
|||
pub fn op_crypto_unwrap_key(
|
||||
#[serde] args: WrapUnwrapKeyArg,
|
||||
#[buffer] data: JsBuffer,
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, Error> {
|
||||
let algorithm = args.algorithm;
|
||||
match algorithm {
|
||||
Algorithm::AesKw => {
|
||||
let key = args.key.as_secret_key()?;
|
||||
|
||||
if data.len() % 8 != 0 {
|
||||
return Err(type_error("Data must be multiple of 8 bytes"));
|
||||
return Err(Error::DataInvalidSize);
|
||||
}
|
||||
|
||||
let unwrapped_key = match key.len() {
|
||||
16 => KekAes128::new(key.into()).unwrap_vec(&data),
|
||||
24 => KekAes192::new(key.into()).unwrap_vec(&data),
|
||||
32 => KekAes256::new(key.into()).unwrap_vec(&data),
|
||||
_ => return Err(type_error("Invalid key length")),
|
||||
_ => return Err(Error::InvalidKeyLength),
|
||||
}
|
||||
.map_err(|_| {
|
||||
operation_error("decryption error - integrity check failed")
|
||||
})?;
|
||||
.map_err(|_| Error::DecryptionError)?;
|
||||
|
||||
Ok(unwrapped_key.into())
|
||||
}
|
||||
_ => Err(type_error("Unsupported algorithm")),
|
||||
_ => Err(Error::UnsupportedAlgorithm),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::type_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::JsBuffer;
|
||||
use deno_core::ToJsBuffer;
|
||||
use elliptic_curve::sec1::ToEncodedPoint;
|
||||
|
@ -63,47 +60,73 @@ pub enum RustRawKeyData {
|
|||
Public(ToJsBuffer),
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum SharedError {
|
||||
#[error("expected valid private key")]
|
||||
ExpectedValidPrivateKey,
|
||||
#[error("expected valid public key")]
|
||||
ExpectedValidPublicKey,
|
||||
#[error("expected valid private EC key")]
|
||||
ExpectedValidPrivateECKey,
|
||||
#[error("expected valid public EC key")]
|
||||
ExpectedValidPublicECKey,
|
||||
#[error("expected private key")]
|
||||
ExpectedPrivateKey,
|
||||
#[error("expected public key")]
|
||||
ExpectedPublicKey,
|
||||
#[error("expected secret key")]
|
||||
ExpectedSecretKey,
|
||||
#[error("failed to decode private key")]
|
||||
FailedDecodePrivateKey,
|
||||
#[error("failed to decode public key")]
|
||||
FailedDecodePublicKey,
|
||||
#[error("unsupported format")]
|
||||
UnsupportedFormat,
|
||||
}
|
||||
|
||||
impl V8RawKeyData {
|
||||
pub fn as_rsa_public_key(&self) -> Result<Cow<'_, [u8]>, AnyError> {
|
||||
pub fn as_rsa_public_key(&self) -> Result<Cow<'_, [u8]>, SharedError> {
|
||||
match self {
|
||||
V8RawKeyData::Public(data) => Ok(Cow::Borrowed(data)),
|
||||
V8RawKeyData::Private(data) => {
|
||||
let private_key = RsaPrivateKey::from_pkcs1_der(data)
|
||||
.map_err(|_| type_error("expected valid private key"))?;
|
||||
.map_err(|_| SharedError::ExpectedValidPrivateKey)?;
|
||||
|
||||
let public_key_doc = private_key
|
||||
.to_public_key()
|
||||
.to_pkcs1_der()
|
||||
.map_err(|_| type_error("expected valid public key"))?;
|
||||
.map_err(|_| SharedError::ExpectedValidPublicKey)?;
|
||||
|
||||
Ok(Cow::Owned(public_key_doc.as_bytes().into()))
|
||||
}
|
||||
_ => Err(type_error("expected public key")),
|
||||
_ => Err(SharedError::ExpectedPublicKey),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_rsa_private_key(&self) -> Result<&[u8], AnyError> {
|
||||
pub fn as_rsa_private_key(&self) -> Result<&[u8], SharedError> {
|
||||
match self {
|
||||
V8RawKeyData::Private(data) => Ok(data),
|
||||
_ => Err(type_error("expected private key")),
|
||||
_ => Err(SharedError::ExpectedPrivateKey),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_secret_key(&self) -> Result<&[u8], AnyError> {
|
||||
pub fn as_secret_key(&self) -> Result<&[u8], SharedError> {
|
||||
match self {
|
||||
V8RawKeyData::Secret(data) => Ok(data),
|
||||
_ => Err(type_error("expected secret key")),
|
||||
_ => Err(SharedError::ExpectedSecretKey),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ec_public_key_p256(&self) -> Result<p256::EncodedPoint, AnyError> {
|
||||
pub fn as_ec_public_key_p256(
|
||||
&self,
|
||||
) -> Result<p256::EncodedPoint, SharedError> {
|
||||
match self {
|
||||
V8RawKeyData::Public(data) => p256::PublicKey::from_sec1_bytes(data)
|
||||
.map(|p| p.to_encoded_point(false))
|
||||
.map_err(|_| type_error("expected valid public EC key")),
|
||||
.map_err(|_| SharedError::ExpectedValidPublicECKey),
|
||||
V8RawKeyData::Private(data) => {
|
||||
let signing_key = p256::SecretKey::from_pkcs8_der(data)
|
||||
.map_err(|_| type_error("expected valid private EC key"))?;
|
||||
.map_err(|_| SharedError::ExpectedValidPrivateECKey)?;
|
||||
Ok(signing_key.public_key().to_encoded_point(false))
|
||||
}
|
||||
// Should never reach here.
|
||||
|
@ -111,14 +134,16 @@ impl V8RawKeyData {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn as_ec_public_key_p384(&self) -> Result<p384::EncodedPoint, AnyError> {
|
||||
pub fn as_ec_public_key_p384(
|
||||
&self,
|
||||
) -> Result<p384::EncodedPoint, SharedError> {
|
||||
match self {
|
||||
V8RawKeyData::Public(data) => p384::PublicKey::from_sec1_bytes(data)
|
||||
.map(|p| p.to_encoded_point(false))
|
||||
.map_err(|_| type_error("expected valid public EC key")),
|
||||
.map_err(|_| SharedError::ExpectedValidPublicECKey),
|
||||
V8RawKeyData::Private(data) => {
|
||||
let signing_key = p384::SecretKey::from_pkcs8_der(data)
|
||||
.map_err(|_| type_error("expected valid private EC key"))?;
|
||||
.map_err(|_| SharedError::ExpectedValidPrivateECKey)?;
|
||||
Ok(signing_key.public_key().to_encoded_point(false))
|
||||
}
|
||||
// Should never reach here.
|
||||
|
@ -126,16 +151,18 @@ impl V8RawKeyData {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn as_ec_public_key_p521(&self) -> Result<p521::EncodedPoint, AnyError> {
|
||||
pub fn as_ec_public_key_p521(
|
||||
&self,
|
||||
) -> Result<p521::EncodedPoint, SharedError> {
|
||||
match self {
|
||||
V8RawKeyData::Public(data) => {
|
||||
// public_key is a serialized EncodedPoint
|
||||
p521::EncodedPoint::from_bytes(data)
|
||||
.map_err(|_| type_error("expected valid public EC key"))
|
||||
.map_err(|_| SharedError::ExpectedValidPublicECKey)
|
||||
}
|
||||
V8RawKeyData::Private(data) => {
|
||||
let signing_key = p521::SecretKey::from_pkcs8_der(data)
|
||||
.map_err(|_| type_error("expected valid private EC key"))?;
|
||||
.map_err(|_| SharedError::ExpectedValidPrivateECKey)?;
|
||||
Ok(signing_key.public_key().to_encoded_point(false))
|
||||
}
|
||||
// Should never reach here.
|
||||
|
@ -143,26 +170,10 @@ impl V8RawKeyData {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn as_ec_private_key(&self) -> Result<&[u8], AnyError> {
|
||||
pub fn as_ec_private_key(&self) -> Result<&[u8], SharedError> {
|
||||
match self {
|
||||
V8RawKeyData::Private(data) => Ok(data),
|
||||
_ => Err(type_error("expected private key")),
|
||||
_ => Err(SharedError::ExpectedPrivateKey),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data_error(msg: impl Into<Cow<'static, str>>) -> AnyError {
|
||||
custom_error("DOMExceptionDataError", msg)
|
||||
}
|
||||
|
||||
pub fn not_supported_error(msg: impl Into<Cow<'static, str>>) -> AnyError {
|
||||
custom_error("DOMExceptionNotSupportedError", msg)
|
||||
}
|
||||
|
||||
pub fn operation_error(msg: impl Into<Cow<'static, str>>) -> AnyError {
|
||||
custom_error("DOMExceptionOperationError", msg)
|
||||
}
|
||||
|
||||
pub fn unsupported_format() -> AnyError {
|
||||
not_supported_error("unsupported format")
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op2;
|
||||
use deno_core::ToJsBuffer;
|
||||
use elliptic_curve::pkcs8::PrivateKeyInfo;
|
||||
|
@ -13,6 +11,14 @@ use spki::der::asn1::BitString;
|
|||
use spki::der::Decode;
|
||||
use spki::der::Encode;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum X25519Error {
|
||||
#[error("Failed to export key")]
|
||||
FailedExport,
|
||||
#[error(transparent)]
|
||||
Der(#[from] spki::der::Error),
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
pub fn op_crypto_generate_x25519_keypair(
|
||||
#[buffer] pkey: &mut [u8],
|
||||
|
@ -113,7 +119,7 @@ pub fn op_crypto_import_pkcs8_x25519(
|
|||
#[serde]
|
||||
pub fn op_crypto_export_spki_x25519(
|
||||
#[buffer] pubkey: &[u8],
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, X25519Error> {
|
||||
let key_info = spki::SubjectPublicKeyInfo {
|
||||
algorithm: spki::AlgorithmIdentifierRef {
|
||||
// id-X25519
|
||||
|
@ -125,9 +131,7 @@ pub fn op_crypto_export_spki_x25519(
|
|||
Ok(
|
||||
key_info
|
||||
.to_der()
|
||||
.map_err(|_| {
|
||||
custom_error("DOMExceptionOperationError", "Failed to export key")
|
||||
})?
|
||||
.map_err(|_| X25519Error::FailedExport)?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
@ -136,7 +140,7 @@ pub fn op_crypto_export_spki_x25519(
|
|||
#[serde]
|
||||
pub fn op_crypto_export_pkcs8_x25519(
|
||||
#[buffer] pkey: &[u8],
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, X25519Error> {
|
||||
use rsa::pkcs1::der::Encode;
|
||||
|
||||
// This should probably use OneAsymmetricKey instead
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::AnyError;
|
||||
|
||||
use deno_core::op2;
|
||||
use deno_core::ToJsBuffer;
|
||||
use ed448_goldilocks::curve::MontgomeryPoint;
|
||||
|
@ -13,6 +12,14 @@ use spki::der::asn1::BitString;
|
|||
use spki::der::Decode;
|
||||
use spki::der::Encode;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum X448Error {
|
||||
#[error("Failed to export key")]
|
||||
FailedExport,
|
||||
#[error(transparent)]
|
||||
Der(#[from] spki::der::Error),
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
pub fn op_crypto_generate_x448_keypair(
|
||||
#[buffer] pkey: &mut [u8],
|
||||
|
@ -56,7 +63,7 @@ const X448_OID: const_oid::ObjectIdentifier =
|
|||
#[serde]
|
||||
pub fn op_crypto_export_spki_x448(
|
||||
#[buffer] pubkey: &[u8],
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, X448Error> {
|
||||
let key_info = spki::SubjectPublicKeyInfo {
|
||||
algorithm: spki::AlgorithmIdentifierRef {
|
||||
oid: X448_OID,
|
||||
|
@ -67,9 +74,7 @@ pub fn op_crypto_export_spki_x448(
|
|||
Ok(
|
||||
key_info
|
||||
.to_der()
|
||||
.map_err(|_| {
|
||||
custom_error("DOMExceptionOperationError", "Failed to export key")
|
||||
})?
|
||||
.map_err(|_| X448Error::FailedExport)?
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
@ -78,7 +83,7 @@ pub fn op_crypto_export_spki_x448(
|
|||
#[serde]
|
||||
pub fn op_crypto_export_pkcs8_x448(
|
||||
#[buffer] pkey: &[u8],
|
||||
) -> Result<ToJsBuffer, AnyError> {
|
||||
) -> Result<ToJsBuffer, X448Error> {
|
||||
use rsa::pkcs1::der::Encode;
|
||||
|
||||
let pk_info = rsa::pkcs8::PrivateKeyInfo {
|
||||
|
|
|
@ -17,6 +17,11 @@ use deno_core::serde_json;
|
|||
use deno_core::url;
|
||||
use deno_core::ModuleResolutionError;
|
||||
use deno_cron::CronError;
|
||||
use deno_crypto::DecryptError;
|
||||
use deno_crypto::EncryptError;
|
||||
use deno_crypto::ExportKeyError;
|
||||
use deno_crypto::GenerateKeyError;
|
||||
use deno_crypto::ImportKeyError;
|
||||
use deno_ffi::CallError;
|
||||
use deno_ffi::CallbackError;
|
||||
use deno_ffi::DlfcnError;
|
||||
|
@ -179,6 +184,165 @@ pub fn get_nix_error_class(error: &nix::Error) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_crypto_decrypt_error_class(e: &DecryptError) -> &'static str {
|
||||
match e {
|
||||
DecryptError::General(e) => get_crypto_shared_error_class(e),
|
||||
DecryptError::Pkcs1(_) => "Error",
|
||||
DecryptError::Failed => "DOMExceptionOperationError",
|
||||
DecryptError::InvalidLength => "TypeError",
|
||||
DecryptError::InvalidCounterLength => "TypeError",
|
||||
DecryptError::InvalidTagLength => "TypeError",
|
||||
DecryptError::InvalidKeyOrIv => "DOMExceptionOperationError",
|
||||
DecryptError::TooMuchData => "DOMExceptionOperationError",
|
||||
DecryptError::InvalidIvLength => "TypeError",
|
||||
DecryptError::Rsa(_) => "DOMExceptionOperationError",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_crypto_encrypt_error_class(e: &EncryptError) -> &'static str {
|
||||
match e {
|
||||
EncryptError::General(e) => get_crypto_shared_error_class(e),
|
||||
EncryptError::InvalidKeyOrIv => "DOMExceptionOperationError",
|
||||
EncryptError::Failed => "DOMExceptionOperationError",
|
||||
EncryptError::InvalidLength => "TypeError",
|
||||
EncryptError::InvalidIvLength => "TypeError",
|
||||
EncryptError::InvalidCounterLength => "TypeError",
|
||||
EncryptError::TooMuchData => "DOMExceptionOperationError",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_crypto_shared_error_class(e: &deno_crypto::SharedError) -> &'static str {
|
||||
match e {
|
||||
deno_crypto::SharedError::ExpectedValidPrivateKey => "TypeError",
|
||||
deno_crypto::SharedError::ExpectedValidPublicKey => "TypeError",
|
||||
deno_crypto::SharedError::ExpectedValidPrivateECKey => "TypeError",
|
||||
deno_crypto::SharedError::ExpectedValidPublicECKey => "TypeError",
|
||||
deno_crypto::SharedError::ExpectedPrivateKey => "TypeError",
|
||||
deno_crypto::SharedError::ExpectedPublicKey => "TypeError",
|
||||
deno_crypto::SharedError::ExpectedSecretKey => "TypeError",
|
||||
deno_crypto::SharedError::FailedDecodePrivateKey => {
|
||||
"DOMExceptionOperationError"
|
||||
}
|
||||
deno_crypto::SharedError::FailedDecodePublicKey => {
|
||||
"DOMExceptionOperationError"
|
||||
}
|
||||
deno_crypto::SharedError::UnsupportedFormat => {
|
||||
"DOMExceptionNotSupportedError"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_crypto_ed25519_error_class(
|
||||
e: &deno_crypto::Ed25519Error,
|
||||
) -> &'static str {
|
||||
match e {
|
||||
deno_crypto::Ed25519Error::FailedExport => "DOMExceptionOperationError",
|
||||
deno_crypto::Ed25519Error::Der(_) => "Error",
|
||||
deno_crypto::Ed25519Error::KeyRejected(_) => "Error",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_crypto_export_key_error_class(e: &ExportKeyError) -> &'static str {
|
||||
match e {
|
||||
ExportKeyError::General(e) => get_crypto_shared_error_class(e),
|
||||
ExportKeyError::Der(_) => "Error",
|
||||
ExportKeyError::UnsupportedNamedCurve => "DOMExceptionNotSupportedError",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_crypto_generate_key_error_class(e: &GenerateKeyError) -> &'static str {
|
||||
match e {
|
||||
GenerateKeyError::General(e) => get_crypto_shared_error_class(e),
|
||||
GenerateKeyError::BadPublicExponent => "DOMExceptionOperationError",
|
||||
GenerateKeyError::InvalidHMACKeyLength => "DOMExceptionOperationError",
|
||||
GenerateKeyError::FailedRSAKeySerialization => "DOMExceptionOperationError",
|
||||
GenerateKeyError::InvalidAESKeyLength => "DOMExceptionOperationError",
|
||||
GenerateKeyError::FailedRSAKeyGeneration => "DOMExceptionOperationError",
|
||||
GenerateKeyError::FailedECKeyGeneration => "DOMExceptionOperationError",
|
||||
GenerateKeyError::FailedKeyGeneration => "DOMExceptionOperationError",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_crypto_import_key_error_class(e: &ImportKeyError) -> &'static str {
|
||||
match e {
|
||||
ImportKeyError::General(e) => get_crypto_shared_error_class(e),
|
||||
ImportKeyError::InvalidModulus => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidPublicExponent => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidPrivateExponent => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidFirstPrimeFactor => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidSecondPrimeFactor => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidFirstCRTExponent => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidSecondCRTExponent => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidCRTCoefficient => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidB64Coordinate => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidRSAPublicKey => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidRSAPrivateKey => "DOMExceptionDataError",
|
||||
ImportKeyError::UnsupportedAlgorithm => "DOMExceptionDataError",
|
||||
ImportKeyError::PublicKeyTooLong => "DOMExceptionDataError",
|
||||
ImportKeyError::PrivateKeyTooLong => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidP256ECPoint => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidP384ECPoint => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidP521ECPoint => "DOMExceptionDataError",
|
||||
ImportKeyError::UnsupportedNamedCurve => "DOMExceptionDataError",
|
||||
ImportKeyError::CurveMismatch => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidKeyData => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidJWKPrivateKey => "DOMExceptionDataError",
|
||||
ImportKeyError::EllipticCurve(_) => "DOMExceptionDataError",
|
||||
ImportKeyError::ExpectedValidPkcs8Data => "DOMExceptionDataError",
|
||||
ImportKeyError::MalformedParameters => "DOMExceptionDataError",
|
||||
ImportKeyError::Spki(_) => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidP256ECSPKIData => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidP384ECSPKIData => "DOMExceptionDataError",
|
||||
ImportKeyError::InvalidP521ECSPKIData => "DOMExceptionDataError",
|
||||
ImportKeyError::Der(_) => "DOMExceptionDataError",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_crypto_x448_error_class(e: &deno_crypto::X448Error) -> &'static str {
|
||||
match e {
|
||||
deno_crypto::X448Error::FailedExport => "DOMExceptionOperationError",
|
||||
deno_crypto::X448Error::Der(_) => "Error",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_crypto_x25519_error_class(e: &deno_crypto::X25519Error) -> &'static str {
|
||||
match e {
|
||||
deno_crypto::X25519Error::FailedExport => "DOMExceptionOperationError",
|
||||
deno_crypto::X25519Error::Der(_) => "Error",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_crypto_error_class(e: &deno_crypto::Error) -> &'static str {
|
||||
match e {
|
||||
deno_crypto::Error::Der(_) => "Error",
|
||||
deno_crypto::Error::JoinError(_) => "Error",
|
||||
deno_crypto::Error::MissingArgumentHash => "TypeError",
|
||||
deno_crypto::Error::MissingArgumentSaltLength => "TypeError",
|
||||
deno_crypto::Error::Other(e) => get_error_class_name(e).unwrap_or("Error"),
|
||||
deno_crypto::Error::UnsupportedAlgorithm => "TypeError",
|
||||
deno_crypto::Error::KeyRejected(_) => "Error",
|
||||
deno_crypto::Error::RSA(_) => "Error",
|
||||
deno_crypto::Error::Pkcs1(_) => "Error",
|
||||
deno_crypto::Error::Unspecified(_) => "Error",
|
||||
deno_crypto::Error::InvalidKeyFormat => "TypeError",
|
||||
deno_crypto::Error::MissingArgumentPublicKey => "TypeError",
|
||||
deno_crypto::Error::P256Ecdsa(_) => "Error",
|
||||
deno_crypto::Error::DecodePrivateKey => "TypeError",
|
||||
deno_crypto::Error::MissingArgumentNamedCurve => "TypeError",
|
||||
deno_crypto::Error::MissingArgumentInfo => "TypeError",
|
||||
deno_crypto::Error::HKDFLengthTooLarge => "DOMExceptionOperationError",
|
||||
deno_crypto::Error::General(e) => get_crypto_shared_error_class(e),
|
||||
deno_crypto::Error::Base64Decode(_) => "Error",
|
||||
deno_crypto::Error::DataInvalidSize => "TypeError",
|
||||
deno_crypto::Error::InvalidKeyLength => "TypeError",
|
||||
deno_crypto::Error::EncryptionError => "DOMExceptionOperationError",
|
||||
deno_crypto::Error::DecryptionError => "DOMExceptionOperationError",
|
||||
deno_crypto::Error::ArrayBufferViewLengthExceeded(_) => {
|
||||
"DOMExceptionQuotaExceededError"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_napi_error_class(e: &NApiError) -> &'static str {
|
||||
match e {
|
||||
NApiError::InvalidPath
|
||||
|
@ -571,6 +735,46 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
|
|||
e.downcast_ref::<BroadcastChannelError>()
|
||||
.map(get_broadcast_channel_error)
|
||||
})
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<DecryptError>()
|
||||
.map(get_crypto_decrypt_error_class)
|
||||
})
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<EncryptError>()
|
||||
.map(get_crypto_encrypt_error_class)
|
||||
})
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<deno_crypto::SharedError>()
|
||||
.map(get_crypto_shared_error_class)
|
||||
})
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<deno_crypto::Ed25519Error>()
|
||||
.map(get_crypto_ed25519_error_class)
|
||||
})
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<ExportKeyError>()
|
||||
.map(get_crypto_export_key_error_class)
|
||||
})
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<GenerateKeyError>()
|
||||
.map(get_crypto_generate_key_error_class)
|
||||
})
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<ImportKeyError>()
|
||||
.map(get_crypto_import_key_error_class)
|
||||
})
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<deno_crypto::X448Error>()
|
||||
.map(get_crypto_x448_error_class)
|
||||
})
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<deno_crypto::X25519Error>()
|
||||
.map(get_crypto_x25519_error_class)
|
||||
})
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<deno_crypto::Error>()
|
||||
.map(get_crypto_error_class)
|
||||
})
|
||||
.or_else(|| {
|
||||
e.downcast_ref::<WebStorageError>()
|
||||
.map(get_webstorage_class_name)
|
||||
|
|
Loading…
Reference in a new issue