Skip to content

Commit

Permalink
sdk: add crypto basic support
Browse files Browse the repository at this point in the history
  • Loading branch information
fuxiaohei committed Sep 4, 2024
1 parent 6b1e103 commit ae8c484
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 70 deletions.
138 changes: 71 additions & 67 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace.package]
version = "0.5.0-rc.7"
version = "0.5.0-rc.10"
edition = "2021"
authors = ["fuxiaohei <fudong0797@gmail.com>"]

Expand Down Expand Up @@ -58,7 +58,7 @@ serde = { version = "1.0.209", features = ["derive"] }
serde_json = "1.0.127"
strum = { version = "0.26.3", features = ["derive"] }
time = { version = "0.3.36", features = ["local-offset"] }
tokio = { version = "1.39.3", features = ["full"] }
tokio = { version = "1.40.0", features = ["full"] }
tower-http = { version = "0.5.2", features = [
"timeout",
"cors",
Expand Down
2 changes: 1 addition & 1 deletion lib/sdk-macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ authors = { workspace = true }
anyhow = { workspace = true }
http = { workspace = true }
quote = "1.0.37"
syn = { version = "2.0.76", features = ["full"] }
syn = { version = "2.0.77", features = ["full"] }

[lib]
proc-macro = true
Expand Down
6 changes: 6 additions & 0 deletions lib/sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ authors = { workspace = true }

[dependencies]
anyhow = { workspace = true }
hmac = { version = "0.12.1" }
http = { workspace = true }
land-sdk-macro = { workspace = true }
lazy_static = { workspace = true }
matchit = "0.8.4"
sha1 = { version = "0.10.6" }
sha2 = { version = "0.10.8" }
wit-bindgen = { workspace = true }

[features]
crypto = [] #["hmac", "sha2", "sha1"]
83 changes: 83 additions & 0 deletions lib/sdk/src/crypto/hmac.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use super::{Algorithm, Error};
use hmac::{Hmac, Mac};
use sha1::Sha1;
use sha2::{Sha256, Sha384, Sha512};
use std::collections::HashMap;
use std::sync::Mutex;

type HmacSha1 = Hmac<Sha1>;
type HmacSha256 = Hmac<Sha256>;
type HmacSha384 = Hmac<Sha384>;
type HmacSha512 = Hmac<Sha512>;

lazy_static::lazy_static! {
static ref HMAC_HANDLES: Mutex<HashMap<u32, Algorithm>> = Mutex::new(HashMap::new());
static ref HMAC_SHA1: Mutex<HashMap<u32,HmacSha1>> = Mutex::new(HashMap::new());
static ref HMAC_SHA256: Mutex<HashMap<u32,HmacSha256>> = Mutex::new(HashMap::new());
static ref HMAC_SHA384: Mutex<HashMap<u32,HmacSha384>> = Mutex::new(HashMap::new());
static ref HMAC_SHA512: Mutex<HashMap<u32,HmacSha512>> = Mutex::new(HashMap::new());
}

macro_rules! new_hmac_key {
($alg:ident, $map:ident, $handle:expr, $key:expr) => {{
let hmac = $alg::new_from_slice($key).map_err(|_| Error::InvalidKey)?;
$map.lock().unwrap().insert($handle, hmac);
}};
}

/// new_key create hmac key
pub fn new_key(handle: u32, al: Algorithm, key: &[u8]) -> Result<(), Error> {
HMAC_HANDLES.lock().unwrap().insert(handle, al.clone());
match al {
Algorithm::HmacSha1 => new_hmac_key!(HmacSha1, HMAC_SHA1, handle, key),
Algorithm::HmacSha256 => new_hmac_key!(HmacSha256, HMAC_SHA256, handle, key),
Algorithm::HmacSha384 => new_hmac_key!(HmacSha384, HMAC_SHA384, handle, key),
Algorithm::HmacSha512 => new_hmac_key!(HmacSha512, HMAC_SHA512, handle, key),
}
Ok(())
}

macro_rules! sign_hmac {
($alg:ident, $map:ident, $handle:expr, $data:expr) => {{
let mut map = $map.lock().unwrap();
let mac = map.get_mut(&$handle).ok_or(Error::InvalidHandle)?;
mac.update($data);
let result = mac.clone().finalize().into_bytes();
Ok(result.to_vec())
}};
}

/// sign sign data and return signature
pub fn sign(handle: u32, data: Vec<u8>) -> Result<Vec<u8>, Error> {
let handles = HMAC_HANDLES.lock().unwrap();
let al = handles.get(&handle).ok_or(Error::InvalidHandle)?;
match al {
Algorithm::HmacSha1 => sign_hmac!(HMAC_SHA1, HMAC_SHA1, handle, &data),
Algorithm::HmacSha256 => sign_hmac!(HMAC_SHA256, HMAC_SHA256, handle, &data),
Algorithm::HmacSha384 => sign_hmac!(HMAC_SHA384, HMAC_SHA384, handle, &data),
Algorithm::HmacSha512 => sign_hmac!(HMAC_SHA512, HMAC_SHA512, handle, &data),
}
}

macro_rules! verify_hmac {
($alg:ident, $map:ident, $handle:expr, $signature:expr, $data:expr) => {{
let mut map = $map.lock().unwrap();
let mac = map.get_mut(&$handle).ok_or(Error::InvalidHandle)?;
mac.update($data);
let res = mac.clone().verify_slice($signature);
res.is_ok()
}};
}

/// verify verify signature
pub fn verify(handle: u32, signature: Vec<u8>, data: Vec<u8>) -> Result<bool, Error> {
let handles = HMAC_HANDLES.lock().unwrap();
let al = handles.get(&handle).ok_or(Error::InvalidHandle)?;
let res = match al {
Algorithm::HmacSha1 => verify_hmac!(HMAC_SHA1, HMAC_SHA1, handle, &signature, &data),
Algorithm::HmacSha256 => verify_hmac!(HMAC_SHA256, HMAC_SHA256, handle, &signature, &data),
Algorithm::HmacSha384 => verify_hmac!(HMAC_SHA384, HMAC_SHA384, handle, &signature, &data),
Algorithm::HmacSha512 => verify_hmac!(HMAC_SHA512, HMAC_SHA512, handle, &signature, &data),
};
Ok(res)
}
120 changes: 120 additions & 0 deletions lib/sdk/src/crypto/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
use std::{
collections::HashMap,
sync::{atomic::AtomicU32, Mutex},
};

mod hmac;

lazy_static::lazy_static! {
static ref CTX: Mutex<Context> = Mutex::new(Context::new());
}

#[derive(Debug)]
/// Error is error for crypto
pub enum Error {
/// InvalidHandle means handle is not exist or not match algorithm
InvalidHandle,
/// InvalidAlgorithm is invalid algorithm or not support
InvalidAlgorithm(String),
/// InvalidKey means crypto key is invalid
InvalidKey,
}

impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::InvalidAlgorithm(al) => write!(f, "invalid algorithm: {}", al),
Error::InvalidKey => write!(f, "invalid key"),
Error::InvalidHandle => write!(f, "invalid handle"),
}
}
}

