feat: datakey support exportable
This commit is contained in:
19
src/jose.rs
19
src/jose.rs
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user