feat: datakey decrypt fails when not exportable

This commit is contained in:
2024-11-15 01:44:21 +08:00
parent 655f9f5ede
commit 909ac90eb9
4 changed files with 37 additions and 37 deletions

View File

@@ -84,7 +84,7 @@ Generate data key:
```shell
curl -X POST http://127.0.0.1:5567/datakey \
-H "Content-Type: application/json" \
-d '{"key_type":"aes", "key_spec":"256", "return_plaintext": true}'
-d '{"type":"aes", "spec":"256", "exportable": true, "return_plaintext": true}'
```
Upgrade to v3.2

View File

@@ -50,7 +50,7 @@ pub fn rsa_key_to_pem(rsa_private_key: &RsaPrivateKey) -> XResult<String> {
}
pub fn jwk_to_rsa_pubic_key(rsa_jwk: &str) -> XResult<RsaPublicKey> {
let rsa: Rsa = opt_result!(serde_json::from_str(&rsa_jwk), "Bad RSA JWK: {}, error: {}", rsa_jwk);
let rsa: Rsa = opt_result!(serde_json::from_str(rsa_jwk), "Bad RSA JWK: {}, error: {}", rsa_jwk);
let rsa_public_key = opt_result!(RsaPublicKey::try_from(rsa), "Bad RSA JWK: {}, error: {:?}", rsa_jwk);
Ok(rsa_public_key)
}
@@ -73,7 +73,7 @@ pub fn deserialize_jwe_rsa(jwe: &str, rsa: &RsaPrivateKey) -> XResult<(Vec<u8>,
if alg != JWE_ALG_RSA_OAEP {
return simple_error!("Invalid JWE header alg: {}", alg);
}
Ok(opt_result!(rsa.decrypt(Oaep::new::<Sha1>(), &key_wrap), "Unwrap key failed: {}"))
Ok(opt_result!(rsa.decrypt(Oaep::new::<Sha1>(), key_wrap), "Unwrap key failed: {}"))
})
}
@@ -82,7 +82,7 @@ pub fn serialize_jwe_aes(payload: &[u8], key: &[u8]) -> XResult<String> {
}
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)?)
serialize_jwe_aes_32(Some(data_type.to_string()), iff!(exportable, None, Some(false)), payload, to_bytes32(key)?)
}
pub fn serialize_jwe_aes_32(data_type: Option<String>, exportable: Option<bool>, payload: &[u8], key: [u8; 32]) -> XResult<String> {
@@ -93,11 +93,10 @@ pub fn serialize_jwe_aes_32(data_type: Option<String>, exportable: Option<bool>,
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);
Ok(opt_result!(kek.wrap_vec(&data_key[..]), "Wrap key failed: {}"))
Ok(opt_result!(kek.wrap_vec(data_key), "Wrap key failed: {}"))
})
}
@@ -111,7 +110,7 @@ pub fn deserialize_jwe_aes_32(jwe: &str, key: [u8; 32]) -> XResult<(Vec<u8>, Jwe
return simple_error!("Invalid JWE header alg: {}", alg);
}
let kek = Kek::from(key);
Ok(opt_result!(kek.unwrap_vec(&key_wrap), "Unwrap key failed: {}"))
Ok(opt_result!(kek.unwrap_vec(key_wrap), "Unwrap key failed: {}"))
})
}
@@ -137,7 +136,7 @@ where
LOCAL_KMS_PREFIX,
header_b64,
URL_SAFE_NO_PAD.encode(&cek),
URL_SAFE_NO_PAD.encode(&iv),
URL_SAFE_NO_PAD.encode(iv),
URL_SAFE_NO_PAD.encode(&ciphertext),
URL_SAFE_NO_PAD.encode(&tag)
))
@@ -187,9 +186,7 @@ fn to_bytes32(bytes: &[u8]) -> XResult<[u8; 32]> {
return simple_error!("Not valid 32 bytes");
}
let mut ret = [0; 32];
for i in 0..32 {
ret[i] = bytes[i];
}
ret.copy_from_slice(&bytes[..32]);
Ok(ret)
}

View File