/// Algorithm are algorithms for crypto
#[derive(Debug, Clone, PartialEq)]
pub enum Algorithm {
/// HmacSha1 is hmac-sha1
HmacSha1,
/// HmacSha256 is hmac-sha256
HmacSha256,
/// HmacSha384 is hmac-sha384
HmacSha384,
/// HmacSha512 is hmac-sha512
HmacSha512,
}

impl std::fmt::Display for Algorithm {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Algorithm::HmacSha1 => write!(f, "hmac-sha1"),
Algorithm::HmacSha256 => write!(f, "hmac-sha256"),
Algorithm::HmacSha384 => write!(f, "hmac-sha384"),
Algorithm::HmacSha512 => write!(f, "hmac-sha512"),
}
}
}

struct Context {
handle_seq: AtomicU32,
handles: HashMap<u32, Algorithm>,
}

impl Context {
pub fn new() -> Self {
Self {
handle_seq: AtomicU32::new(1),
handles: HashMap::new(),
}
}
pub fn new_handle(&mut self, al: Algorithm) -> u32 {
let handle = self
.handle_seq
.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
self.handles.insert(handle, al);
handle
}
}

fn convert_algorithm(al: String) -> Result<Algorithm, Error> {
match al.as_str() {
"hmac-sha1" => Ok(Algorithm::HmacSha1),
"hmac-sha256" => Ok(Algorithm::HmacSha256),
"hmac-sha384" => Ok(Algorithm::HmacSha384),
"hmac-sha512" => Ok(Algorithm::HmacSha512),
_ => Err(Error::InvalidAlgorithm(al)),
}
}

