-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
293 additions
and
70 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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())) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters