feat: datakey support exportable

This commit is contained in:
2024-11-15 01:26:09 +08:00
parent 82b38a2cf1
commit 655f9f5ede
2 changed files with 19 additions and 14 deletions

View File

@@ -7,7 +7,7 @@ use rand::{random, thread_rng};
use rsa::pkcs1::LineEnding;
use rsa::pkcs8::EncodePublicKey;
use rsa::{Oaep, RsaPrivateKey, RsaPublicKey};
use rust_util::{opt_result, simple_error, XResult};
use rust_util::{iff, opt_result, simple_error, XResult};
use serde_derive::{Deserialize, Serialize};
use sha1::Sha1;
use sha2::{Digest, Sha256};
@@ -18,7 +18,7 @@ const JWE_ALG_A256KW: &str = "A256KW";
const JWE_ALG_RSA_OAEP: &str = "RSA-OAEP";
const JWE_DOT: &str = ".";
#[derive(Debug, Serialize, Deserialize)]
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct JweHeader {
pub enc: String,
pub alg: String,
@@ -27,6 +27,8 @@ pub struct JweHeader {
pub version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub data_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub exportable: Option<bool>,
}
pub fn generate_rsa_key(bits: u32) -> XResult<RsaPrivateKey> {
@@ -58,8 +60,7 @@ pub fn serialize_jwe_rsa(payload: &[u8], rsa_public_key: &RsaPublicKey) -> XResu
enc: JWE_ENC_A256GCM.to_string(),
alg: JWE_ALG_RSA_OAEP.to_string(),
vendor: "local-mini-kms".to_string(),
version: None,
data_type: None,
..Default::default()
};
serialize_jwe_fn(&header, payload, |data_key| -> XResult<Vec<u8>> {
let mut r = thread_rng();
@@ -77,20 +78,22 @@ pub fn deserialize_jwe_rsa(jwe: &str, rsa: &RsaPrivateKey) -> XResult<(Vec<u8>,
}
pub fn serialize_jwe_aes(payload: &[u8], key: &[u8]) -> XResult<String> {
serialize_jwe_aes_32(None, payload, to_bytes32(key)?)
serialize_jwe_aes_32(None, None, payload, to_bytes32(key)?)
}
pub fn serialize_jwe_aes_with_data_type(data_type: &str, payload: &[u8], key: &[u8]) -> XResult<String> {
serialize_jwe_aes_32(Some(data_type.to_string()), payload, to_bytes32(key)?)
pub fn serialize_jwe_aes_with_data_type(data_type: &str, exportable: bool, payload: &[u8], key: &[u8]) -> XResult<String> {
serialize_jwe_aes_32(Some(data_type.to_string()), iff!(exportable, Some(false), None), payload, to_bytes32(key)?)
}
pub fn serialize_jwe_aes_32(data_type: Option<String>, payload: &[u8], key: [u8; 32]) -> XResult<String> {
pub fn serialize_jwe_aes_32(data_type: Option<String>, exportable: Option<bool>, payload: &[u8], key: [u8; 32]) -> XResult<String> {
let header = JweHeader {
enc: JWE_ENC_A256GCM.to_string(),
alg: JWE_ALG_A256KW.to_string(),
vendor: "local-mini-kms".to_string(),
version: Some(get_master_key_checksum(&key)),
data_type,
exportable,
..Default::default()
};
serialize_jwe_fn(&header, payload, |data_key| -> XResult<Vec<u8>> {
let kek = Kek::from(key);

View File

@@ -20,6 +20,7 @@ struct DataKeyRequest {
key_type: String,
key_spec: String,
key_name: Option<String>,
exportable: Option<bool>,
return_plaintext: Option<bool>,
}
@@ -36,12 +37,13 @@ async fn inner_generate(req: Request<Body>) -> XResult<(StatusCode, Value)> {
None => return serve_common::error("status_not_ready"),
Some(key) => key,
};
let ret_key_plaintext = request.return_plaintext.unwrap_or(false);
let exportable = request.exportable.unwrap_or(true);
let ret_key_plaintext = iff!(exportable, false, request.return_plaintext.unwrap_or(false));
let response_result = match (request.key_type.as_str(), request.key_spec.as_str()) {
("aes", "128") => generate_aes("datakey:aes-128", key, 16, ret_key_plaintext),
("aes", "192") => generate_aes("datakey:aes-192", key, 24, ret_key_plaintext),
("aes", "256") => generate_aes("datakey:aes-256", key, 32, ret_key_plaintext),
("aes", "128") => generate_aes("datakey:aes-128", exportable, key, 16, ret_key_plaintext),
("aes", "192") => generate_aes("datakey:aes-192", exportable, key, 24, ret_key_plaintext),
("aes", "256") => generate_aes("datakey:aes-256", exportable, key, 32, ret_key_plaintext),
// TODO rsa 2048, rsa 3072, rsa 4096
// TODO ec p256, p384, p521, ed25519, cv25519
_ => return serve_common::error("invalid key_type or key_spec"),
@@ -68,10 +70,10 @@ async fn inner_generate(req: Request<Body>) -> XResult<(StatusCode, Value)> {
}
}
fn generate_aes(data_key_type: &str, key: SecBytes, len: i32, ret_key_plaintext: bool) -> XResult<(Option<Vec<u8>>, String)> {
fn generate_aes(data_key_type: &str, exportable: bool, key: SecBytes, len: i32, ret_key_plaintext: bool) -> XResult<(Option<Vec<u8>>, String)> {
let bytes: [u8; 32] = random();
let value = &bytes[0..len as usize];
let key_plaintext = iff!(ret_key_plaintext, Some(value.to_vec()), None);
let key_ciphertext = jose::serialize_jwe_aes_with_data_type(data_key_type, value, &key.read())?;
let key_ciphertext = jose::serialize_jwe_aes_with_data_type(data_key_type, exportable, value, &key.read())?;
Ok((key_plaintext, key_ciphertext))
}