feat: v0.3.6, add generate aes(128,192,256 bit) datakey
This commit is contained in:
77
src/serve_datakey.rs
Normal file
77
src/serve_datakey.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
use crate::serve_common::{get_master_key, Result};
|
||||
use crate::{do_response, jose, serve_common};
|
||||
use base64::engine::general_purpose::STANDARD;
|
||||
use base64::Engine;
|
||||
use hyper::body::Buf;
|
||||
use hyper::{Body, Request, Response, StatusCode};
|
||||
use rand::random;
|
||||
use rust_util::{debugging, iff, XResult};
|
||||
use seckey::SecBytes;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use serde_json::{Map, Value};
|
||||
|
||||
|
||||
// type:aes, spec:128,192,256
|
||||
// type:rsa, spec:2048,3072,4096
|
||||
// type:ec, spec:p256,p384,p521,ed25519,cv25519
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct DataKeyRequest {
|
||||
key_type: String,
|
||||
key_spec: String,
|
||||
return_plaintext: Option<bool>,
|
||||
}
|
||||
|
||||
pub async fn generate(req: Request<Body>) -> Result<Response<Body>> {
|
||||
do_response!(inner_generate(req).await)
|
||||
}
|
||||
|
||||
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);
|
||||
let key = match get_master_key() {
|
||||
None => return serve_common::error("status_not_ready"),
|
||||
Some(key) => key,
|
||||
};
|
||||
let ret_key_plaintext = 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),
|
||||
// TODO rsa 2048, rsa 3072, rsa 4096
|
||||
// TODO ec p256, p384, p521, ed25519, cv25519
|
||||
_ => return serve_common::error("invalid key_type or key_spec"),
|
||||
};
|
||||
|
||||
match response_result {
|
||||
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));
|
||||
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));
|
||||
Ok((StatusCode::OK, Value::Object(map)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_aes(prefix: &str, 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(&join_prefix_value(prefix, value), &key.read())?;
|
||||
Ok((key_plaintext, key_ciphertext))
|
||||
}
|
||||
|
||||
fn join_prefix_value(prefix: &str, value: &[u8]) -> Vec<u8> {
|
||||
let mut ret = Vec::with_capacity(prefix.len() + value.len());
|
||||
ret.extend_from_slice(prefix.as_bytes());
|
||||
ret.extend_from_slice(value);
|
||||
ret
|
||||
}
|
||||
Reference in New Issue
Block a user