/// import_key import crypto key
pub fn import_key(al: String, key: Vec<u8>) -> Result<u32, Error> {
let al = convert_algorithm(al)?;
let handle = CTX.lock().unwrap().new_handle(al.clone());
hmac::new_key(handle, al, &key)?;
Ok(handle)
}

/// sign sign data with handle that index to key
pub fn sign(handle: u32, data: Vec<u8>) -> Result<Vec<u8>, Error> {
let al = CTX.lock().unwrap().handles.get(&handle).unwrap().clone();
if al == Algorithm::HmacSha1
|| al == Algorithm::HmacSha256
|| al == Algorithm::HmacSha384
|| al == Algorithm::HmacSha512
{
return hmac::sign(handle, data);
}
Err(Error::InvalidAlgorithm(al.to_string()))
}

/// verify verify signature with handle that index to key
pub fn verify(handle: u32, signature: Vec<u8>, data: Vec<u8>) -> Result<bool, Error> {
let al = CTX.lock().unwrap().handles.get(&handle).unwrap().clone();
if al == Algorithm::HmacSha1
|| al == Algorithm::HmacSha256
|| al == Algorithm::HmacSha384
|| al == Algorithm::HmacSha512
{
return hmac::verify(handle, signature, data);
}
Err(Error::InvalidAlgorithm(al.to_string()))
}
4 changes: 4 additions & 0 deletions lib/sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,7 @@ pub use execution_ctx::ExecutionCtx;

/// Re-export macro from sdk-macro
pub use land_sdk_macro::http_main;

// #[cfg(feature = "crypto")]
/// Re-export crypto module
pub mod crypto;
1 change: 1 addition & 0 deletions lib/wasm-host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ lazy_static = { workspace = true }
moka = { version = "0.12.8", features = ["sync"] }
once_cell = { workspace = true }
reqwest = { workspace = true }
ring = "0.17.8"
tokio = { workspace = true }
tracing = { workspace = true }
wasmtime = { workspace = true }
Expand Down
5 changes: 5 additions & 0 deletions lib/wasm-host/src/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,15 @@ impl Worker {

// create linker
let mut linker: Linker<crate::context::Context> = Linker::new(&engine);

// init wasi context
wasmtime_wasi::add_to_linker_async(&mut linker)?;

// init http_service
crate::hostcall::HttpService::add_to_linker(&mut linker, crate::context::Context::host_ctx)
.expect("add http_service failed");

// create instance-pre
let instance_pre = linker.instantiate_pre(&component)?;
Ok(Self {
path: path.unwrap_or("binary".to_string()),
Expand All @@ -58,6 +62,7 @@ impl Worker {
let mut linker: Linker<crate::context::Context> = Linker::new(&engine);
// init wasi context
wasmtime_wasi::add_to_linker_async(&mut linker)?;
// init http_service
crate::hostcall::HttpService::add_to_linker(&mut linker, crate::context::Context::host_ctx)
.expect("add http_service failed");

Expand Down

0 comments on commit ae8c484

Please sign in to comment.