feat: v1.0.4, generate data key and save to db
This commit is contained in:
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -365,9 +365,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.2.15"
|
version = "0.2.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6"
|
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -997,7 +997,7 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "local-mini-kms"
|
name = "local-mini-kms"
|
||||||
version = "1.0.3"
|
version = "1.0.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm-stream",
|
"aes-gcm-stream",
|
||||||
"aes-kw",
|
"aes-kw",
|
||||||
@@ -1334,9 +1334,9 @@ checksum = "7be55bf0ae1635f4d7c7ddd6efc05c631e98a82104a73d35550bbc52db960027"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.91"
|
version = "1.0.92"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "307e3004becf10f5a6e0d59d20f3cd28231b0e0827a96cd3e0ce6d14bc1e4bb3"
|
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "local-mini-kms"
|
name = "local-mini-kms"
|
||||||
version = "1.0.3"
|
version = "1.0.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
31
README.md
31
README.md
@@ -11,6 +11,7 @@ cargo build --release [--no-default-features]
|
|||||||
## Init
|
## Init
|
||||||
|
|
||||||
New random master key:
|
New random master key:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
head -c 32 /dev/random | base64
|
head -c 32 /dev/random | base64
|
||||||
```
|
```
|
||||||
@@ -18,6 +19,7 @@ head -c 32 /dev/random | base64
|
|||||||
## Generate Yubikey encrypted master key
|
## Generate Yubikey encrypted master key
|
||||||
|
|
||||||
Generate encrypted master key with Yubikey:
|
Generate encrypted master key with Yubikey:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
local-mini-kms yubikey-init-master-key --generate-key [--yubikey-challenge *challenge*]
|
local-mini-kms yubikey-init-master-key --generate-key [--yubikey-challenge *challenge*]
|
||||||
```
|
```
|
||||||
@@ -25,11 +27,13 @@ local-mini-kms yubikey-init-master-key --generate-key [--yubikey-challenge *chal
|
|||||||
## Startup Server
|
## Startup Server
|
||||||
|
|
||||||
Startup without init:
|
Startup without init:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
local-mini-kms serve
|
local-mini-kms serve
|
||||||
```
|
```
|
||||||
|
|
||||||
Init with Yubikey:
|
Init with Yubikey:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
local-mini-kms serve [--init-encrypted-master-key LKMS:*** [--yubikey-challenge *challenge*]]
|
local-mini-kms serve [--init-encrypted-master-key LKMS:*** [--yubikey-challenge *challenge*]]
|
||||||
```
|
```
|
||||||
@@ -67,6 +71,7 @@ local-mini-kms cli --write --name test --value hello [--force-write] [--comment
|
|||||||
## cURL
|
## cURL
|
||||||
|
|
||||||
Write value:
|
Write value:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl -X POST http://127.0.0.1:5567/write \
|
curl -X POST http://127.0.0.1:5567/write \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
@@ -74,6 +79,7 @@ curl -X POST http://127.0.0.1:5567/write \
|
|||||||
```
|
```
|
||||||
|
|
||||||
Read value:
|
Read value:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl -X POST http://127.0.0.1:5567/read \
|
curl -X POST http://127.0.0.1:5567/read \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
@@ -81,14 +87,35 @@ curl -X POST http://127.0.0.1:5567/read \
|
|||||||
```
|
```
|
||||||
|
|
||||||
Generate data key:
|
Generate data key:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl -X POST http://127.0.0.1:5567/datakey \
|
curl -X POST http://127.0.0.1:5567/datakey \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"type":"aes", "spec":"256", "exportable": true, "return_plaintext": true}'
|
-d '{"type":"aes", "spec":"256", "exportable": true, "return_plaintext": true, "name": "key001", "comment": "the comment"}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
|
xh POST http://127.0.0.1:5567/datakey \
|
||||||
|
type=aes \
|
||||||
|
spec=256 \
|
||||||
|
exportable:=false \
|
||||||
|
name=testkey01 \
|
||||||
|
comment='this is a test key 01'
|
||||||
|
```
|
||||||
|
|
||||||
|
| Key | Comment |
|
||||||
|
|------------------|--------------------------------------------|
|
||||||
|
| type | `aes` |
|
||||||
|
| spec | ~~`128`, `192`,~~ `256` if `type` == `aes` |
|
||||||
|
| exportable | `true` or `false` |
|
||||||
|
| return_plaintext | `true` or `false` |
|
||||||
|
| name | Data key name |
|
||||||
|
| comment | Data key comment |
|
||||||
|
|
||||||
Upgrade to v3.2
|
Upgrade to v3.2
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
ALTER TABLE keys ADD COLUMN comment TEXT;
|
ALTER TABLE keys
|
||||||
|
ADD COLUMN comment TEXT;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
10
src/cli.rs
10
src/cli.rs
@@ -241,10 +241,10 @@ async fn do_inner_request(sub_arg_matches: &ArgMatches<'_>, action: &str, body:
|
|||||||
let req = Request::builder().method(Method::POST).uri(uri).body(Body::from(body))?;
|
let req = Request::builder().method(Method::POST).uri(uri).body(Body::from(body))?;
|
||||||
|
|
||||||
let req_response = client.request(req).await?;
|
let req_response = client.request(req).await?;
|
||||||
if req_response.status() != StatusCode::OK {
|
// if req_response.status() != StatusCode::OK {
|
||||||
let status = req_response.status().as_u16();
|
// let status = req_response.status().as_u16();
|
||||||
let data = response_to_value(req_response).await?;
|
// let data = response_to_value(req_response).await?;
|
||||||
return simple_error!("Server status is not success: {}, response: {}", status, data);
|
// return simple_error!("Server status is not success: {}, response: {}", status, data);
|
||||||
}
|
// }
|
||||||
response_to_value(req_response).await
|
response_to_value(req_response).await
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/db.rs
18
src/db.rs
@@ -9,10 +9,14 @@ pub struct Key {
|
|||||||
pub comment: Option<String>,
|
pub comment: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_db_key_name(name: &str) -> String {
|
pub fn make_value_key_name(name: &str) -> String {
|
||||||
format!("value:{}", name)
|
format!("value:{}", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn make_data_key_name(name: &str) -> String {
|
||||||
|
format!("data_key:{}", name)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn open_db(db: &str) -> XResult<Connection> {
|
pub fn open_db(db: &str) -> XResult<Connection> {
|
||||||
let con = opt_result!(Connection::open(db), "Open sqlite db: {}, failed: {}", db);
|
let con = opt_result!(Connection::open(db), "Open sqlite db: {}, failed: {}", db);
|
||||||
log::debug!("Db auto commit: {}", con.is_autocommit());
|
log::debug!("Db auto commit: {}", con.is_autocommit());
|
||||||
@@ -42,6 +46,7 @@ pub fn init_db(conn: &Connection) -> XResult<bool> {
|
|||||||
|
|
||||||
pub fn insert_key(conn: &Connection, key: &Key) -> XResult<()> {
|
pub fn insert_key(conn: &Connection, key: &Key) -> XResult<()> {
|
||||||
let default_comment = "".to_string();
|
let default_comment = "".to_string();
|
||||||
|
log::debug!("insert key name={}", &key.name);
|
||||||
let _ = conn.execute(
|
let _ = conn.execute(
|
||||||
"INSERT INTO keys (name, value, comment) VALUES (?1, ?2, ?3)",
|
"INSERT INTO keys (name, value, comment) VALUES (?1, ?2, ?3)",
|
||||||
(&key.name, &key.encrypted_key, key.comment.as_ref().unwrap_or(&default_comment)),
|
(&key.name, &key.encrypted_key, key.comment.as_ref().unwrap_or(&default_comment)),
|
||||||
@@ -50,6 +55,7 @@ pub fn insert_key(conn: &Connection, key: &Key) -> XResult<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_key(conn: &Connection, key: &Key) -> XResult<()> {
|
pub fn update_key(conn: &Connection, key: &Key) -> XResult<()> {
|
||||||
|
log::debug!("update key name={}", &key.name);
|
||||||
if let Some(comment) = &key.comment {
|
if let Some(comment) = &key.comment {
|
||||||
let _ = conn.execute(
|
let _ = conn.execute(
|
||||||
"UPDATE keys SET value = ?1, comment = ?2 WHERE name = ?3",
|
"UPDATE keys SET value = ?1, comment = ?2 WHERE name = ?3",
|
||||||
@@ -74,8 +80,14 @@ pub fn find_key(conn: &Connection, name: &str) -> XResult<Option<Key>> {
|
|||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
match key_iter.next() {
|
match key_iter.next() {
|
||||||
None => Ok(None),
|
None => {
|
||||||
Some(Ok(r)) => Ok(Some(r)),
|
log::debug!("key name={} not exists", name);
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
Some(Ok(r)) => {
|
||||||
|
log::debug!("found key name={}", name);
|
||||||
|
Ok(Some(r))
|
||||||
|
}
|
||||||
Some(Err(e)) => simple_error!("Find key failed: {}", e),
|
Some(Err(e)) => simple_error!("Find key failed: {}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,13 +34,20 @@ pub fn ok(body: Value) -> XResult<(StatusCode, Value)> {
|
|||||||
Ok((StatusCode::OK, body))
|
Ok((StatusCode::OK, body))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error(error: &str) -> XResult<(StatusCode, Value)> {
|
pub fn client_error(error: &str) -> XResult<(StatusCode, Value)> {
|
||||||
Ok((
|
Ok((
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
json!({ "error": error })
|
json!({ "error": error })
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn server_error(error: &str) -> XResult<(StatusCode, Value)> {
|
||||||
|
Ok((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
json!({ "error": error })
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
// pub fn bad_request(error: &str, error_message: &str) -> XResult<(StatusCode, Value)> {
|
// pub fn bad_request(error: &str, error_message: &str) -> XResult<(StatusCode, Value)> {
|
||||||
// Ok((
|
// Ok((
|
||||||
// StatusCode::BAD_REQUEST,
|
// StatusCode::BAD_REQUEST,
|
||||||
@@ -97,6 +104,15 @@ impl MultipleViewValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export] macro_rules! require_master_key {
|
||||||
|
() => {
|
||||||
|
match $crate::serve_common::get_master_key() {
|
||||||
|
None => return $crate::serve_common::client_error("status_not_ready"),
|
||||||
|
Some(key) => key,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_master_key() -> Option<SecBytes> {
|
pub fn get_master_key() -> Option<SecBytes> {
|
||||||
let startup_rw_lock = STATUP_RW_LOCK.lock().expect("Lock read startup rw lock error");
|
let startup_rw_lock = STATUP_RW_LOCK.lock().expect("Lock read startup rw lock error");
|
||||||
match &*startup_rw_lock {
|
match &*startup_rw_lock {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::serve_common::{get_master_key, Result};
|
use crate::db::Key;
|
||||||
use crate::{do_response, jose, serve_common};
|
use crate::serve_common::{open_local_db, Result};
|
||||||
|
use crate::{db, do_response, jose, require_master_key, serve_common};
|
||||||
use base64::engine::general_purpose::STANDARD;
|
use base64::engine::general_purpose::STANDARD;
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use hyper::body::Buf;
|
use hyper::body::Buf;
|
||||||
@@ -11,7 +12,6 @@ use serde_derive::{Deserialize, Serialize};
|
|||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use serde_json::{Map, Value};
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
|
|
||||||
// type:aes, spec:128,192,256
|
// type:aes, spec:128,192,256
|
||||||
// type:rsa, spec:2048,3072,4096
|
// type:rsa, spec:2048,3072,4096
|
||||||
// type:ec, spec:p256,p384,p521,ed25519,cv25519
|
// type:ec, spec:p256,p384,p521,ed25519,cv25519
|
||||||
@@ -20,6 +20,7 @@ struct DataKeyRequest {
|
|||||||
r#type: String,
|
r#type: String,
|
||||||
spec: String,
|
spec: String,
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
|
comment: Option<String>,
|
||||||
exportable: Option<bool>,
|
exportable: Option<bool>,
|
||||||
return_plaintext: Option<bool>,
|
return_plaintext: Option<bool>,
|
||||||
}
|
}
|
||||||
@@ -33,24 +34,21 @@ async fn inner_generate(req: Request<Body>) -> XResult<(StatusCode, Value)> {
|
|||||||
let request: DataKeyRequest = serde_json::from_reader(whole_body.reader())?;
|
let request: DataKeyRequest = serde_json::from_reader(whole_body.reader())?;
|
||||||
|
|
||||||
log::debug!("Generate data key: {} {}", &request.r#type, &request.spec);
|
log::debug!("Generate data key: {} {}", &request.r#type, &request.spec);
|
||||||
let key = match get_master_key() {
|
let key = require_master_key!();
|
||||||
None => return serve_common::error("status_not_ready"),
|
|
||||||
Some(key) => key,
|
|
||||||
};
|
|
||||||
let exportable = request.exportable.unwrap_or(true);
|
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.r#type.as_str(), request.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", "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", "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),
|
("aes", "256") => generate_aes("datakey:aes-256", exportable, key, 32, ret_key_plaintext),
|
||||||
// TODO rsa 2048, rsa 3072, rsa 4096
|
// TODO rsa 2048, rsa 3072, rsa 4096
|
||||||
// TODO ec p256, p384, p521, ed25519, cv25519
|
// TODO ec p256, p384, p521, ed25519, cv25519
|
||||||
_ => return serve_common::error("invalid key_type or key_spec"),
|
_ => return serve_common::client_error("invalid key_type or key_spec"),
|
||||||
};
|
};
|
||||||
|
|
||||||
match response_result {
|
match response_result {
|
||||||
Err(e) => serve_common::error(&format!("internal error: {}", e)),
|
Err(e) => serve_common::server_error(&format!("internal error: {}", e)),
|
||||||
Ok((key_plaintext, key_ciphertext)) => {
|
Ok((key_plaintext, key_ciphertext)) => {
|
||||||
let mut map = Map::new();
|
let mut map = Map::new();
|
||||||
map.insert("key_type".to_string(), Value::String(request.r#type));
|
map.insert("key_type".to_string(), Value::String(request.r#type));
|
||||||
@@ -58,11 +56,24 @@ async fn inner_generate(req: Request<Body>) -> XResult<(StatusCode, Value)> {
|
|||||||
if let Some(key_plaintext) = key_plaintext {
|
if let Some(key_plaintext) = key_plaintext {
|
||||||
map.insert("key_plaintext".to_string(), Value::String(STANDARD.encode(&key_plaintext)));
|
map.insert("key_plaintext".to_string(), Value::String(STANDARD.encode(&key_plaintext)));
|
||||||
}
|
}
|
||||||
map.insert("key_ciphertext".to_string(), Value::String(key_ciphertext));
|
map.insert("key_ciphertext".to_string(), Value::String(key_ciphertext.clone()));
|
||||||
|
|
||||||
if let Some(_name) = &request.name {
|
if let Some(name) = &request.name {
|
||||||
// TODO write datakey to db
|
if name.is_empty() {
|
||||||
// TODO let data_key_name = format!("datakey:{}", name);
|
return serve_common::client_error("name_is_empty");
|
||||||
|
}
|
||||||
|
let conn = open_local_db()?;
|
||||||
|
let db_key_name = db::make_data_key_name(name);
|
||||||
|
let db_key = db::find_key(&conn, &db_key_name)?;
|
||||||
|
if db_key.is_some() {
|
||||||
|
return serve_common::client_error("name_exists");
|
||||||
|
}
|
||||||
|
let key = Key {
|
||||||
|
name: db_key_name,
|
||||||
|
encrypted_key: key_ciphertext,
|
||||||
|
comment: request.comment,
|
||||||
|
};
|
||||||
|
db::insert_key(&conn, &key)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((StatusCode::OK, Value::Object(map)))
|
Ok((StatusCode::OK, Value::Object(map)))
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ use rust_util::XResult;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::{json, Map, Value};
|
use serde_json::{json, Map, Value};
|
||||||
|
|
||||||
use crate::do_response;
|
|
||||||
use crate::jose;
|
use crate::jose;
|
||||||
use crate::serve_common::{self, byte_to_multi_view_map, get_master_key, MultipleViewValue, Result};
|
use crate::serve_common::{self, byte_to_multi_view_map, MultipleViewValue, Result};
|
||||||
|
use crate::{do_response, require_master_key};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct DecryptRequest {
|
struct DecryptRequest {
|
||||||
@@ -22,16 +22,13 @@ async fn inner_decrypt(req: Request<Body>) -> XResult<(StatusCode, Value)> {
|
|||||||
let data: DecryptRequest = serde_json::from_reader(whole_body.reader())?;
|
let data: DecryptRequest = serde_json::from_reader(whole_body.reader())?;
|
||||||
|
|
||||||
log::debug!("To be decrypted value: {}", &data.encrypted_value);
|
log::debug!("To be decrypted value: {}", &data.encrypted_value);
|
||||||
let key = match get_master_key() {
|
let key = require_master_key!();
|
||||||
None => return serve_common::error("status_not_ready"),
|
|
||||||
Some(key) => key,
|
|
||||||
};
|
|
||||||
let decrypted_value = jose::deserialize_jwe_aes(&data.encrypted_value, &key.read());
|
let decrypted_value = jose::deserialize_jwe_aes(&data.encrypted_value, &key.read());
|
||||||
drop(key);
|
drop(key);
|
||||||
let (data, header) = decrypted_value?;
|
let (data, header) = decrypted_value?;
|
||||||
|
|
||||||
if let Some(false) = header.exportable {
|
if let Some(false) = header.exportable {
|
||||||
return serve_common::error("data_not_exportable");
|
return serve_common::client_error("data_not_exportable");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut map = byte_to_multi_view_map(&data, true);
|
let mut map = byte_to_multi_view_map(&data, true);
|
||||||
@@ -58,10 +55,7 @@ async fn inner_encrypt(req: Request<Body>) -> XResult<(StatusCode, Value)> {
|
|||||||
let whole_body = hyper::body::aggregate(req).await?;
|
let whole_body = hyper::body::aggregate(req).await?;
|
||||||
let data: MultipleViewValue = serde_json::from_reader(whole_body.reader())?;
|
let data: MultipleViewValue = serde_json::from_reader(whole_body.reader())?;
|
||||||
let value = data.to_bytes()?;
|
let value = data.to_bytes()?;
|
||||||
let key = match get_master_key() {
|
let key = require_master_key!();
|
||||||
None => return serve_common::error("status_not_ready"),
|
|
||||||
Some(key) => key,
|
|
||||||
};
|
|
||||||
let encrypt_result = jose::serialize_jwe_aes(&value, &key.read());
|
let encrypt_result = jose::serialize_jwe_aes(&value, &key.read());
|
||||||
drop(key);
|
drop(key);
|
||||||
|
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ async fn inner_init(req: Request<Body>) -> XResult<(StatusCode, Value)> {
|
|||||||
pub async fn inner_init_request(init_request: InitRequest) -> XResult<(StatusCode, Value)> {
|
pub async fn inner_init_request(init_request: InitRequest) -> XResult<(StatusCode, Value)> {
|
||||||
let mut startup_rw_lock = serve_common::STATUP_RW_LOCK.lock().expect("Lock read startup rw lock error");
|
let mut startup_rw_lock = serve_common::STATUP_RW_LOCK.lock().expect("Lock read startup rw lock error");
|
||||||
match &*startup_rw_lock {
|
match &*startup_rw_lock {
|
||||||
None => return Ok((StatusCode::INTERNAL_SERVER_ERROR, json!({ "error": "internal_error", "error_message": "not init " }))),
|
None => return serve_common::server_error("instant_key_pair_not_initialized"),
|
||||||
Some(memory_key) => if memory_key.master_key.is_some() {
|
Some(memory_key) => if memory_key.master_key.is_some() {
|
||||||
return Ok((StatusCode::BAD_REQUEST, json!({ "error": "bad_request", "error_message": "already init " })));
|
return serve_common::client_error("already_initialized");
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,14 +53,14 @@ pub async fn inner_init_request(init_request: InitRequest) -> XResult<(StatusCod
|
|||||||
let (clear_master_key, _) = jose::deserialize_jwe_rsa(&encrypted_master_key, &k.instance_rsa_key_pair)?;
|
let (clear_master_key, _) = jose::deserialize_jwe_rsa(&encrypted_master_key, &k.instance_rsa_key_pair)?;
|
||||||
clear_master_key
|
clear_master_key
|
||||||
} else {
|
} else {
|
||||||
return Ok((StatusCode::INTERNAL_SERVER_ERROR, json!({ "error": "internal_error", "error_message": "not init " })));
|
return serve_common::server_error("instant_key_pair_not_initialized");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return serve_common::error("master_key_missing");
|
return serve_common::client_error("master_key_missing");
|
||||||
};
|
};
|
||||||
|
|
||||||
if clear_master_key.len() != 32 {
|
if clear_master_key.len() != 32 {
|
||||||
return serve_common::error("bad_master_key_length");
|
return serve_common::client_error("bad_master_key_length");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(k) = &mut *startup_rw_lock {
|
if let Some(k) = &mut *startup_rw_lock {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::db::Key;
|
use crate::db::Key;
|
||||||
use crate::do_response;
|
use crate::serve_common::{self, byte_to_multi_view_map, open_local_db, MultipleViewValue, Result};
|
||||||
use crate::serve_common::{self, byte_to_multi_view_map, get_master_key, open_local_db, MultipleViewValue, Result};
|
|
||||||
use crate::{db, jose};
|
use crate::{db, jose};
|
||||||
|
use crate::{do_response, require_master_key};
|
||||||
use hyper::body::Buf;
|
use hyper::body::Buf;
|
||||||
use hyper::{Body, Request, Response, StatusCode};
|
use hyper::{Body, Request, Response, StatusCode};
|
||||||
use rust_util::XResult;
|
use rust_util::XResult;
|
||||||
@@ -30,22 +30,19 @@ async fn inner_read(req: Request<Body>) -> XResult<(StatusCode, Value)> {
|
|||||||
let named: Named = serde_json::from_reader(whole_body.reader())?;
|
let named: Named = serde_json::from_reader(whole_body.reader())?;
|
||||||
let name = &named.name;
|
let name = &named.name;
|
||||||
if name.is_empty() {
|
if name.is_empty() {
|
||||||
return serve_common::error("key_name_is_empty");
|
return serve_common::client_error("name_is_empty");
|
||||||
}
|
}
|
||||||
let db_key_name = db::make_db_key_name(name);
|
let db_key_name = db::make_value_key_name(name);
|
||||||
|
|
||||||
let conn = open_local_db()?;
|
let conn = open_local_db()?;
|
||||||
let db_key = db::find_key(&conn, &db_key_name)?;
|
let db_key = db::find_key(&conn, &db_key_name)?;
|
||||||
|
|
||||||
let db_key_value = match db_key {
|
let db_key_value = match db_key {
|
||||||
None => return serve_common::error("key_name_not_exists"),
|
None => return serve_common::client_error("name_not_exists"),
|
||||||
Some(k) => k,
|
Some(k) => k,
|
||||||
};
|
};
|
||||||
|
|
||||||
let key = match get_master_key() {
|
let key = require_master_key!();
|
||||||
None => return serve_common::error("status_not_ready"),
|
|
||||||
Some(key) => key,
|
|
||||||
};
|
|
||||||
let data = jose::deserialize_jwe_aes(&db_key_value.encrypted_key, &key.read())?;
|
let data = jose::deserialize_jwe_aes(&db_key_value.encrypted_key, &key.read())?;
|
||||||
drop(key);
|
drop(key);
|
||||||
|
|
||||||
@@ -64,23 +61,20 @@ async fn inner_write(req: Request<Body>) -> XResult<(StatusCode, Value)> {
|
|||||||
let named_value: NamedValue = serde_json::from_reader(whole_body.reader())?;
|
let named_value: NamedValue = serde_json::from_reader(whole_body.reader())?;
|
||||||
let name = &named_value.name;
|
let name = &named_value.name;
|
||||||
if name.is_empty() {
|
if name.is_empty() {
|
||||||
return serve_common::error("key_name_is_empty");
|
return serve_common::client_error("name_is_empty");
|
||||||
}
|
}
|
||||||
let db_key_name = db::make_db_key_name(name);
|
let db_key_name = db::make_value_key_name(name);
|
||||||
let force_write = named_value.force_write.unwrap_or(false);
|
let force_write = named_value.force_write.unwrap_or(false);
|
||||||
|
|
||||||
let conn = open_local_db()?;
|
let conn = open_local_db()?;
|
||||||
let db_key = db::find_key(&conn, &db_key_name)?;
|
let db_key = db::find_key(&conn, &db_key_name)?;
|
||||||
|
|
||||||
if db_key.is_some() && !force_write {
|
if db_key.is_some() && !force_write {
|
||||||
return serve_common::error("key_name_exists");
|
return serve_common::client_error("name_exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
let value = named_value.value.to_bytes()?;
|
let value = named_value.value.to_bytes()?;
|
||||||
let key = match get_master_key() {
|
let key = require_master_key!();
|
||||||
None => return serve_common::error("status_not_ready"),
|
|
||||||
Some(key) => key,
|
|
||||||
};
|
|
||||||
let encrypt_value = jose::serialize_jwe_aes(&value, &key.read())?;
|
let encrypt_value = jose::serialize_jwe_aes(&value, &key.read())?;
|
||||||
drop(key);
|
drop(key);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user