use super::subtle::{
AesKeyGenParams, EcKeyGenParams, EcdhDerivParams, HkdfDerivParams, HmacKeyGenParams,
RsaHashedKeyGenParams,
};
use super::subtle_idl_v1::{
AesMetadata, EcdhMetadata, HkdfMetadata, HmacMetadata, RsaMetadata, SecpK1Metadata,
SecpR1Metadata, ShaMetadata,
};
use super::subtle_idl_v1_enums::{
AesKeyBitsize, AesTagLength, KeyFormat, RsaKeyBitsize, SecpK1KeyBitsize, SecpR1KeyBitsize,
ShaAlgorithm, ShaDigestBitsize,
};
use serde::{Deserialize, Serialize};
use std::error::Error;
#[derive(Deserialize, Serialize)]
struct KeyFormatWrapper {
pub format: KeyFormat,
}
pub fn is_valid_hash_algorithm(algorithm: &str) -> bool {
matches!(
algorithm,
"sha-256"
| "sha-384"
| "sha-512"
| "sha2-256"
| "sha2-384"
| "sha2-512"
| "sha3-256"
| "sha3-384"
| "sha3-512"
| "SHA-256"
| "SHA-384"
| "SHA-512"
| "SHA2-256"
| "SHA2-384"
| "SHA2-512"
| "SHA3-256"
| "SHA3-384"
| "SHA3-512"
| "sha1"
| "SHA1"
| "sha1-160"
| "SHA1-160"
)
}
pub fn digest_size(algorithm: &str) -> usize {
match algorithm {
"sha1" | "SHA1" | "sha1-160" | "SHA1-160" => 20,
"sha-256" | "SHA-256" | "sha2-256" | "SHA2-256" | "sha3-256" | "SHA3-256" => 32,
"sha-384" | "SHA-384" | "sha2-384" | "SHA2-384" | "sha3-384" | "SHA3-384" => 48,
"sha-512" | "SHA-512" | "sha2-512" | "SHA2-512" | "sha3-512" | "SHA3-512" => 64,
_ => 0,
}
}
pub fn get_sha_metadata(algorithm: &str) -> Result<ShaMetadata, Box<dyn Error>> {
match algorithm {
"sha1" | "SHA1" | "sha1-160" | "SHA1-160" => Ok(ShaMetadata {
algo_id: ShaAlgorithm::Sha2,
length: ShaDigestBitsize::Sha1,
}),
"sha-256" | "SHA-256" | "sha2-256" | "SHA2-256" => Ok(ShaMetadata {
algo_id: ShaAlgorithm::Sha2,
length: ShaDigestBitsize::Sha256,
}),
"sha-384" | "SHA-384" | "sha2-384" | "SHA2-384" => Ok(ShaMetadata {
algo_id: ShaAlgorithm::Sha2,
length: ShaDigestBitsize::Sha384,
}),
"sha-512" | "SHA-512" | "sha2-512" | "SHA2-512" => Ok(ShaMetadata {
algo_id: ShaAlgorithm::Sha2,
length: ShaDigestBitsize::Sha512,
}),
"sha3-256" | "SHA3-256" => Ok(ShaMetadata {
algo_id: ShaAlgorithm::Sha3,
length: ShaDigestBitsize::Sha256,
}),
"sha3-384" | "SHA3-384" => Ok(ShaMetadata {
algo_id: ShaAlgorithm::Sha3,
length: ShaDigestBitsize::Sha384,
}),
"sha3-512" | "SHA3-512" => Ok(ShaMetadata {
algo_id: ShaAlgorithm::Sha3,
length: ShaDigestBitsize::Sha512,
}),
_ => Err("Invalid hash algorithm".into()),
}
}
pub fn rsa_bitsize(modulus_length: u32) -> Result<RsaKeyBitsize, Box<dyn Error>> {
match modulus_length {
2048 => Ok(RsaKeyBitsize::Rsa2048),
3072 => Ok(RsaKeyBitsize::Rsa3072),
4096 => Ok(RsaKeyBitsize::Rsa4096),
_ => Err("Invalid RSA modulus length".into()),
}
}
pub fn get_rsa_metadata(params: &RsaHashedKeyGenParams) -> Result<RsaMetadata, Box<dyn Error>> {
let hash = params.hash.as_str();
if !is_valid_hash_algorithm(hash) {
return Err("Invalid hash algorithm".into());
}
let digest_size = digest_size(hash);
if digest_size == 0 {
return Err("Invalid hash algorithm".into());
}
let Ok(rsa_bitsize) = rsa_bitsize(params.modulus_length) else {
return Err("Invalid RSA modulus length".into());
};
let Ok(sha_metadata) = get_sha_metadata(hash) else {
return Err("Invalid hash algorithm".into());
};
Ok(RsaMetadata {
modulus: rsa_bitsize,
public_exponent: params.public_exponent,
sha_metadata,
})
}
pub fn get_secpr1_metadata(params: &EcKeyGenParams) -> Result<SecpR1Metadata, Box<dyn Error>> {
match params.named_curve.as_str() {
"P-256" => Ok(SecpR1Metadata {
length: SecpR1KeyBitsize::SecpR1256,
}),
"P-384" => Ok(SecpR1Metadata {
length: SecpR1KeyBitsize::SecpR1384,
}),
"P-521" => Ok(SecpR1Metadata {
length: SecpR1KeyBitsize::SecpR1521,
}),
_ => Err("Invalid curve name".into()),
}
}
pub fn get_secpk1_metadata(params: &EcKeyGenParams) -> Result<SecpK1Metadata, Box<dyn Error>> {
match params.named_curve.as_str() {
"secp256k1" | "SECP256K1" => Ok(SecpK1Metadata {
length: SecpK1KeyBitsize::SecpK1256,
}),
_ => Err("Invalid curve name".into()),
}
}
pub fn get_aes_metadata(params: &AesKeyGenParams) -> Result<AesMetadata, Box<dyn Error>> {
match params.length {
128 => Ok(AesMetadata {
length: AesKeyBitsize::Aes128,
}),
192 => Ok(AesMetadata {
length: AesKeyBitsize::Aes192,
}),
256 => Ok(AesMetadata {
length: AesKeyBitsize::Aes256,
}),
_ => Err("Invalid AES key length".into()),
}
}
pub fn get_hmac_metadata(params: &HmacKeyGenParams) -> Result<HmacMetadata, Box<dyn Error>> {
let hash: &str = params.hash.as_str();
match get_sha_metadata(hash) {
Ok(sha_metadata) => Ok(HmacMetadata {
sha_metadata,
length: params.length,
}),
Err(_) => Err("Invalid hash algorithm".into()),
}
}
pub fn get_ecdh_metadata(params: &EcdhDerivParams) -> Result<EcdhMetadata, Box<dyn Error>> {
Ok(EcdhMetadata {
public_key: params.public.id.clone(),
})
}
pub fn get_hkdf_metadata(params: &HkdfDerivParams) -> Result<HkdfMetadata, Box<dyn Error>> {
Ok(HkdfMetadata {
salt: params.salt.clone(),
info: params.info.clone(),
hash_info: get_sha_metadata(¶ms.hash)?,
})
}
pub fn get_key_format(format: &str) -> Result<KeyFormat, Box<dyn Error>> {
match format {
"raw" | "RAW" => Ok(KeyFormat::Raw),
"pkcs8" | "PKCS8" => Ok(KeyFormat::Pkcs8),
"spki" | "SPKI" => Ok(KeyFormat::Spki),
"sec1" | "SEC1" => Ok(KeyFormat::Sec1),
"pkcs1" | "PKCS1" => Ok(KeyFormat::Pkcs1),
_ => Err("Invalid key format".into()),
}
}
pub fn get_aes_tag_length(tag_length: &u32) -> Result<AesTagLength, Box<dyn Error>> {
match tag_length {
96 => Ok(AesTagLength::Tag96),
104 => Ok(AesTagLength::Tag104),
112 => Ok(AesTagLength::Tag112),
120 => Ok(AesTagLength::Tag120),
128 => Ok(AesTagLength::Tag128),
_ => Err("Invalid tag length".into()),
}
}