@@ -17,9 +17,9 @@ use serde_json::{Map, Value};
// type:ec, spec:p256,p384,p521,ed25519,cv25519
#[derive(Serialize, Deserialize)]
struct DataKeyRequest {
key_type: String,
key_spec: String,
key_name: Option<String>,
r#type: String,
spec: String,
name: Option<String>,
exportable: Option<bool>,
return_plaintext: Option<bool>,
}
@@ -32,15 +32,15 @@ async fn inner_generate(req: Request<Body>) -> XResult<(StatusCode, Value)> {
let whole_body = hyper::body::aggregate(req).await?;
let request: DataKeyRequest = serde_json::from_reader(whole_body.reader())?;
debugging!("Generate data key: {} {}", &request.key_type, &request.key_spec);
debugging!("Generate data key: {} {}", &request.r#type, &request.spec);
let key = match get_master_key() {
None => return serve_common::error("status_not_ready"),
Some(key) => key,
};
let exportable = request.exportable.unwrap_or(true);
let ret_key_plaintext = iff!(exportable, false, request.return_plaintext.unwrap_or(false));
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()) {
let response_result = match (request.r#type.as_str(), request.spec.as_str()) {
("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),
@@ -53,16 +53,16 @@ async fn inner_generate(req: Request<Body>) -> XResult<(StatusCode, Value)> {
Err(e) => serve_common::error(&format!("internal error: {}", e)),
Ok((key_plaintext, key_ciphertext)) => {
let mut map = Map::new();
map.insert("key_type".to_string(), Value::String(request.key_type));
map.insert("key_spec".to_string(), Value::String(request.key_spec));
map.insert("key_type".to_string(), Value::String(request.r#type));
map.insert("key_spec".to_string(), Value::String(request.spec));
if let Some(key_plaintext) = key_plaintext {
map.insert("key_plaintext".to_string(), Value::String(STANDARD.encode(&key_plaintext)));
}
map.insert("key_ciphertext".to_string(), Value::String(key_ciphertext));
if let Some(_key_name) = &request.key_name {
if let Some(_name) = &request.name {
// TODO write datakey to db
// TODO let data_key_name = format!("datakey:{}", key_name);
// TODO let data_key_name = format!("datakey:{}", name);
}
Ok((StatusCode::OK, Value::Object(map)))

View File

@@ -28,23 +28,26 @@ async fn inner_decrypt(req: Request<Body>) -> XResult<(StatusCode, Value)> {
};
let decrypted_value = jose::deserialize_jwe_aes(&data.encrypted_value, &key.read());
drop(key);
let (data, header) = decrypted_value?;
decrypted_value.map(|(data, header)| {
let mut map = byte_to_multi_view_map(&data, true);
let mut header_map = Map::new();
header_map.insert("enc".to_string(), Value::String(header.enc.clone()));
header_map.insert("alg".to_string(), Value::String(header.alg.clone()));
if let Some(version) = &header.version {
header_map.insert("version".to_string(), Value::String(version.to_string()));
}
if let Some(data_type) = &header.data_type {
header_map.insert("data_type".to_string(), Value::String(data_type.to_string()));
}
if !header_map.is_empty() {
map.insert("header".to_string(), Value::Object(header_map));
}
(StatusCode::OK, Value::Object(map))
})
if let Some(false) = header.exportable {
return serve_common::error("data_not_exportable");
}
let mut map = byte_to_multi_view_map(&data, true);
let mut header_map = Map::new();
header_map.insert("enc".to_string(), Value::String(header.enc.clone()));
header_map.insert("alg".to_string(), Value::String(header.alg.clone()));
if let Some(version) = &header.version {
header_map.insert("version".to_string(), Value::String(version.to_string()));
}
if let Some(data_type) = &header.data_type {
header_map.insert("data_type".to_string(), Value::String(data_type.to_string()));
}
if !header_map.is_empty() {
map.insert("header".to_string(), Value::Object(header_map));
}
Ok((StatusCode::OK, Value::Object(map)))
}
pub async fn encrypt(req: Request<Body>) -> Result<Response<Body>> {