commit ba3d0fea562aff62da265c96c59643a8b76e0524 Author: Hatter Jiang Date: Sat Sep 2 19:37:48 2023 +0800 feat: hmac-sm3 v0.1.0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef862 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target/ +.idea/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..2674306 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,77 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac-sm3" +version = "0.1.0" +dependencies = [ + "hex", + "sm3", +] + +[[package]] +name = "sm3" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebb9a3b702d0a7e33bc4d85a14456633d2b165c2ad839c5fd9a8417c1ab15860" +dependencies = [ + "digest", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a2dc745 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "hmac-sm3" +version = "0.1.0" +edition = "2021" +authors = ["Hatter Jiang"] +repository = "https://git.hatter.ink/hatter/hmac-sm3" +description = "HMAC-SM3 Library" +license = "MIT OR Apache-2.0" +keywords = ["crypto", "hmac", "sm3", "hmac-sm3", "stream"] +categories = ["cryptography"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +sm3 = "0.4.2" + + +[dev-dependencies] +hex = "0.4.3" diff --git a/README.md b/README.md new file mode 100644 index 0000000..29ed84b --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +HMAC-SM3 by `hmac_sm3` + +```rust +let message = b"Hello World"; +let key = b"TestSecret"; + +let hmac1 = hmac_sm3(key, message); +assert_eq!("9d91da552268ddf11b9f69662773a66c6375b250336dfb9293e7e2611c36d79f", hex::encode(hmac1)); +``` + +or use stream style: + +```rust +let mut hm = HmacSm3::new(key); +hm.update(b"Hello"); +hm.update(b" "); +hm.update(b"World"); +let hmac2 = hm.finalize(); +assert_eq!("9d91da552268ddf11b9f69662773a66c6375b250336dfb9293e7e2611c36d79f", hex::encode(hmac2)); +``` + diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..5c51b39 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,92 @@ +use sm3::{Digest, Sm3}; +use sm3::digest::Output; + +const BLOCK_LENGTH: usize = 64; +const SM3_OUTPUT_LENGTH: usize = 32; + +pub struct HmacSm3 { + opad: [u8; BLOCK_LENGTH], + sm3: Sm3, +} + +impl HmacSm3 { + pub fn new(key: &[u8]) -> Self { + let mut structured_key = vec![0_u8; BLOCK_LENGTH]; + if key.len() > BLOCK_LENGTH { + structured_key[0..SM3_OUTPUT_LENGTH].copy_from_slice(sm3_digest(&key).as_slice()); + } else { + structured_key[0..key.len()].copy_from_slice(key); + } + + let mut ipad = [0x36_u8; BLOCK_LENGTH]; + let mut opad = [0x5c_u8; BLOCK_LENGTH]; + for i in 0..BLOCK_LENGTH { + ipad[i] ^= structured_key[i]; + opad[i] ^= structured_key[i]; + } + + let mut sm3 = Sm3::new(); + sm3.update(&ipad); + Self { + opad, + sm3, + } + } + + pub fn update(&mut self, message: &[u8]) { + self.sm3.update(message); + } + + pub fn finalize(&mut self) -> Vec { + let ipad_message_digest = self.sm3.clone().finalize(); + let mut opad_ipad_message_digest = self.opad.to_vec(); + opad_ipad_message_digest.extend_from_slice(ipad_message_digest.as_slice()); + sm3_digest(&opad_ipad_message_digest).as_slice().to_vec() + } +} + +pub fn hmac_sm3(key: &[u8], message: &[u8]) -> Vec { + let mut hsm3 = HmacSm3::new(key); + hsm3.update(message); + hsm3.finalize() +} + +fn sm3_digest(message: &[u8]) -> Output { + let mut sm3 = Sm3::new(); + sm3.update(&message); + sm3.finalize() +} + +#[test] +fn test_001() { + let message = b"Hello World"; + let key = b"TestSecret"; + + let hmac1 = hmac_sm3(key, message); + assert_eq!("9d91da552268ddf11b9f69662773a66c6375b250336dfb9293e7e2611c36d79f", hex::encode(hmac1)); + + let mut hm = HmacSm3::new(key); + hm.update(b"Hello"); + hm.update(b" "); + hm.update(b"World"); + let hmac2 = hm.finalize(); + assert_eq!("9d91da552268ddf11b9f69662773a66c6375b250336dfb9293e7e2611c36d79f", hex::encode(hmac2)); +} + + +#[test] +fn test_002() { + let message = b"Hello World"; + let key = b"TestSecretTestSecretTestSecretTestSecretTestSecretTestSecretTestSecretTestSecretTestSecretTest"; + + let hmac1 = hmac_sm3(key, message); + assert_eq!("ee3a9564211308bd5ca5b428b3de8a2494bb731b55d7169c60907f0e2045649d", hex::encode(hmac1)); + + let mut hm = HmacSm3::new(key); + hm.update(b"Hello"); + hm.update(b" "); + hm.update(b"World"); + let hmac2 = hm.finalize(); + assert_eq!("ee3a9564211308bd5ca5b428b3de8a2494bb731b55d7169c60907f0e2045649d", hex::encode(hmac2)); +} +