├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── lib.rs ├── sm2.rs ├── sm3.rs └── sm4.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "smcrypto" 3 | version = "0.3.1" 4 | edition = "2021" 5 | authors = ["yumeng "] 6 | description = "A Rust Implementation of China's Standards of Encryption Algorithms(SM2/SM3/SM4)" 7 | keywords = ["cipher", "cryptography"] 8 | license = "MIT" 9 | repository = "https://github.com/zhuobie/smcrypto" 10 | 11 | [dependencies] 12 | num-traits = "0.2.14" 13 | num-bigint = "0.4.3" 14 | hex = "0.4.3" 15 | num-integer = "0.1.44" 16 | rand = "0.8.4" 17 | pem = "1.0.2" 18 | base64 = "0.13.0" 19 | yasna = {version = "0.5.0", features = ["num-bigint"]} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Meng Yu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # smcrypto 2 | 3 | A rust implementation of China's standards of encryption algorithms(SM2/SM3/SM4). 4 | 5 | ## Quick Start 6 | 7 | ### SM3 8 | 9 | ``` 10 | let hash = sm3::sm3_hash(b"abc"); 11 | assert_eq!(hash, "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0"); 12 | ``` 13 | 14 | ### SM2 Key Generate 15 | 16 | Note that the public key is in hexadecimal format and does not contain the "04" prefix. 17 | 18 | ``` 19 | let (sk, pk) = sm2::gen_keypair(); 20 | ``` 21 | 22 | ### SM2 Sign/Verify 23 | 24 | ``` 25 | let sign_ctx = sm2::Sign::new(&sk); 26 | let sign = sign_ctx.sign(b"abc"); 27 | let verify_ctx = sm2::Verify::new(&pk); 28 | let verify = verify_ctx.verify(b"abc", &sign); 29 | assert_eq!(verify, true); 30 | ``` 31 | 32 | ### SM2 Encrypt/Decrypt 33 | 34 | ``` 35 | let enc_ctx = sm2::Encrypt::new(&pk); 36 | let enc = enc_ctx.encrypt(b"abc"); 37 | let dec_ctx = sm2::Decrypt::new(&sk); 38 | let dec = dec_ctx.decrypt(&enc); 39 | assert_eq!(String::from_utf8(dec).unwrap(), "abc"); 40 | ``` 41 | 42 | ### SM2 Key Exchange 43 | 44 | ``` 45 | // Step 1 46 | // a side 47 | let ida = b"id_a@company.com"; 48 | let (ska, _) = sm2::gen_keypair(); 49 | let keyexchange_a = sm2::KeyExchange::new(ida, &ska); 50 | let (a2b, rska) = keyexchange_a.keyexchange_1ab(16); 51 | // b side 52 | let idb = b"id_b@company.com"; 53 | let (skb, _) = sm2::gen_keypair(); 54 | let keyexchange_b = sm2::KeyExchange::new(idb, &skb); 55 | let (b2a, rskb) = keyexchange_b.keyexchange_1ab(16); 56 | // Step 2 57 | // a side 58 | let ka = keyexchange_a.keyexchange_2a(&rska, &b2a); 59 | // b side 60 | let kb = keyexchange_b.keyexchange_2b(&rskb, &a2b); 61 | // Step 3 62 | assert_eq!(ka.k, kb.k); 63 | assert_eq!(ka.s12, kb.s12); 64 | ``` 65 | 66 | ### SM4 ECB Encrypt/Decrypt 67 | 68 | ``` 69 | let key = b"1234567812345678"; 70 | let sm4_ecb = sm4::CryptSM4ECB::new(key); 71 | let enc_ecb = sm4_ecb.encrypt_ecb(b"abc"); 72 | let dec_ecb = sm4_ecb.decrypt_ecb(&enc_ecb); 73 | assert_eq!(String::from_utf8(dec_ecb).unwrap(), "abc"); 74 | ``` 75 | 76 | ### SM4 CBC Encrypt/Decrypt 77 | 78 | ``` 79 | let key = b"1234567812345678"; 80 | let iv = b"0000000000000000"; 81 | let sm4_cbc = sm4::CryptSM4CBC::new(key, iv); 82 | let enc_cbc = sm4_cbc.encrypt_cbc(b"abc"); 83 | let dec_cbc = sm4_cbc.decrypt_cbc(&enc_cbc); 84 | assert_eq!(String::from_utf8(dec_cbc).unwrap(), "abc"); 85 | ``` -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A rust implementation of China's standards of encryption algorithms(SM2/SM3/SM4). 2 | //! 3 | //! ## Quick Start 4 | //! 5 | //! ### SM3 6 | //! 7 | //! ``` 8 | //! use smcrypto::sm3; 9 | //! let hash = sm3::sm3_hash(b"abc"); 10 | //! assert_eq!(hash, "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0"); 11 | //! ``` 12 | //! 13 | //! ### SM2 Key Generate 14 | //! 15 | //! Note that the public key is in hexadecimal format and does not contain the "04" prefix. 16 | //! 17 | //! ``` 18 | //! use smcrypto::sm2; 19 | //! let (sk, pk) = sm2::gen_keypair(); 20 | //! ``` 21 | //! 22 | //! ### SM2 Sign/Verify 23 | //! 24 | //! ``` 25 | //! use smcrypto::sm2; 26 | //! let (sk, pk) = sm2::gen_keypair(); 27 | //! let sign_ctx = sm2::Sign::new(&sk); 28 | //! let sign = sign_ctx.sign(b"abc"); 29 | //! let verify_ctx = sm2::Verify::new(&pk); 30 | //! let verify = verify_ctx.verify(b"abc", &sign); 31 | //! assert_eq!(verify, true); 32 | //! ``` 33 | //! 34 | //! ### SM2 Encrypt/Decrypt 35 | //! 36 | //! ``` 37 | //! use smcrypto::sm2; 38 | //! let (sk, pk) = sm2::gen_keypair(); 39 | //! let enc_ctx = sm2::Encrypt::new(&pk); 40 | //! let enc = enc_ctx.encrypt(b"abc"); 41 | //! let dec_ctx = sm2::Decrypt::new(&sk); 42 | //! let dec = dec_ctx.decrypt(&enc); 43 | //! assert_eq!(String::from_utf8(dec).unwrap(), "abc"); 44 | //! ``` 45 | //! 46 | //! ### SM2 Key Exchange 47 | //! 48 | //! ``` 49 | //! use smcrypto::sm2; 50 | //! // Step 1 51 | //! // a side 52 | //! let ida = b"id_a@company.com"; 53 | //! let (ska, _) = sm2::gen_keypair(); 54 | //! let keyexchange_a = sm2::KeyExchange::new(ida, &ska); 55 | //! let (a2b, rska) = keyexchange_a.keyexchange_1ab(16); 56 | //! // b side 57 | //! let idb = b"id_b@company.com"; 58 | //! let (skb, _) = sm2::gen_keypair(); 59 | //! let keyexchange_b = sm2::KeyExchange::new(idb, &skb); 60 | //! let (b2a, rskb) = keyexchange_b.keyexchange_1ab(16); 61 | //! // Step 2 62 | //! // a side 63 | //! let ka = keyexchange_a.keyexchange_2a(&rska, &b2a); 64 | //! // b side 65 | //! let kb = keyexchange_b.keyexchange_2b(&rskb, &a2b); 66 | //! // Step 3 67 | //! assert_eq!(ka.k, kb.k); 68 | //! assert_eq!(ka.s12, kb.s12); 69 | //! ``` 70 | //! 71 | //! ### SM4 ECB Encrypt/Decrypt 72 | //! 73 | //! ``` 74 | //! use smcrypto::sm4; 75 | //! let key = b"1234567812345678"; 76 | //! let sm4_ecb = sm4::CryptSM4ECB::new(key); 77 | //! let enc_ecb = sm4_ecb.encrypt_ecb(b"abc"); 78 | //! let dec_ecb = sm4_ecb.decrypt_ecb(&enc_ecb); 79 | //! assert_eq!(String::from_utf8(dec_ecb).unwrap(), "abc"); 80 | //! ``` 81 | //! 82 | //! ### SM4 CBC Encrypt/Decrypt 83 | //! 84 | //! ``` 85 | //! use smcrypto::sm4; 86 | //! let key = b"1234567812345678"; 87 | //! let iv = b"0000000000000000"; 88 | //! let sm4_cbc = sm4::CryptSM4CBC::new(key, iv); 89 | //! let enc_cbc = sm4_cbc.encrypt_cbc(b"abc"); 90 | //! let dec_cbc = sm4_cbc.decrypt_cbc(&enc_cbc); 91 | //! assert_eq!(String::from_utf8(dec_cbc).unwrap(), "abc"); 92 | //! ``` 93 | 94 | pub mod sm2; 95 | pub mod sm3; 96 | pub mod sm4; -------------------------------------------------------------------------------- /src/sm2.rs: -------------------------------------------------------------------------------- 1 | use crate::sm3::{sm3_hash, sm3_hash_raw}; 2 | use std::vec; 3 | use num_bigint::BigUint; 4 | use num_traits::*; 5 | use num_integer::*; 6 | use rand::seq::SliceRandom; 7 | use std::process::Command; 8 | use std::path::Path; 9 | use std::fs; 10 | use std::borrow::Cow; 11 | 12 | static PARA_LEN: usize = 64; 13 | static ECC_N: &str = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"; 14 | static ECC_P: &str = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"; 15 | static ECC_G: &str = "32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0"; 16 | static ECC_A: &str = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC"; 17 | static ECC_B: &str = "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93"; 18 | 19 | macro_rules! format_hex { 20 | ($a: expr) => { 21 | format!("{:0width$x}", $a, width = PARA_LEN) 22 | }; 23 | 24 | ($a: expr, $b: expr) => { 25 | format!("{:0width$x}{:0width$x}", $a, $b, width = PARA_LEN) 26 | }; 27 | 28 | ($a: expr, $($b: tt)*) => { 29 | format!("{:0width$x}{}", $a, format_hex!($($b)*), width = PARA_LEN) 30 | } 31 | } 32 | 33 | fn submod(a: &BigUint, b: &BigUint, ecc_p: &BigUint) -> BigUint { 34 | if a >= b { 35 | (a - b) % ecc_p 36 | } else { 37 | let d = b - a; 38 | let e = d.div_ceil(ecc_p); 39 | e * ecc_p - d 40 | } 41 | } 42 | 43 | fn random_hex(x: usize) -> String { 44 | let c = vec!["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"]; 45 | let mut s: String = "".to_string(); 46 | for _ in 0..x { 47 | s += *c.choose(&mut rand::thread_rng()).unwrap(); 48 | } 49 | s 50 | } 51 | 52 | fn appendzero(data: &[u8], size: usize) -> Vec { 53 | let mut result = Vec::with_capacity(size); 54 | if data.len() < size { 55 | result.extend(std::iter::repeat(0).take(size - data.len())); 56 | result.extend_from_slice(data); 57 | } else { 58 | result.extend_from_slice(data); 59 | } 60 | result 61 | } 62 | 63 | fn concvec(vec1: &[u8], vec2: &[u8]) -> Vec { 64 | let mut vec1 = vec1.to_vec(); 65 | vec1.extend(vec2); 66 | vec1 67 | } 68 | 69 | macro_rules! concvec { 70 | ($a: expr) => { 71 | $a.to_vec() 72 | }; 73 | 74 | ($a: expr, $b: expr) => { 75 | concvec($a, $b) 76 | }; 77 | 78 | ($a: expr, $($b: tt)*) => { 79 | concvec($a, &concvec!($($b)*)) 80 | } 81 | } 82 | 83 | fn kdf(z: &[u8], klen: usize) -> Vec { 84 | let mut c: Vec = Vec::with_capacity(klen); 85 | let mut ct = 0x00000001u32; 86 | let j: usize = (klen + 31) / 32; 87 | let mut tmp: Vec = Vec::with_capacity(68); 88 | for i in 0..j { 89 | tmp.clear(); 90 | tmp.extend_from_slice(z); 91 | tmp.extend_from_slice(&ct.to_be_bytes()); 92 | let hash = sm3_hash_raw(&tmp); 93 | if i + 1 == j && klen % 32 != 0 { 94 | c.extend_from_slice(&hash[0..(klen % 32)]) 95 | } else { 96 | c.extend_from_slice(&hash) 97 | } 98 | ct += 1; 99 | } 100 | c 101 | } 102 | 103 | fn pubkey2point(public_key: &str) -> Point { 104 | Point { 105 | x: BigUint::from_str_radix(&public_key[0..PARA_LEN], 16).unwrap(), 106 | y: BigUint::from_str_radix(&public_key[PARA_LEN..], 16).unwrap(), 107 | z: BigUint::one() 108 | } 109 | } 110 | 111 | #[derive(Debug, Clone, Eq, PartialEq)] 112 | struct Point { 113 | x: BigUint, 114 | y: BigUint, 115 | z: BigUint 116 | } 117 | 118 | fn double_point(input: Point) -> Point { 119 | let (x1, y1, z1) = (input.x, input.y, input.z); 120 | let ecc_p = BigUint::from_str_radix(ECC_P, 16).unwrap(); 121 | let t6 = (&z1 * &z1) % &ecc_p; 122 | let t2 = (&y1 * &y1) % &ecc_p; 123 | let t3 = (&x1 + &t6) % &ecc_p; 124 | let t4 = submod(&x1, &t6, &ecc_p); 125 | let t1 = (&t3 * &t4) % &ecc_p; 126 | let t3 = (&y1 * &z1) % &ecc_p; 127 | let mut t4 = (&t2 * BigUint::new(vec![8])) % &ecc_p; 128 | let t5 = (&x1 * &t4) % &ecc_p; 129 | let t1 = (&t1 * BigUint::new(vec![3])) % &ecc_p; 130 | let t6 = (&t6 * &t6) % &ecc_p; 131 | let ecc_a3 = BigUint::new(vec![0]); 132 | let t6 = (&ecc_a3 * &t6) % &ecc_p; 133 | let t1 = (&t1 + &t6) % &ecc_p; 134 | let z3 = (&t3 + &t3) % &ecc_p; 135 | let t3 = (&t1 * &t1) % &ecc_p; 136 | let t2 = (&t2 * &t4) % &ecc_p; 137 | let x3 = submod(&t3, &t5, &ecc_p); 138 | if &t5 % BigUint::new(vec![2]) == BigUint::one() { 139 | let tt = &t5 + ((&t5 + &ecc_p) >> 1); 140 | t4 = submod(&tt, &t3, &ecc_p); 141 | } else { 142 | let tt = &t5 + (&t5 >> 1); 143 | t4 = submod(&tt, &t3, &ecc_p); 144 | } 145 | let t1 = (&t1 * &t4) % &ecc_p; 146 | let y3 = submod(&t1, &t2, &ecc_p); 147 | Point { 148 | x: x3, 149 | y: y3, 150 | z: z3 151 | } 152 | } 153 | 154 | fn add_point(p1: Point, p2: Point) -> Point { 155 | let (x1, y1, z1) = (p1.x, p1.y, p1.z); 156 | let (x2, y2) = (p2.x, p2.y); 157 | let ecc_p: BigUint = BigUint::from_str_radix(ECC_P, 16).unwrap(); 158 | let t1: BigUint = (&z1 * &z1) % &ecc_p; 159 | let t2: BigUint = (&y2 * &z1) % &ecc_p; 160 | let t3: BigUint = (&x2 * &t1) % &ecc_p; 161 | let t1: BigUint = (&t1 * &t2) % &ecc_p; 162 | let t2: BigUint = submod(&t3, &x1, &ecc_p); 163 | let t3: BigUint = (&t3 + &x1) % &ecc_p; 164 | let t4: BigUint = (&t2 * &t2) % &ecc_p; 165 | let t1 = submod(&t1, &y1, &ecc_p); 166 | let z3: BigUint = (&z1 * &t2) % &ecc_p; 167 | let t2: BigUint = (&t2 * &t4) % &ecc_p; 168 | let t3: BigUint = (&t3 * &t4) % &ecc_p; 169 | let t5: BigUint = (&t1 * &t1) % &ecc_p; 170 | let t4: BigUint = (&x1 * &t4) % &ecc_p; 171 | let x3: BigUint = submod(&t5, &t3, &ecc_p); 172 | let t2: BigUint = (&y1 * &t2) % &ecc_p; 173 | let t3: BigUint = submod(&t4, &x3, &ecc_p); 174 | let t1: BigUint = (&t1 * &t3) % &ecc_p; 175 | let y3: BigUint = submod(&t1, &t2, &ecc_p); 176 | Point { 177 | x: x3, 178 | y: y3, 179 | z: z3 180 | } 181 | } 182 | 183 | fn convert_jacb_to_nor(point: Point) -> Point { 184 | let ecc_p: BigUint = BigUint::from_str_radix(ECC_P, 16).unwrap(); 185 | let (x, y, z) = (point.x, point.y, point.z); 186 | let z_inv: BigUint = z.modpow(&(&ecc_p - BigUint::new(vec![2])), &ecc_p); 187 | let z_invsquar: BigUint = (&z_inv * &z_inv) % &ecc_p; 188 | let z_invqube: BigUint = (&z_invsquar * &z_inv) % &ecc_p; 189 | let x_new: BigUint = (&x * &z_invsquar) % &ecc_p; 190 | let y_new: BigUint = (&y * &z_invqube) % &ecc_p; 191 | let z_new: BigUint = (&z * &z_inv) % &ecc_p; 192 | if z_new == BigUint::one() { 193 | Point { 194 | x: x_new, 195 | y: y_new, 196 | z: z_new 197 | } 198 | } else { 199 | Point { 200 | x: BigUint::zero(), 201 | y: BigUint::zero(), 202 | z: BigUint::zero() 203 | } 204 | } 205 | } 206 | 207 | fn kg(k: BigUint, point: &str) -> Point { 208 | let mut k = k; 209 | let point: String = point.to_string() + "1"; 210 | let point = Point { 211 | x: BigUint::from_str_radix(&point[0..PARA_LEN], 16).unwrap(), 212 | y: BigUint::from_str_radix(&point[PARA_LEN..(PARA_LEN * 2)], 16).unwrap(), 213 | z: BigUint::from_str_radix(&point[(PARA_LEN * 2)..], 16).unwrap() 214 | }; 215 | let mut mask_str = "8".to_string(); 216 | for _ in 0..((PARA_LEN) - 1) { 217 | mask_str += "0"; 218 | } 219 | let mask: BigUint = BigUint::from_str_radix(&mask_str, 16).unwrap(); 220 | let mut temp = point.clone(); 221 | let mut flag = false; 222 | for _ in 0..(PARA_LEN * 4) { 223 | if flag { 224 | temp = double_point(temp); 225 | } 226 | if &k & &mask != BigUint::zero() { 227 | if flag { 228 | temp = add_point(temp, point.clone()); 229 | } else { 230 | flag = true; 231 | temp = point.clone(); 232 | } 233 | } 234 | k = k << 1; 235 | } 236 | convert_jacb_to_nor(temp) 237 | } 238 | 239 | /// Check whether the private key is legal. 240 | pub fn privkey_valid(private_key: &str) -> bool { 241 | hex_valid(private_key) && private_key.len() == 64 242 | } 243 | 244 | /// Check whether the public key is legal. The input public key may or may not contain the "04" prefix. 245 | 246 | pub fn pubkey_valid(public_key: &str) -> bool { 247 | let public_key_len = public_key.len(); 248 | if public_key_len != 128 && public_key_len != 130 { 249 | return false; 250 | } 251 | if public_key_len == 130 && &public_key[0..2] != "04" { 252 | return false; 253 | } 254 | let public_key = pubkey_trim(public_key); 255 | if !hex_valid(&public_key) { 256 | return false; 257 | } 258 | let x: &str = &public_key[0..64]; 259 | let y: &str = &public_key[64..128]; 260 | let x = BigUint::from_str_radix(x, 16).unwrap(); 261 | let y = BigUint::from_str_radix(y, 16).unwrap(); 262 | let a = BigUint::from_str_radix(ECC_A, 16).unwrap(); 263 | let b = BigUint::from_str_radix(ECC_B, 16).unwrap(); 264 | let p = BigUint::from_str_radix(ECC_P, 16).unwrap(); 265 | let np0 = kg(BigUint::from_str_radix(ECC_N, 16).unwrap(), &public_key) == Point {x: BigUint::zero(), y: BigUint::zero(), z: BigUint::zero()}; 266 | let on_curve = (&y * &y) % &p == (&x * &x * &x + &a * &x + &b) % &p; 267 | np0 && on_curve 268 | } 269 | 270 | /// Check whether a hex string is legal. 271 | pub fn hex_valid(input: &str) -> bool { 272 | let hex_chars: Vec = vec![ 273 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 274 | 'a', 'b', 'c', 'd', 'e', 'f', 275 | 'A', 'B', 'C', 'D', 'E', 'F' 276 | ]; 277 | let input_chars: Vec = input.chars().collect(); 278 | let is_even = input_chars.len() % 2 == 0; 279 | let all_in_hex = input_chars.iter().map(|x| hex_chars.contains(&x)).into_iter().all(|x| x); 280 | is_even && all_in_hex 281 | } 282 | 283 | /// Check whether a base64 string is legal. 284 | pub fn base64_valid(input: &str) -> bool { 285 | match base64::decode(input) { 286 | Ok(_) => true, 287 | Err(_) => false, 288 | } 289 | } 290 | 291 | fn pubkey_trim<'a>(public_key: &'a str) -> Cow<'a, str> { 292 | if public_key.len() == 130 && &public_key[0..2] == "04" { 293 | Cow::Borrowed(&public_key[2..]) 294 | } else { 295 | Cow::Borrowed(public_key) 296 | } 297 | } 298 | 299 | fn keypair_from_pem_bytes(pem_bytes: Vec) -> (String, String) { 300 | let pem_try = pem::parse(pem_bytes); 301 | let pem: pem::Pem; 302 | match pem_try { 303 | Ok(v) => { 304 | pem = v; 305 | } 306 | Err(_) => { 307 | return ("".to_string(), "".to_string()); 308 | } 309 | } 310 | let keyfield = pem.contents; 311 | let priv_key = hex::encode(&keyfield[36..68]); 312 | let pub_key = hex::encode(&keyfield[74..138]); 313 | let pub_key = if !pubkey_valid(&pub_key) && &pub_key[0..2] == "04" { 314 | hex::encode(&keyfield[75..139]) 315 | } else { 316 | pub_key 317 | }; 318 | (priv_key, pub_key) 319 | } 320 | 321 | /// Export private/public key from pem file. The pem file should be in pkcs8 format and unencryped. 322 | 323 | pub fn keypair_from_pem_file(pem_file: &str) -> (String, String) { 324 | let pem_file_path = Path::new(pem_file); 325 | let pem_bytes = fs::read(pem_file_path).unwrap(); 326 | keypair_from_pem_bytes(pem_bytes) 327 | } 328 | 329 | fn pubkey_from_pem_bytes(pem_bytes: Vec) -> String { 330 | // let pem = pem::parse(pem_bytes).unwrap(); 331 | let pem: pem::Pem; 332 | if let Ok(v) = pem::parse(pem_bytes) { 333 | pem = v; 334 | } else { 335 | return "".to_string(); 336 | } 337 | let keyfield = pem.contents; 338 | let pub_key = hex::encode(&keyfield[27..91]); 339 | pub_key 340 | } 341 | 342 | /// Export public key from pem file. The pem file should be in pkcs8 format and unencrypted. 343 | 344 | pub fn pubkey_from_pem_file(pem_file: &str) -> String { 345 | let pem_file_path = Path::new(pem_file); 346 | let pem_bytes = fs::read(pem_file_path).unwrap(); 347 | pubkey_from_pem_bytes(pem_bytes) 348 | } 349 | 350 | fn keypair_to_pem_bytes(private_key: &str) -> Vec { 351 | let public_key = pk_from_sk(private_key); 352 | let pem = "308187020100301306072a8648ce3d020106082a811ccf5501822d046d306b0201010420".to_string() + private_key + "a14403420004" + &public_key; 353 | let pem = hex::decode(pem).unwrap(); 354 | let pem = base64::encode(pem); 355 | let pem = "-----BEGIN PRIVATE KEY-----".to_string() + "\n" + &pem[0..64] + "\n" + &pem[64..128] + "\n" + &pem[128..] + "\n-----END PRIVATE KEY-----\n"; 356 | pem.into_bytes() 357 | } 358 | 359 | /// Dump the keypair from a private key to a pem file in unencryped pkcs8 format. 360 | 361 | pub fn keypair_to_pem_file(private_key: &str, pem_file: &str) { 362 | let output_file = Path::new(pem_file); 363 | let pem_bytes = keypair_to_pem_bytes(private_key); 364 | fs::write(output_file, &pem_bytes[..]).unwrap(); 365 | } 366 | 367 | fn pubkey_to_pem_bytes(public_key: &str) -> Vec { 368 | let public_key = pubkey_trim(public_key); 369 | let pem = "3059301306072a8648ce3d020106082a811ccf5501822d03420004".to_string() + &public_key; 370 | let pem = hex::decode(pem).unwrap(); 371 | let pem = base64::encode(pem); 372 | let pem = "-----BEGIN PUBLIC KEY-----".to_string() + "\n" + &pem[0..64] + "\n" + &pem[64..] + "\n-----END PUBLIC KEY-----\n"; 373 | pem.into_bytes() 374 | } 375 | 376 | /// Dump the public key to a pem file in unencryped pkcs8 format. 377 | 378 | pub fn pubkey_to_pem_file(public_key: &str, pem_file: &str) { 379 | let output_file = Path::new(pem_file); 380 | let pem_bytes = pubkey_to_pem_bytes(public_key); 381 | fs::write(output_file, &pem_bytes[..]).unwrap(); 382 | } 383 | 384 | /// A keypair can be generated by openssl. The `openssl` executable file must be in system PATH. Currently openssl 1.1.1 is supported. 385 | 386 | pub fn gen_keypair_openssl() -> (String, String) { 387 | let output = if cfg!(target_os = "windows") { 388 | Command::new("cmd").args(["/C", "openssl ecparam -genkey -name SM2 | openssl pkcs8 -topk8 -inform PEM -outform pem -nocrypt"]).output().expect("openssl generate faild.") 389 | } else { 390 | Command::new("sh").arg("-c").arg("openssl ecparam -genkey -name SM2 | openssl pkcs8 -topk8 -inform PEM -outform pem -nocrypt").output().expect("openssl generate faild.") 391 | }; 392 | let output = output.stdout; 393 | keypair_from_pem_bytes(output) 394 | } 395 | 396 | pub fn gen_keypair() -> (String, String) { 397 | let d = random_hex(PARA_LEN); 398 | let pa = kg(BigUint::from_str_radix(&d, 16).unwrap(), ECC_G); 399 | let pa = format_hex!(pa.x, pa.y); 400 | (d, pa) 401 | } 402 | 403 | /// Calculate public key from a private key. 404 | 405 | pub fn pk_from_sk(private_key: &str) -> String { 406 | let p = kg(BigUint::from_str_radix(private_key, 16).unwrap(), ECC_G); 407 | format_hex!(p.x, p.y) 408 | } 409 | 410 | fn sign_raw(data: &[u8], private_key: &str) -> Vec { 411 | let e = BigUint::from_bytes_be(data); 412 | let d = BigUint::from_str_radix(private_key, 16).unwrap(); 413 | let k = random_hex(PARA_LEN); 414 | let k = BigUint::from_str_radix(&k, 16).unwrap(); 415 | let k1 = k.clone(); 416 | let p1 = kg(k, ECC_G); 417 | let r = (e + p1.x) % BigUint::from_str_radix(ECC_N, 16).unwrap(); 418 | if r == BigUint::zero() || &r + &k1 == BigUint::from_str_radix(ECC_N, 16).unwrap() { 419 | vec![] 420 | } else { 421 | let d_1: BigUint = (&d + BigUint::one()).modpow(&(BigUint::from_str_radix(ECC_N, 16).unwrap() - BigUint::new(vec![2])), &BigUint::from_str_radix(ECC_N, 16).unwrap()); 422 | let s: BigUint = (&d_1 * (&k1 + &r) - &r) % BigUint::from_str_radix(ECC_N, 16).unwrap(); 423 | if s == BigUint::zero() { 424 | vec![] 425 | } else { 426 | yasna::construct_der(|writer| { 427 | writer.write_sequence(|writer| { 428 | writer.next().write_biguint(&r); 429 | writer.next().write_biguint(&s); 430 | }); 431 | }) 432 | } 433 | } 434 | } 435 | 436 | fn verify_raw(data: &[u8], sign: &[u8], public_key: &str) -> bool { 437 | let rs = yasna::parse_der(sign, |reader| { 438 | reader.read_sequence(|reader| { 439 | let r = reader.next().read_biguint()?; 440 | let s = reader.next().read_biguint()?; 441 | return Ok((r, s)); 442 | }) 443 | }); 444 | let r: BigUint; 445 | let s: BigUint; 446 | match rs { 447 | Ok(v) => { 448 | r = v.0; 449 | s = v.1; 450 | } 451 | Err(_) => { 452 | return false; 453 | } 454 | } 455 | let r1 = r.clone(); 456 | let s1 = s.clone(); 457 | let e = BigUint::from_bytes_be(data); 458 | let t = (r + s) % BigUint::from_str_radix(ECC_N, 16).unwrap(); 459 | let t1 = t.clone(); 460 | if t == BigUint::zero() { 461 | false 462 | } else { 463 | let mut p1 = kg(s1, ECC_G); 464 | let p2 = kg(t1, public_key); 465 | if p1 == p2 { 466 | p1 = double_point(p1); 467 | } else { 468 | p1 = add_point(p1, p2); 469 | p1 = convert_jacb_to_nor(p1); 470 | } 471 | let x = p1.x; 472 | r1 == (&e + &x) % BigUint::from_str_radix(ECC_N, 16).unwrap() 473 | } 474 | } 475 | 476 | fn sign(id: &[u8], data: &[u8], private_key: &str) -> Vec { 477 | let public_key = pk_from_sk(private_key); 478 | let m_bar = concvec(&hex::decode(zab(&public_key, id)).unwrap(), data); 479 | let e = hex::decode(sm3_hash(&m_bar)).unwrap(); 480 | sign_raw(&e, private_key) 481 | } 482 | 483 | fn verify(id: &[u8], data: &[u8], sign: &[u8], public_key: &str) -> bool { 484 | let m_bar = concvec(&hex::decode(zab(&public_key, id)).unwrap(), data); 485 | let e = hex::decode(sm3_hash(&m_bar)).unwrap(); 486 | verify_raw(&e, sign, public_key) 487 | } 488 | 489 | fn sign_to_file(id: &[u8], data: &[u8], sign_file: &str, private_key: &str) { 490 | let sign_file = Path::new(sign_file); 491 | let sign_data = sign(id, data, private_key); 492 | fs::write(sign_file, &sign_data[..]).unwrap(); 493 | } 494 | 495 | fn verify_from_file(id: &[u8], data: &[u8], sign_file: &str, public_key: &str) -> bool { 496 | let sign_file = Path::new(sign_file); 497 | let sign_data = fs::read(sign_file).unwrap(); 498 | verify(id, data, &sign_data, public_key) 499 | } 500 | 501 | fn encrypt(data: &[u8], public_key: &str) -> Vec { 502 | let k = random_hex(PARA_LEN); 503 | let c1xyz = kg(BigUint::from_str_radix(k.as_str(), 16).unwrap(), ECC_G); 504 | let c1x = appendzero(&BigUint::to_bytes_be(&c1xyz.x), PARA_LEN / 2); 505 | let c1y = appendzero(&BigUint::to_bytes_be(&c1xyz.y), PARA_LEN / 2); 506 | let c1 = concvec(&c1x, &c1y); 507 | let xy = kg(BigUint::from_str_radix(k.as_str(), 16).unwrap(), public_key); 508 | let x2 = BigUint::to_bytes_be(&xy.x); 509 | let y2 = BigUint::to_bytes_be(&xy.y); 510 | let x2 = appendzero(&x2, PARA_LEN / 2); 511 | let y2 = appendzero(&y2, PARA_LEN / 2); 512 | let xy = concvec(&x2, &y2); 513 | let t = kdf(&xy, data.len()); 514 | let cipher = if BigUint::from_bytes_be(&t) == BigUint::zero() { 515 | b"".to_vec() 516 | } else { 517 | let c2 = BigUint::from_bytes_be(&data) ^ BigUint::from_bytes_be(&t); 518 | let c2 = BigUint::to_bytes_be(&c2); 519 | let c2 = appendzero(&c2, data.len()); 520 | let h = concvec!(&x2, data, &y2); 521 | let c3 = sm3_hash(&h); 522 | let c3 = hex::decode(c3).unwrap(); 523 | let cipher = concvec!(&c1, &c3, &c2); 524 | cipher 525 | }; 526 | cipher 527 | } 528 | 529 | fn decrypt(data: &[u8], private_key: &str) -> Vec { 530 | let c1 = &data[0..64]; 531 | let c2 = &data[96..]; 532 | let xy = kg(BigUint::from_str_radix(private_key, 16).unwrap(), &hex::encode(c1)); 533 | let x = appendzero(&BigUint::to_bytes_be(&xy.x), 32); 534 | let y = appendzero(&BigUint::to_bytes_be(&xy.y), 32); 535 | let xy = concvec(&x, &y); 536 | let t = kdf(&xy, c2.len()); 537 | let result = if BigUint::from_bytes_be(&t) == BigUint::zero() { 538 | vec![] 539 | } else { 540 | BigUint::to_bytes_be(&(BigUint::from_bytes_be(&c2) ^ BigUint::from_bytes_be(&t))) 541 | }; 542 | result 543 | } 544 | 545 | fn encrypt_c1c2c3(data: &[u8], public_key: &str) -> Vec { 546 | let cipher_c1c3c2 = encrypt(data, public_key); 547 | let c1 = &cipher_c1c3c2[0..64]; 548 | let c3 = &cipher_c1c3c2[64..96]; 549 | let c2 = &cipher_c1c3c2[96..]; 550 | concvec!(c1, c2, c3) 551 | } 552 | 553 | fn decrypt_c1c2c3(data: &[u8], private_key: &str) -> Vec { 554 | let c1 = &data[0..64]; 555 | let c2 = &data[64..(data.len() - 32)]; 556 | let c3 = &data[(data.len() - 32)..]; 557 | let cipher_c1c3c2 = concvec!(c1, c3, c2); 558 | decrypt(&cipher_c1c3c2, private_key) 559 | } 560 | 561 | fn encrypt_asna1(data: &[u8], public_key: &str) -> Vec { 562 | let cipher = encrypt(data, public_key); 563 | let x = BigUint::from_bytes_be(&cipher[0..32]); 564 | let y = BigUint::from_bytes_be(&cipher[32..64]); 565 | let sm3 = &cipher[64..96]; 566 | let secret = &cipher[96..]; 567 | yasna::construct_der(|writer| { 568 | writer.write_sequence(|writer| { 569 | writer.next().write_biguint(&x); 570 | writer.next().write_biguint(&y); 571 | writer.next().write_bytes(&sm3); 572 | writer.next().write_bytes(&secret); 573 | }); 574 | }) 575 | } 576 | 577 | fn decrypt_asna1(data: &[u8], private_key: &str) -> Vec { 578 | let (x, y, sm3, secret) = yasna::parse_der(data, |reader| { 579 | reader.read_sequence(|reader| { 580 | let x = reader.next().read_biguint()?; 581 | let y = reader.next().read_biguint()?; 582 | let sm3 = reader.next().read_bytes()?; 583 | let secret = reader.next().read_bytes()?; 584 | return Ok((x, y, sm3, secret)); 585 | }) 586 | }).unwrap(); 587 | let x = BigUint::to_bytes_be(&x); 588 | let y = BigUint::to_bytes_be(&y); 589 | let x = appendzero(&x, 32); 590 | let y = appendzero(&y, 32); 591 | let cipher = concvec!(&x, &y, &sm3, &secret); 592 | decrypt(&cipher, private_key) 593 | } 594 | 595 | fn encrypt_hex(data: &[u8], public_key: &str) -> String { 596 | hex::encode(encrypt(data, public_key)) 597 | } 598 | 599 | fn decrypt_hex(data: &str, private_key: &str) -> Vec { 600 | decrypt(&hex::decode(data).unwrap(), private_key) 601 | } 602 | 603 | fn encrypt_base64(data: &[u8], public_key: &str) -> String { 604 | base64::encode(encrypt(data, public_key)) 605 | } 606 | 607 | fn decrypt_base64(data: &str, private_key: &str) -> Vec { 608 | // decrypt(&base64::decode(data).unwrap(), private_key) 609 | if let Ok(v) = base64::decode(data) { 610 | decrypt(&v, private_key) 611 | } else { 612 | vec![] 613 | } 614 | } 615 | 616 | fn encrypt_to_file(data: &[u8], enc_file: &str, public_key: &str) { 617 | let enc_file = Path::new(enc_file); 618 | let enc_data = encrypt_asna1(data, public_key); 619 | fs::write(enc_file, &enc_data[..]).unwrap(); 620 | } 621 | 622 | fn decrypt_from_file(enc_file: &str, private_key: &str) -> Vec { 623 | let enc_file = Path::new(enc_file); 624 | let enc_data = fs::read(enc_file).unwrap(); 625 | decrypt_asna1(&enc_data, private_key) 626 | } 627 | 628 | fn kexhat(x: BigUint) -> BigUint { 629 | let w_2: Vec = [0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00].to_vec(); 630 | let w_2 = BigUint::from_bytes_be(&w_2); 631 | &w_2 + (&x & (&w_2 - BigUint::new(vec![1]))) 632 | } 633 | 634 | fn zab(public_key: &str, uid: &[u8]) -> String { 635 | let entla: usize = 8 * uid.len(); 636 | let za = concvec!( 637 | &vec![((entla >> 8) & 0xFF) as u8, (entla & 0xFF) as u8], 638 | uid, 639 | &hex::decode(ECC_A).unwrap(), 640 | &hex::decode(ECC_B).unwrap(), 641 | &hex::decode(ECC_G).unwrap(), 642 | &hex::decode(public_key).unwrap() 643 | ); 644 | sm3_hash(&za) 645 | } 646 | 647 | pub struct KeyExchangeResult { 648 | pub k: String, 649 | pub s12: Vec 650 | } 651 | 652 | fn keyexchange_raw(klen: usize, ida: &[u8], idb: &[u8], private_key: &str, public_key: &str, r_private_key: &str, r_public_key: &str, is_a: bool) -> KeyExchangeResult { 653 | let x2hat = kexhat(BigUint::from_str_radix(&pk_from_sk(r_private_key)[0..64], 16).unwrap()); 654 | let x2rb = x2hat * BigUint::from_str_radix(r_private_key, 16).unwrap(); 655 | let tbt = BigUint::from_str_radix(private_key, 16).unwrap() + x2rb; 656 | let tb = tbt % BigUint::from_str_radix(ECC_N, 16).unwrap(); 657 | assert_eq!(pubkey_valid(r_public_key), true); 658 | let x1hat = kexhat(BigUint::from_str_radix(&r_public_key[0..64], 16).unwrap()); 659 | let kx1y1 = kg(x1hat, &r_public_key); 660 | let vxyt = add_point(pubkey2point(public_key), kx1y1); 661 | let vxyt = convert_jacb_to_nor(vxyt); 662 | let vxyt = format_hex!(vxyt.x, vxyt.y); 663 | let vxy = kg(tb, &vxyt); 664 | let vx = vxy.x; 665 | let vy = vxy.y; 666 | let pza = if is_a { 667 | pk_from_sk(private_key) 668 | } else { 669 | public_key.to_string() 670 | }; 671 | let za = zab(&pza, ida); 672 | assert_eq!(vx == BigUint::zero() || vy == BigUint::zero(), false); 673 | let pzb = if !is_a { 674 | pk_from_sk(private_key) 675 | } else { 676 | public_key.to_string() 677 | }; 678 | let zb = zab(&pzb, idb); 679 | let z = concvec!( 680 | &vx.to_bytes_be(), 681 | &vy.to_bytes_be(), 682 | &hex::decode(&za).unwrap(), 683 | &hex::decode(&zb).unwrap() 684 | ); 685 | let z = hex::encode(&z).into_bytes(); 686 | let h1 = if !is_a { 687 | concvec!( 688 | &BigUint::to_bytes_be(&vx), 689 | &za.into_bytes(), 690 | &zb.into_bytes(), 691 | &BigUint::to_bytes_be(&BigUint::from_str_radix(&pk_from_sk(&r_private_key)[0..64], 16).unwrap()), 692 | &BigUint::to_bytes_be(&BigUint::from_str_radix(&pk_from_sk(&r_private_key)[64..], 16).unwrap()), 693 | &BigUint::to_bytes_be(&BigUint::from_str_radix(&r_public_key[0..64], 16).unwrap()), 694 | &BigUint::to_bytes_be(&BigUint::from_str_radix(&r_public_key[64..], 16).unwrap()) 695 | ) 696 | } else { 697 | concvec!( 698 | &BigUint::to_bytes_be(&vx), 699 | &za.into_bytes(), 700 | &zb.into_bytes(), 701 | &BigUint::to_bytes_be(&BigUint::from_str_radix(&r_public_key[0..64], 16).unwrap()), 702 | &BigUint::to_bytes_be(&BigUint::from_str_radix(&r_public_key[64..], 16).unwrap()), 703 | &BigUint::to_bytes_be(&BigUint::from_str_radix(&pk_from_sk(&r_private_key)[0..64], 16).unwrap()), 704 | &BigUint::to_bytes_be(&BigUint::from_str_radix(&pk_from_sk(&r_private_key)[64..], 16).unwrap()) 705 | ) 706 | }; 707 | let hash = sm3_hash(&h1); 708 | let h2 = concvec!( 709 | &hex::decode("02").unwrap(), 710 | &BigUint::to_bytes_be(&vy), 711 | &hex::decode(&hash).unwrap() 712 | ); 713 | let s1 = sm3_hash(&h2); 714 | let h3 = concvec!( 715 | &hex::decode("03").unwrap(), 716 | &BigUint::to_bytes_be(&vy), 717 | &hex::decode(&hash).unwrap() 718 | ); 719 | let s2 = sm3_hash(&h3); 720 | KeyExchangeResult { 721 | k: hex::encode(kdf(&z, klen)), 722 | s12: yasna::construct_der(|writer| { 723 | writer.write_sequence(|writer| { 724 | writer.next().write_bytes(&s1.into_bytes()); 725 | writer.next().write_bytes(&s2.into_bytes()); 726 | }); 727 | }) 728 | } 729 | } 730 | 731 | fn keyexchange_a(klen: usize, ida: &[u8], idb: &[u8], private_key_a: &str, public_key_b: &str, private_key_ar: &str, public_key_br: &str) -> KeyExchangeResult { 732 | keyexchange_raw(klen, ida, idb, private_key_a, public_key_b, private_key_ar, public_key_br, true) 733 | } 734 | 735 | fn keyexchange_b(klen: usize, idb: &[u8], ida: &[u8], private_key_b: &str, public_key_a: &str, private_key_br: &str, public_key_ar: &str) -> KeyExchangeResult { 736 | keyexchange_raw(klen, ida, idb, private_key_b, public_key_a, private_key_br, public_key_ar, false) 737 | } 738 | 739 | fn keyexchange_1ab(klen: usize, id: &[u8], private_key: &str) -> (Vec, String) { 740 | let public_key = pk_from_sk(private_key); 741 | let (private_key_r, public_key_r) = gen_keypair(); 742 | ( 743 | yasna::construct_der(|writer| { 744 | writer.write_sequence(|writer| { 745 | writer.next().write_u32(klen as u32); 746 | writer.next().write_bytes(id); 747 | writer.next().write_bytes(&public_key.into_bytes()); 748 | writer.next().write_bytes(&public_key_r.into_bytes()); 749 | }); 750 | }), 751 | private_key_r 752 | ) 753 | } 754 | 755 | fn keyexchange_2a(id: &[u8], private_key: &str, private_key_r: &str, recive_bytes: &[u8]) -> KeyExchangeResult { 756 | let klenidbpkpkr = yasna::parse_der(recive_bytes, |reader| { 757 | reader.read_sequence(|reader| { 758 | let klen = reader.next().read_u32()?; 759 | let idb = reader.next().read_bytes()?; 760 | let public_key = reader.next().read_bytes()?; 761 | let public_key_r = reader.next().read_bytes()?; 762 | return Ok((klen, idb, public_key, public_key_r)); 763 | }) 764 | }); 765 | let klen: u32; 766 | let idb: Vec; 767 | let public_key: Vec; 768 | let public_key_r: Vec; 769 | match klenidbpkpkr { 770 | Ok(v) => { 771 | klen = v.0; 772 | idb = v.1; 773 | public_key = v.2; 774 | public_key_r = v.3; 775 | } 776 | Err(_) => { 777 | return KeyExchangeResult { 778 | k: "".to_string(), 779 | s12: vec![], 780 | }; 781 | } 782 | } 783 | let klen = klen as usize; 784 | let public_key = std::str::from_utf8(&public_key).unwrap(); 785 | let public_key_r = std::str::from_utf8(&public_key_r).unwrap(); 786 | keyexchange_a(klen, id, &idb, private_key, public_key, private_key_r, public_key_r) 787 | } 788 | 789 | fn keyexchange_2b(id: &[u8], private_key: &str, private_key_r: &str, recive_bytes: &[u8]) -> KeyExchangeResult { 790 | let klenidapkpkr = yasna::parse_der(recive_bytes, |reader| { 791 | reader.read_sequence(|reader| { 792 | let klen = reader.next().read_u32()?; 793 | let idb = reader.next().read_bytes()?; 794 | let public_key = reader.next().read_bytes()?; 795 | let public_key_r = reader.next().read_bytes()?; 796 | return Ok((klen, idb, public_key, public_key_r)); 797 | }) 798 | }); 799 | let klen: u32; 800 | let ida: Vec; 801 | let public_key: Vec; 802 | let public_key_r: Vec; 803 | match klenidapkpkr { 804 | Ok(v) => { 805 | klen = v.0; 806 | ida = v.1; 807 | public_key = v.2; 808 | public_key_r = v.3; 809 | } 810 | Err(_) => { 811 | return KeyExchangeResult { 812 | k: "".to_string(), 813 | s12: vec![], 814 | }; 815 | } 816 | } 817 | let klen = klen as usize; 818 | let public_key = std::str::from_utf8(&public_key).unwrap(); 819 | let public_key_r = std::str::from_utf8(&public_key_r).unwrap(); 820 | keyexchange_b(klen, id, &ida, private_key, public_key, private_key_r, public_key_r) 821 | } 822 | 823 | pub struct Sign<'a> { 824 | pub id: &'a [u8], 825 | pub private_key: &'a str 826 | } 827 | 828 | impl<'a> Default for Sign<'a> { 829 | fn default() -> Self { 830 | Sign {id: b"1234567812345678", private_key: ""} 831 | } 832 | } 833 | 834 | impl<'a> Sign<'a> { 835 | /// Initialize a sm2 sign instance with default id b"1234567812345678". 836 | pub fn new(private_key: &'a str) -> Self { 837 | Sign {private_key: private_key, ..Sign::default()} 838 | } 839 | 840 | /// Initialize a sm2 sign instance with a custom id. 841 | pub fn new_with_id(id: &'a [u8], private_key: &'a str) -> Self { 842 | Sign {id: id, private_key: private_key} 843 | } 844 | 845 | /// Sign with sm3. 846 | pub fn sign(&self, data: &[u8]) -> Vec { 847 | sign(self.id, data, self.private_key) 848 | } 849 | 850 | /// Sign without sm3. 851 | pub fn sign_raw(&self, data: &[u8]) -> Vec { 852 | sign_raw(data, self.private_key) 853 | } 854 | 855 | pub fn sign_to_file(&self, data: &[u8], sign_file: &str) { 856 | sign_to_file(self.id, data, sign_file, self.private_key) 857 | } 858 | } 859 | 860 | pub struct Verify<'a> { 861 | pub id: &'a [u8], 862 | pub public_key: Cow<'a, str> 863 | } 864 | 865 | impl<'a> Default for Verify<'a> { 866 | fn default() -> Self { 867 | Verify {id: b"1234567812345678", public_key: Cow::Borrowed("")} 868 | } 869 | } 870 | 871 | impl<'a> Verify<'a> { 872 | /// Initialize a sm2 verify instance with default id b"1234567812345678". 873 | pub fn new(public_key: &'a str) -> Self { 874 | let public_key = pubkey_trim(public_key); 875 | Verify{public_key: public_key, ..Verify::default()} 876 | } 877 | 878 | /// Initialize a sm2 verify instance with a custom id. 879 | pub fn new_with_id(id: &'a [u8], public_key: &'a str) -> Self { 880 | Verify {id: id, public_key: Cow::Borrowed(public_key)} 881 | } 882 | 883 | /// Verify with sm3. 884 | pub fn verify(&self, data: &[u8], sign: &[u8]) -> bool { 885 | verify(self.id, data, sign, &self.public_key) 886 | } 887 | 888 | /// Verify without sm3. 889 | pub fn verify_raw(&self, data: &[u8], sign: &[u8]) -> bool { 890 | verify_raw(data, sign, &self.public_key) 891 | } 892 | 893 | pub fn verify_from_file(&self, data: &[u8], sign_file: &str) -> bool { 894 | verify_from_file(self.id, data, sign_file, &self.public_key) 895 | } 896 | } 897 | 898 | pub struct Encrypt<'a> { 899 | pub public_key: Cow<'a, str> 900 | } 901 | 902 | impl<'a> Encrypt<'a> { 903 | pub fn new(public_key: &'a str) -> Self { 904 | let public_key = pubkey_trim(public_key); 905 | Encrypt{public_key: public_key} 906 | } 907 | 908 | pub fn encrypt(&self, data: &[u8]) -> Vec { 909 | encrypt(data, &self.public_key) 910 | } 911 | 912 | pub fn encrypt_c1c2c3(&self, data: &[u8]) -> Vec { 913 | encrypt_c1c2c3(data, &self.public_key) 914 | } 915 | 916 | pub fn encrypt_asna1(&self, data: &[u8]) -> Vec { 917 | encrypt_asna1(data, &self.public_key) 918 | } 919 | 920 | pub fn encrypt_hex(&self, data: &[u8]) -> String { 921 | encrypt_hex(data, &self.public_key) 922 | } 923 | 924 | pub fn encrypt_base64(&self, data: &[u8]) -> String { 925 | encrypt_base64(data, &self.public_key) 926 | } 927 | 928 | pub fn encrypt_to_file(&self, data: &[u8], enc_file: &str) { 929 | encrypt_to_file(data, enc_file, &self.public_key) 930 | } 931 | } 932 | 933 | pub struct Decrypt<'a> { 934 | pub private_key: &'a str 935 | } 936 | 937 | impl<'a> Decrypt<'a> { 938 | pub fn new(private_key: &'a str) -> Self { 939 | Decrypt{private_key: private_key} 940 | } 941 | 942 | pub fn decrypt(&self, data: &[u8]) -> Vec { 943 | decrypt(data, self.private_key) 944 | } 945 | 946 | pub fn decrypt_c1c2c3(&self, data: &[u8]) -> Vec { 947 | decrypt_c1c2c3(data, self.private_key) 948 | } 949 | 950 | pub fn decrypt_asna1(&self, data: &[u8]) -> Vec { 951 | decrypt_asna1(data, self.private_key) 952 | } 953 | 954 | pub fn decrypt_hex(&self, data: &str) -> Vec { 955 | decrypt_hex(data, self.private_key) 956 | } 957 | 958 | pub fn decrypt_base64(&self, data: &str) -> Vec { 959 | decrypt_base64(data, self.private_key) 960 | } 961 | 962 | pub fn decrypt_from_file(&self, enc_file: &str) -> Vec { 963 | decrypt_from_file(enc_file, self.private_key) 964 | } 965 | } 966 | 967 | pub struct KeyExchange<'a> { 968 | pub id: &'a [u8], 969 | pub private_key: &'a str 970 | } 971 | 972 | impl<'a> KeyExchange<'a> { 973 | pub fn new(id: &'a [u8], private_key: &'a str) -> Self { 974 | KeyExchange{id: id, private_key: private_key} 975 | } 976 | 977 | /// klen is the length of key to generate. 978 | pub fn keyexchange_1ab(&self, klen: usize) -> (Vec, String) { 979 | keyexchange_1ab(klen, self.id, self.private_key) 980 | } 981 | 982 | pub fn keyexchange_2a(&self, private_key_r: &str, recive_bytes: &[u8]) -> KeyExchangeResult { 983 | keyexchange_2a(self.id, self.private_key, private_key_r, recive_bytes) 984 | } 985 | 986 | pub fn keyexchange_2b(&self, private_key_r: &str, recive_bytes: &[u8]) -> KeyExchangeResult { 987 | keyexchange_2b(self.id, self.private_key, private_key_r, recive_bytes) 988 | } 989 | } -------------------------------------------------------------------------------- /src/sm3.rs: -------------------------------------------------------------------------------- 1 | use std::vec; 2 | 3 | fn sm3_ff_j(x: u32, y: u32, z: u32, j: u32) -> u32 { 4 | let mut ret = 0; 5 | if j < 16 { 6 | ret = x ^ y ^ z; 7 | } else if 16 <= j && j < 64 { 8 | ret = (x & y) | (x & z) | (y & z); 9 | } 10 | ret 11 | } 12 | 13 | fn sm3_gg_j(x: u32, y: u32, z: u32, j: u32) -> u32 { 14 | let mut ret = 0; 15 | if j < 16 { 16 | ret = x ^ y ^ z; 17 | } else if 16 <= j && j < 64 { 18 | ret = (x & y) | (!x & z) 19 | } 20 | ret 21 | } 22 | 23 | fn sm3_p_0(x: u32) -> u32 { 24 | x ^ x.rotate_left(9) ^ x.rotate_left(17) 25 | } 26 | 27 | fn sm3_p_1(x: u32) -> u32 { 28 | x ^ x.rotate_left(15) ^ x.rotate_left(23) 29 | } 30 | 31 | fn sm3_cf(v_i: &Vec, b_i: &Vec) -> Vec { 32 | let t_j: Vec = vec![ 33 | 2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 34 | 2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 35 | 2043430169, 2043430169, 2043430169, 2043430169, 2055708042, 2055708042, 36 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 37 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 38 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 39 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 40 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 41 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 42 | 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 43 | 2055708042, 2055708042, 2055708042, 2055708042 44 | ]; 45 | let mut w: Vec = Vec::with_capacity(68); 46 | for i in 0..16 { 47 | let mut weight = 0x1000000; 48 | let mut data: u32 = 0; 49 | for k in (i * 4)..((i + 1) * 4) { 50 | data = data.wrapping_add(b_i[k] * weight); 51 | weight /= 0x100; 52 | } 53 | w.push(data); 54 | } 55 | for j in 16..68 { 56 | w.push(sm3_p_1(w[j - 16] ^ w[j - 9] ^ w[j - 3].rotate_left(15)) ^ w[j - 13].rotate_left(7) ^ w[j - 6]); 57 | } 58 | let mut w_1: Vec = Vec::with_capacity(64); 59 | for j in 0..64 { 60 | w_1.push( w[j] ^ w[j + 4]); 61 | } 62 | let mut a = v_i[0]; 63 | let mut b = v_i[1]; 64 | let mut c = v_i[2]; 65 | let mut d = v_i[3]; 66 | let mut e = v_i[4]; 67 | let mut f = v_i[5]; 68 | let mut g = v_i[6]; 69 | let mut h = v_i[7]; 70 | for j in 0..64 { 71 | let ss_1 = ((a.rotate_left(12).wrapping_add(e).wrapping_add(t_j[j].rotate_left(j as u32))) & 0xffffffff).rotate_left(7); 72 | let ss_2 = ss_1 ^ a.rotate_left(12); 73 | let tt_1 = (sm3_ff_j(a, b, c, j as u32).wrapping_add(d).wrapping_add(ss_2).wrapping_add(w_1[j])) & 0xffffffff; 74 | let tt_2 = (sm3_gg_j(e, f, g, j as u32).wrapping_add(h).wrapping_add(ss_1).wrapping_add(w[j])) & 0xffffffff; 75 | d = c; 76 | c = b.rotate_left(9); 77 | b = a; 78 | a = tt_1; 79 | h = g; 80 | g = f.rotate_left(19); 81 | f = e; 82 | e = sm3_p_0(tt_2); 83 | a = a & 0xFFFFFFFF; 84 | b = b & 0xFFFFFFFF; 85 | c = c & 0xFFFFFFFF; 86 | d = d & 0xFFFFFFFF; 87 | e = e & 0xFFFFFFFF; 88 | f = f & 0xFFFFFFFF; 89 | g = g & 0xFFFFFFFF; 90 | h = h & 0xFFFFFFFF; 91 | } 92 | let mut cf: Vec = Vec::with_capacity(8); 93 | let v_j: Vec = vec![a, b, c, d, e, f, g, h]; 94 | for i in 0..8 { 95 | cf.push(v_j[i] ^ v_i[i]); 96 | } 97 | cf 98 | } 99 | 100 | pub fn sm3_hash_raw(msg: &[u8]) -> Vec { 101 | let iv: Vec = vec![ 102 | 1937774191, 1226093241, 388252375, 3666478592, 103 | 2842636476, 372324522, 3817729613, 2969243214, 104 | ]; 105 | let len = msg.len(); 106 | let reserve = len % 64 + 1; 107 | let len_pad = match reserve > 56 { 108 | true => len + 130 - reserve, 109 | false => len + 66 - reserve 110 | }; 111 | let range_end = match reserve > 56 { 112 | true => 120, 113 | false => 56 114 | }; 115 | let mut msg_pad: Vec = Vec::with_capacity(len_pad); 116 | msg_pad.extend_from_slice(msg); 117 | msg_pad.push(0x80); 118 | for _ in reserve..range_end { 119 | msg_pad.push(0x00); 120 | } 121 | let mut bit_length: usize = len * 8; 122 | let mut bit_length_str: Vec = Vec::with_capacity(8); 123 | bit_length_str.push(bit_length % 0x100); 124 | for _ in 0..7 { 125 | bit_length /= 0x100; 126 | bit_length_str.push(bit_length % 0x100); 127 | } 128 | for i in 0..8 { 129 | msg_pad.push(bit_length_str[7 - i] as u8); 130 | } 131 | let group_count: usize = len_pad / 64; 132 | let mut b: Vec> = Vec::with_capacity(group_count); 133 | for _ in 0..group_count { 134 | b.push(Vec::with_capacity(64)); 135 | } 136 | for i in 0..group_count { 137 | b[i] = msg_pad[(i * 64)..((i + 1) * 64)].iter().map(|x| x.to_be() as u32).collect(); 138 | } 139 | let mut v: Vec> = Vec::with_capacity(group_count + 1); 140 | for _ in 0..(group_count + 1) { 141 | v.push(Vec::with_capacity(8)); 142 | } 143 | v[0] = iv; 144 | for i in 0..group_count { 145 | v[i + 1] = sm3_cf(&v[i], &b[i]); 146 | } 147 | let y = &v[group_count]; 148 | y.into_iter().flat_map(|x| x.to_be_bytes()).collect() 149 | } 150 | 151 | pub fn sm3_hash(msg: &[u8]) -> String { 152 | let hash = sm3_hash_raw(msg); 153 | hash.iter().map(|x| format!("{:02x}", x)).collect() 154 | } 155 | 156 | pub fn sm3_hash_file(input_file: &str) -> String { 157 | let input_file = std::path::Path::new(input_file); 158 | let input_data = std::fs::read(input_file).unwrap(); 159 | sm3_hash(&input_data) 160 | } 161 | 162 | pub fn sm3_hash_string(msg_str: &str) -> String { 163 | let msg = msg_str.as_bytes(); 164 | sm3_hash(msg) 165 | } 166 | -------------------------------------------------------------------------------- /src/sm4.rs: -------------------------------------------------------------------------------- 1 | use std::vec; 2 | 3 | const SM4_BOXES_TABLE: [u8; 256] = [ 4 | 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 5 | 0x05, 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 6 | 0x06, 0x99, 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 7 | 0xcf, 0xac, 0x62, 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 8 | 0x75, 0x8f, 0x3f, 0xa6, 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 9 | 0x19, 0xe6, 0x85, 0x4f, 0xa8, 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 10 | 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 11 | 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 12 | 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 13 | 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 14 | 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 15 | 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, 0xd5, 0xdb, 0x37, 0x45, 16 | 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, 0x8d, 0x1b, 0xaf, 17 | 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, 0x0a, 0xc1, 18 | 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, 0x89, 19 | 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, 20 | 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 21 | 0x48 22 | ]; 23 | 24 | const SM4_FK: [u32; 4] = [0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc]; 25 | 26 | const SM4_CK: [u32; 32] = [ 27 | 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 28 | 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, 29 | 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 30 | 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 31 | 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 32 | 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, 33 | 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 34 | 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 35 | ]; 36 | 37 | fn round_key(ka: u32) -> u32 { 38 | let mut b: [u8; 4] = [0, 0, 0, 0]; 39 | let a = ka.to_be_bytes(); 40 | b[0] = SM4_BOXES_TABLE[a[0] as usize]; 41 | b[1] = SM4_BOXES_TABLE[a[1] as usize]; 42 | b[2] = SM4_BOXES_TABLE[a[2] as usize]; 43 | b[3] = SM4_BOXES_TABLE[a[3] as usize]; 44 | let bb = u32::from_be_bytes(b); 45 | let rk = bb ^ (bb.rotate_left(13)) ^ (bb.rotate_left(23)); 46 | rk 47 | } 48 | 49 | fn sm4_l_t(ka: u32) -> u32 { 50 | let mut b: [u8; 4] = [0, 0, 0, 0]; 51 | let a = ka.to_be_bytes(); 52 | b[0] = SM4_BOXES_TABLE[a[0] as usize]; 53 | b[1] = SM4_BOXES_TABLE[a[1] as usize]; 54 | b[2] = SM4_BOXES_TABLE[a[2] as usize]; 55 | b[3] = SM4_BOXES_TABLE[a[3] as usize]; 56 | let bb = u32::from_be_bytes(b); 57 | bb ^ (bb.rotate_left(2)) ^ (bb.rotate_left(10)) ^ (bb.rotate_left(18)) ^ (bb.rotate_left(24)) 58 | } 59 | 60 | fn f(x0: u32, x1: u32, x2: u32, x3: u32, rk: u32) -> u32 { 61 | x0 ^ sm4_l_t(x1 ^ x2 ^ x3 ^ rk) 62 | } 63 | 64 | fn xor(a: &Vec, b: &Vec) -> Vec { 65 | assert_eq!(a.len(), b.len()); 66 | (0..a.len()).map(|i| a[i] ^ b[i]).collect() 67 | } 68 | 69 | fn padding(data: Vec) -> Vec { 70 | let mut result: Vec = data.clone(); 71 | let mut append: Vec = vec![(16 - &data.len() % 16) as u8; 16 - &data.len() % 16]; 72 | result.append(&mut append); 73 | result 74 | } 75 | 76 | fn unpadding(data: Vec) -> Vec { 77 | data[0..(data.len() - data[data.len() - 1] as usize)].to_vec() 78 | } 79 | 80 | fn set_key(key: &[u8], mode: &str) -> Vec { 81 | let mut sk: Vec = vec![0; 32]; 82 | let mut mk: Vec = vec![0, 0, 0, 0]; 83 | let mut k: Vec = vec![0; 36]; 84 | mk[0] = u32::from_be_bytes([key[0], key[1], key[2], key[3]]); 85 | mk[1] = u32::from_be_bytes([key[4], key[5], key[6], key[7]]); 86 | mk[2] = u32::from_be_bytes([key[8], key[9], key[10], key[11]]); 87 | mk[3] = u32::from_be_bytes([key[12], key[13], key[14], key[15]]); 88 | let temp: Vec = (0..4).map(|i| mk[i] ^ SM4_FK[i]).collect(); 89 | k[0..4].clone_from_slice(&temp); 90 | for i in 0..32 { 91 | k[i + 4] = k[i] ^ (round_key(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ SM4_CK[i])); 92 | sk[i] = k[i + 4]; 93 | } 94 | if mode == "SM4_DECRYPT" { 95 | for idx in 0..16 { 96 | let t = sk[idx]; 97 | sk[idx] = sk[31 - idx]; 98 | sk[31 - idx] = t; 99 | } 100 | } 101 | sk 102 | } 103 | 104 | fn one_round(sk: Vec, in_put: Vec) -> Vec { 105 | let mut out_put = vec![]; 106 | let mut ulbuf = vec![0; 36]; 107 | ulbuf[0] = u32::from_be_bytes([in_put[0], in_put[1], in_put[2], in_put[3]]); 108 | ulbuf[1] = u32::from_be_bytes([in_put[4], in_put[5], in_put[6], in_put[7]]); 109 | ulbuf[2] = u32::from_be_bytes([in_put[8], in_put[9], in_put[10], in_put[11]]); 110 | ulbuf[3] = u32::from_be_bytes([in_put[12], in_put[13], in_put[14], in_put[15]]); 111 | for idx in 0..32 { 112 | ulbuf[idx + 4] = f(ulbuf[idx], ulbuf[idx + 1], ulbuf[idx + 2], ulbuf[idx + 3], sk[idx]); 113 | } 114 | out_put.append(&mut ulbuf[35].to_be_bytes().to_vec()); 115 | out_put.append(&mut ulbuf[34].to_be_bytes().to_vec()); 116 | out_put.append(&mut ulbuf[33].to_be_bytes().to_vec()); 117 | out_put.append(&mut ulbuf[32].to_be_bytes().to_vec()); 118 | out_put 119 | } 120 | 121 | fn encrypt_ecb(input_data: &[u8], key: &[u8]) -> Vec { 122 | let sk = set_key(key, "SM4_ENCRYPT"); 123 | let input_data = padding(input_data.to_vec()); 124 | let mut length = input_data.len(); 125 | let mut i = 0; 126 | let mut output_data: Vec = vec![]; 127 | while length > 0 { 128 | output_data.append(&mut one_round(sk.to_owned(), input_data[i..(i + 16)].to_vec())); 129 | i += 16; 130 | length -= 16; 131 | } 132 | output_data 133 | } 134 | 135 | fn encrypt_ecb_base64(input_data: &[u8], key: &[u8]) -> String { 136 | base64::encode(encrypt_ecb(input_data, key)) 137 | } 138 | 139 | fn encrypt_ecb_hex(input_data: &[u8], key: &[u8]) -> String { 140 | hex::encode(encrypt_ecb(input_data, key)) 141 | } 142 | 143 | fn encrypt_ecb_to_file(input_file: &str, output_file: &str, key: &[u8]) { 144 | let input_file = std::path::Path::new(input_file); 145 | let output_file = std::path::Path::new(output_file); 146 | let input_data = std::fs::read(input_file).unwrap(); 147 | let output_data = encrypt_ecb(&input_data, key); 148 | std::fs::write(output_file, &output_data[..]).unwrap(); 149 | } 150 | 151 | fn decrypt_ecb(input_data: &[u8], key: &[u8]) -> Vec { 152 | let sk = set_key(key, "SM4_DECRYPT"); 153 | let mut length = input_data.len(); 154 | let mut i = 0; 155 | let mut output_data: Vec = vec![]; 156 | while length > 0 { 157 | output_data.append(&mut one_round(sk.to_owned(), input_data[i..(i + 16)].to_vec())); 158 | i += 16; 159 | length -= 16; 160 | } 161 | unpadding(output_data) 162 | } 163 | 164 | fn decrypt_ecb_base64(input_data: &str, key: &[u8]) -> Vec { 165 | decrypt_ecb(&base64::decode(input_data).unwrap(), key) 166 | } 167 | 168 | fn decrypt_ecb_hex(input_data: &str, key: &[u8]) -> Vec { 169 | decrypt_ecb(&hex::decode(input_data).unwrap(), key) 170 | } 171 | 172 | fn decrypt_ecb_from_file(input_file: &str, output_file: &str, key: &[u8]) { 173 | let input_file = std::path::Path::new(input_file); 174 | let output_file = std::path::Path::new(output_file); 175 | let input_data = std::fs::read(input_file).unwrap(); 176 | let output_data = decrypt_ecb(&input_data, key); 177 | std::fs::write(output_file, &output_data[..]).unwrap() 178 | } 179 | 180 | fn encrypt_cbc(input_data: &[u8], key: &[u8], iv: &[u8]) -> Vec { 181 | let sk = set_key(key, "SM4_ENCRYPT"); 182 | let mut i = 0; 183 | let mut output_data: Vec = vec![]; 184 | let mut tmp_input: Vec; 185 | let mut iv = iv.to_vec(); 186 | let input_data = padding(input_data.to_vec()); 187 | let mut length = input_data.len(); 188 | while length > 0 { 189 | tmp_input = xor(&input_data[i..(i + 16)].to_vec(), &iv[0..16].to_vec()); 190 | output_data.append(&mut one_round(sk.to_owned(), tmp_input[0..16].to_vec())); 191 | iv = output_data[i..(i + 16)].to_vec(); 192 | i += 16; 193 | length -= 16; 194 | } 195 | output_data 196 | } 197 | 198 | fn encrypt_cbc_base64(input_data: &[u8], key: &[u8], iv: &[u8]) -> String { 199 | base64::encode(encrypt_cbc(input_data, key, iv)) 200 | } 201 | 202 | fn encrypt_cbc_hex(input_data: &[u8], key: &[u8], iv: &[u8]) -> String { 203 | hex::encode(encrypt_cbc(input_data, key, iv)) 204 | } 205 | 206 | fn encrypt_cbc_to_file(input_file: &str, output_file: &str, key: &[u8], iv: &[u8]) { 207 | let input_file = std::path::Path::new(input_file); 208 | let output_file = std::path::Path::new(output_file); 209 | let input_data = std::fs::read(input_file).unwrap(); 210 | let output_data = encrypt_cbc(&input_data, key, iv); 211 | std::fs::write(output_file, &output_data[..]).unwrap(); 212 | } 213 | 214 | fn decrypt_cbc(input_data: &[u8], key: &[u8], iv: &[u8]) -> Vec { 215 | let sk = set_key(key, "SM4_DECRYPT"); 216 | let mut i = 0; 217 | let mut output_data: Vec = vec![]; 218 | let mut iv = iv.to_vec(); 219 | let mut length = input_data.len(); 220 | while length > 0 { 221 | output_data.append(&mut one_round(sk.to_owned(), input_data[i..(i + 16)].to_vec())); 222 | let tmp_copy = xor(&output_data[i..(i + 16)].to_vec(), &iv[0..16].to_vec()); 223 | let (_left1, right1) = output_data.split_at_mut(i); 224 | let (left2, _right2) = right1.split_at_mut(16); 225 | left2.copy_from_slice(&tmp_copy); 226 | iv = input_data[i..(i + 16)].to_vec(); 227 | i += 16; 228 | length -= 16 229 | } 230 | unpadding(output_data) 231 | } 232 | 233 | fn decrypt_cbc_base64(input_data: &str, key: &[u8], iv: &[u8]) -> Vec { 234 | decrypt_cbc(&base64::decode(input_data).unwrap(), key, iv) 235 | } 236 | 237 | fn decrypt_cbc_hex(input_data: &str, key: &[u8], iv: &[u8]) -> Vec { 238 | decrypt_cbc(&hex::decode(input_data).unwrap(), key, iv) 239 | } 240 | 241 | fn decrypt_cbc_from_file(input_file: &str, output_file: &str, key: &[u8], iv: &[u8]) { 242 | let input_file = std::path::Path::new(input_file); 243 | let output_file = std::path::Path::new(output_file); 244 | let input_data = std::fs::read(input_file).unwrap(); 245 | let output_data = decrypt_cbc(&input_data, key, iv); 246 | std::fs::write(output_file, output_data).unwrap() 247 | } 248 | 249 | pub struct CryptSM4ECB<'a> { 250 | pub key: &'a [u8] 251 | } 252 | 253 | impl<'a> CryptSM4ECB<'a> { 254 | pub fn new(key: &'a [u8]) -> Self { 255 | CryptSM4ECB{key: key} 256 | } 257 | 258 | pub fn encrypt_ecb(&self, input_data: &[u8]) -> Vec { 259 | encrypt_ecb(input_data, self.key) 260 | } 261 | 262 | pub fn encrypt_ecb_base64(&self, input_data: &[u8]) -> String { 263 | encrypt_ecb_base64(input_data, self.key) 264 | } 265 | 266 | pub fn encrypt_ecb_hex(&self, input_data: &[u8]) -> String { 267 | encrypt_ecb_hex(input_data, self.key) 268 | } 269 | 270 | pub fn decrypt_ecb(&self, input_data: &[u8]) -> Vec { 271 | decrypt_ecb(input_data, self.key) 272 | } 273 | 274 | pub fn decrypt_ecb_base64(&self, input_data: &str) -> Vec { 275 | decrypt_ecb_base64(input_data, self.key) 276 | } 277 | 278 | pub fn decrypt_ecb_hex(&self, input_data: &str) -> Vec { 279 | decrypt_ecb_hex(input_data, self.key) 280 | } 281 | 282 | pub fn encrypt_to_file(&self, input_file: &str, output_file: &str) { 283 | encrypt_ecb_to_file(input_file, output_file, self.key) 284 | } 285 | 286 | pub fn decrypt_from_file(&self, input_file: &str, output_file: &str) { 287 | decrypt_ecb_from_file(input_file, output_file, self.key) 288 | } 289 | } 290 | 291 | pub struct CryptSM4CBC<'a> { 292 | pub key: &'a [u8], 293 | pub iv: &'a [u8] 294 | } 295 | 296 | impl<'a> CryptSM4CBC<'a> { 297 | pub fn new(key: &'a [u8], iv: &'a [u8]) -> Self { 298 | CryptSM4CBC{key: key, iv: iv} 299 | } 300 | 301 | pub fn encrypt_cbc(&self, input_data: &[u8]) -> Vec { 302 | encrypt_cbc(input_data, self.key, self.iv) 303 | } 304 | 305 | pub fn encrypt_cbc_base64(&self, input_data: &[u8]) -> String { 306 | encrypt_cbc_base64(input_data, self.key, self.iv) 307 | } 308 | 309 | pub fn encrypt_cbc_hex(&self, input_data: &[u8]) -> String { 310 | encrypt_cbc_hex(input_data, self.key, self.iv) 311 | } 312 | 313 | pub fn decrypt_cbc(&self, input_data: &[u8]) -> Vec { 314 | decrypt_cbc(input_data, self.key, self.iv) 315 | } 316 | 317 | pub fn decrypt_cbc_base64(&self, input_data: &str) -> Vec { 318 | decrypt_cbc_base64(input_data, self.key, self.iv) 319 | } 320 | 321 | pub fn decrypt_cbc_hex(&self, input_data: &str) -> Vec { 322 | decrypt_cbc_hex(input_data, self.key, self.iv) 323 | } 324 | 325 | pub fn encrypt_to_file(&self, input_file: &str, output_file: &str) { 326 | encrypt_cbc_to_file(input_file, output_file, self.key, self.iv) 327 | } 328 | 329 | pub fn decrypt_from_file(&self, input_file: &str, output_file: &str) { 330 | decrypt_cbc_from_file(input_file, output_file, self.key, self.iv) 331 | } 332 | } 333 | --------------------------------------------------------------------------------