2024-01-01 14:58:21 -05:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2023-01-13 02:51:32 -05:00
|
|
|
|
2023-09-13 11:54:19 -04:00
|
|
|
use deno_core::op2;
|
2023-08-23 19:03:05 -04:00
|
|
|
use deno_core::unsync::spawn_blocking;
|
2023-06-22 17:37:56 -04:00
|
|
|
use deno_core::ToJsBuffer;
|
2021-12-13 12:45:08 -05:00
|
|
|
use elliptic_curve::rand_core::OsRng;
|
|
|
|
use num_traits::FromPrimitive;
|
2021-12-18 16:14:42 -05:00
|
|
|
use once_cell::sync::Lazy;
|
2021-12-13 12:45:08 -05:00
|
|
|
use ring::rand::SecureRandom;
|
|
|
|
use ring::signature::EcdsaKeyPair;
|
2022-06-20 07:23:57 -04:00
|
|
|
use rsa::pkcs1::EncodeRsaPrivateKey;
|
2021-12-13 12:45:08 -05:00
|
|
|
use rsa::BigUint;
|
|
|
|
use rsa::RsaPrivateKey;
|
|
|
|
use serde::Deserialize;
|
|
|
|
|
2023-01-13 02:51:32 -05:00
|
|
|
use crate::shared::*;
|
|
|
|
|
2024-10-18 18:23:20 -04:00
|
|
|
#[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,
|
|
|
|
}
|
|
|
|
|
2021-12-13 12:45:08 -05:00
|
|
|
// Allowlist for RSA public exponents.
|
2021-12-18 16:14:42 -05:00
|
|
|
static PUB_EXPONENT_1: Lazy<BigUint> =
|
|
|
|
Lazy::new(|| BigUint::from_u64(3).unwrap());
|
|
|
|
static PUB_EXPONENT_2: Lazy<BigUint> =
|
|
|
|
Lazy::new(|| BigUint::from_u64(65537).unwrap());
|
2021-12-13 12:45:08 -05:00
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
#[serde(rename_all = "camelCase", tag = "algorithm")]
|
|
|
|
pub enum GenerateKeyOptions {
|
|
|
|
#[serde(rename = "RSA", rename_all = "camelCase")]
|
|
|
|
Rsa {
|
|
|
|
modulus_length: u32,
|
|
|
|
#[serde(with = "serde_bytes")]
|
|
|
|
public_exponent: Vec<u8>,
|
|
|
|
},
|
|
|
|
#[serde(rename = "EC", rename_all = "camelCase")]
|
|
|
|
Ec { named_curve: EcNamedCurve },
|
|
|
|
#[serde(rename = "AES", rename_all = "camelCase")]
|
|
|
|
Aes { length: usize },
|
|
|
|
#[serde(rename = "HMAC", rename_all = "camelCase")]
|
|
|
|
Hmac {
|
|
|
|
hash: ShaHash,
|
|
|
|
length: Option<usize>,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2023-09-13 11:54:19 -04:00
|
|
|
#[op2(async)]
|
|
|
|
#[serde]
|
2021-12-13 12:45:08 -05:00
|
|
|
pub async fn op_crypto_generate_key(
|
2023-09-13 11:54:19 -04:00
|
|
|
#[serde] opts: GenerateKeyOptions,
|
2024-10-18 18:23:20 -04:00
|
|
|
) -> Result<ToJsBuffer, GenerateKeyError> {
|
2021-12-13 12:45:08 -05:00
|
|
|
let fun = || match opts {
|
|
|
|
GenerateKeyOptions::Rsa {
|
|
|
|
modulus_length,
|
|
|
|
public_exponent,
|
|
|
|
} => generate_key_rsa(modulus_length, &public_exponent),
|
|
|
|
GenerateKeyOptions::Ec { named_curve } => generate_key_ec(named_curve),
|
|
|
|
GenerateKeyOptions::Aes { length } => generate_key_aes(length),
|
|
|
|
GenerateKeyOptions::Hmac { hash, length } => {
|
|
|
|
generate_key_hmac(hash, length)
|
|
|
|
}
|
|
|
|
};
|
2023-05-14 17:40:01 -04:00
|
|
|
let buf = spawn_blocking(fun).await.unwrap()?;
|
2021-12-13 12:45:08 -05:00
|
|
|
Ok(buf.into())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn generate_key_rsa(
|
|
|
|
modulus_length: u32,
|
|
|
|
public_exponent: &[u8],
|
2024-10-18 18:23:20 -04:00
|
|
|
) -> Result<Vec<u8>, GenerateKeyError> {
|
2021-12-13 12:45:08 -05:00
|
|
|
let exponent = BigUint::from_bytes_be(public_exponent);
|
|
|
|
if exponent != *PUB_EXPONENT_1 && exponent != *PUB_EXPONENT_2 {
|
2024-10-18 18:23:20 -04:00
|
|
|
return Err(GenerateKeyError::BadPublicExponent);
|
2021-12-13 12:45:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
let mut rng = OsRng;
|
|
|
|
|
|
|
|
let private_key =
|
|
|
|
RsaPrivateKey::new_with_exp(&mut rng, modulus_length as usize, &exponent)
|
2024-10-18 18:23:20 -04:00
|
|
|
.map_err(|_| GenerateKeyError::FailedRSAKeyGeneration)?;
|
2021-12-13 12:45:08 -05:00
|
|
|
|
|
|
|
let private_key = private_key
|
|
|
|
.to_pkcs1_der()
|
2024-10-18 18:23:20 -04:00
|
|
|
.map_err(|_| GenerateKeyError::FailedRSAKeySerialization)?;
|
2021-12-13 12:45:08 -05:00
|
|
|
|
2022-06-20 07:23:57 -04:00
|
|
|
Ok(private_key.as_bytes().to_vec())
|
2021-12-13 12:45:08 -05:00
|
|
|
}
|
|
|
|
|
2024-01-06 06:18:31 -05:00
|
|
|
fn generate_key_ec_p521() -> Vec<u8> {
|
|
|
|
let mut rng = OsRng;
|
|
|
|
let key = p521::SecretKey::random(&mut rng);
|
|
|
|
key.to_nonzero_scalar().to_bytes().to_vec()
|
|
|
|
}
|
|
|
|
|
2024-10-18 18:23:20 -04:00
|
|
|
fn generate_key_ec(
|
|
|
|
named_curve: EcNamedCurve,
|
|
|
|
) -> Result<Vec<u8>, GenerateKeyError> {
|
2021-12-13 12:45:08 -05:00
|
|
|
let curve = match named_curve {
|
|
|
|
EcNamedCurve::P256 => &ring::signature::ECDSA_P256_SHA256_FIXED_SIGNING,
|
|
|
|
EcNamedCurve::P384 => &ring::signature::ECDSA_P384_SHA384_FIXED_SIGNING,
|
2024-01-06 06:18:31 -05:00
|
|
|
EcNamedCurve::P521 => return Ok(generate_key_ec_p521()),
|
2021-12-13 12:45:08 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
let rng = ring::rand::SystemRandom::new();
|
|
|
|
|
|
|
|
let pkcs8 = EcdsaKeyPair::generate_pkcs8(curve, &rng)
|
2024-10-18 18:23:20 -04:00
|
|
|
.map_err(|_| GenerateKeyError::FailedECKeyGeneration)?;
|
2021-12-13 12:45:08 -05:00
|
|
|
|
|
|
|
Ok(pkcs8.as_ref().to_vec())
|
|
|
|
}
|
|
|
|
|
2024-10-18 18:23:20 -04:00
|
|
|
fn generate_key_aes(length: usize) -> Result<Vec<u8>, GenerateKeyError> {
|
2021-12-13 12:45:08 -05:00
|
|
|
if length % 8 != 0 || length > 256 {
|
2024-10-18 18:23:20 -04:00
|
|
|
return Err(GenerateKeyError::InvalidAESKeyLength);
|
2021-12-13 12:45:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
let mut key = vec![0u8; length / 8];
|
|
|
|
let rng = ring::rand::SystemRandom::new();
|
|
|
|
rng
|
|
|
|
.fill(&mut key)
|
2024-10-18 18:23:20 -04:00
|
|
|
.map_err(|_| GenerateKeyError::FailedKeyGeneration)?;
|
2021-12-13 12:45:08 -05:00
|
|
|
|
|
|
|
Ok(key)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn generate_key_hmac(
|
|
|
|
hash: ShaHash,
|
|
|
|
length: Option<usize>,
|
2024-10-18 18:23:20 -04:00
|
|
|
) -> Result<Vec<u8>, GenerateKeyError> {
|
2021-12-13 12:45:08 -05:00
|
|
|
let hash = match hash {
|
|
|
|
ShaHash::Sha1 => &ring::hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY,
|
|
|
|
ShaHash::Sha256 => &ring::hmac::HMAC_SHA256,
|
|
|
|
ShaHash::Sha384 => &ring::hmac::HMAC_SHA384,
|
|
|
|
ShaHash::Sha512 => &ring::hmac::HMAC_SHA512,
|
|
|
|
};
|
|
|
|
|
|
|
|
let length = if let Some(length) = length {
|
|
|
|
if length % 8 != 0 {
|
2024-10-18 18:23:20 -04:00
|
|
|
return Err(GenerateKeyError::InvalidHMACKeyLength);
|
2021-12-13 12:45:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
let length = length / 8;
|
|
|
|
if length > ring::digest::MAX_BLOCK_LEN {
|
2024-10-18 18:23:20 -04:00
|
|
|
return Err(GenerateKeyError::InvalidHMACKeyLength);
|
2021-12-13 12:45:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
length
|
|
|
|
} else {
|
2023-10-27 17:15:09 -04:00
|
|
|
hash.digest_algorithm().block_len()
|
2021-12-13 12:45:08 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
let rng = ring::rand::SystemRandom::new();
|
|
|
|
let mut key = vec![0u8; length];
|
|
|
|
rng
|
|
|
|
.fill(&mut key)
|
2024-10-18 18:23:20 -04:00
|
|
|
.map_err(|_| GenerateKeyError::FailedKeyGeneration)?;
|
2021-12-13 12:45:08 -05:00
|
|
|
|
|
|
|
Ok(key)
|
|
|
|
}
|