1use crate::encrypt;
2use crate::error::Sm2Error;
3use base64::engine::general_purpose::STANDARD;
4use base64::Engine;
5use byteorder::{BigEndian, WriteBytesExt};
6use libsm::sm2::ecc::{EccCtx, Point};
7use libsm::sm2::signature::Signature;
8use libsm::sm3::hash::Sm3Hash;
9use num_bigint::BigUint;
10use num_traits::{One, Zero};
11use sha1::Digest;
12use smcrypto::sm3;
13
14pub fn rsa_verify(msg: &[u8], pk: &[u8], sign: &str) -> Result<bool, Sm2Error> {
20 let signature = STANDARD.decode(sign)?;
22
23 let rsa = openssl::rsa::Rsa::public_key_from_pem(pk)?;
25
26 let pkey = openssl::pkey::PKey::from_rsa(rsa)?;
27
28 let mut verifier = openssl::sign::Verifier::new(openssl::hash::MessageDigest::sha256(), &pkey)?;
30
31 verifier.update(msg)?;
33
34 Ok(verifier.verify(&signature)?)
36}
37
38pub fn sign_body(data: &str, secret: &str) -> Result<String, Sm2Error> {
43 let data = sha1_base64(data);
44 let data = sm3::sm3_hash(data.as_bytes());
45 encrypt(&data, secret)
46}
47
48pub fn sign(msg: &[u8], pk: &str, sk: &str) -> Result<String, Sm2Error> {
55 let curve = &EccCtx::new();
56 let pk = &hex::decode(pk)?;
57 let pk = load_pubkey(curve, pk)?;
58 let sk = &hex::decode(sk)?;
59 let sk = BigUint::from_bytes_be(sk);
60 let digest = sign_hash(curve, &pk, msg)?;
62 let signature = sign_raw(curve, &digest[..], &sk)?;
63 let base64 = STANDARD.encode(signature);
64 Ok(base64)
65}
66
67pub fn verify(msg: &[u8], pk: &str, sign: &str) -> Result<bool, Sm2Error> {
73 let sig = Signature::der_decode(&hex::decode(STANDARD.decode(sign)?)?).map_err(|e| Sm2Error::LibSmError(format!("{}", e)))?;
74 let pk = efficient_sm2::PublicKey::from_slice(&hex::decode(&pk[2..])?);
75 let signature = efficient_sm2::Signature::new(&sig.get_r().to_bytes_be(), &sig.get_s().to_bytes_be()).map_err(|e| Sm2Error::LibSmError(format!("{:?}", e)))?;
76 if signature.verify(&pk, msg).is_ok() {
77 return Ok(true);
78 }
79 Ok(false)
80}
81
82pub fn sha1_base64(data: &str) -> String {
86 let mut hasher = sha1::Sha1::new();
87 hasher.update(data);
88 let hash_bytes = hasher.finalize();
89 STANDARD.encode(hash_bytes)
90}
91
92fn load_pubkey(curve: &EccCtx, buf: &[u8]) -> Result<Point, Sm2Error> {
93 curve.bytes_to_point(buf).map_err(|e| Sm2Error::LibSmError(e.to_string()))
94}
95fn sign_hash(curve: &EccCtx, pk: &Point, msg: &[u8]) -> Result<[u8; 32], Sm2Error> {
96 let id = "1234567812345678";
97 let mut prepend: Vec<u8> = Vec::new();
98 prepend.write_u16::<BigEndian>((id.len() * 8) as u16).map_err(|e| Sm2Error::LibSmError(e.to_string()))?;
99 for c in id.bytes() {
100 prepend.push(c);
101 }
102
103 let mut a = curve.get_a().to_bytes();
104 let mut b = curve.get_b().to_bytes();
105
106 prepend.append(&mut a);
107 prepend.append(&mut b);
108
109 let (x_g, y_g) = curve.to_affine(
110 &curve.generator().map_err(|e| Sm2Error::LibSmError(e.to_string()))?
111 ).map_err(|e| Sm2Error::LibSmError(e.to_string()))?;
112 let (mut x_g, mut y_g) = (x_g.to_bytes(), y_g.to_bytes());
113 prepend.append(&mut x_g);
114 prepend.append(&mut y_g);
115
116 let (x_a, y_a) = curve.to_affine(pk).map_err(|e| Sm2Error::LibSmError(e.to_string()))?;
117 let (mut x_a, mut y_a) = (x_a.to_bytes(), y_a.to_bytes());
118 prepend.append(&mut x_a);
119 prepend.append(&mut y_a);
120
121 let mut hasher = Sm3Hash::new(&prepend[..]);
122 let z_a = hasher.get_hash();
123
124 let mut prepended_msg: Vec<u8> = Vec::new();
129 prepended_msg.extend_from_slice(&z_a[..]);
130 prepended_msg.extend_from_slice(msg);
131
132 let mut hasher = Sm3Hash::new(&prepended_msg[..]);
133 Ok(hasher.get_hash())
134}
135fn sign_raw(curve: &EccCtx, digest: &[u8], sk: &BigUint) -> Result<String, Sm2Error> {
136 let e = BigUint::from_bytes_be(digest);
138 loop {
140 let k = BigUint::from_bytes_be(&hex::decode("dc388f4220a38e285ebb3da2bfd48ff2d52358030e13672c76ceceebcb03991f")?);
142 let p_1 = curve.bytes_to_point(&hex::decode("047121548af8b601e2ebec3c7b679429f0d3387b5f3ea7883925c68fdd1161a73fa593a5dd16c9248b93ef9d8d85053715754e050cc199e94ac332cfdde8bdff52")?)
143 .map_err(|e| Sm2Error::LibSmError(e.to_string()))?;
144
145 let (x_1, _) = curve.to_affine(&p_1).map_err(|e| Sm2Error::LibSmError(e.to_string()))?;
146 let x_1 = x_1.to_biguint();
147
148 let r = (&e + x_1) % curve.get_n();
150 if r == BigUint::zero() || &r + &k == *curve.get_n() {
151 continue;
152 }
153
154 let s1 = curve.inv_n(&(sk + BigUint::one())).map_err(|e| Sm2Error::LibSmError(e.to_string()))?;
156
157 let mut s2_1 = &r * sk;
158 if s2_1 < k {
159 s2_1 += curve.get_n();
160 }
161 let mut s2 = s2_1 - k;
162 s2 %= curve.get_n();
163 let s2 = curve.get_n() - s2;
164
165 let s = (s1 * s2) % curve.get_n();
166
167 if s != BigUint::zero() {
168 let signature = yasna::construct_der(|writer| {
170 writer.write_sequence(|writer| {
171 writer.next().write_biguint(&r);
172 writer.next().write_biguint(&s);
173 })
174 });
175 let signature = hex::encode(signature);
177 return Ok(signature);
178 }
179 return Err(Sm2Error::LibSmError("Signature failed".to_string()));
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 #[test]
186 fn test_sign() {
187 let msg = r#"hello world"#;
188 let pk = "04ff055e4349345eba0fc69362f483f4f408d876dda2520e8e424e81978129da56b19587538253a2406d035a8d9981efeeac60ec72b3308b9a07a5398b61d3d189";
189 let sk = "6d7964184b735645ef49b3c1ee5a2c2efdbd15d6c9d851c57eef341ed0e1eb1b";
190
191 let signature = super::sign(msg.as_bytes(), pk, sk).unwrap();
193 assert_eq!(signature, "MzA0NjAyMjEwMDgwMGM3NDg0NTlkZDQ2MTdlMzMzNWM3OGRjNDJlOGFjZWU0OTg5YmYwYjk2NzFmYWYzZjkxN2ZkNmU0NGFhOTkwMjIxMDBjOGM2YjhiZjI5NzRmNzljYWE3Mjc4MzZjZjgwMTc2MzI0YmI1YjkxZDFkYWQzNjIzMWQyODA2MDVhZTNhNDYy");
194
195 let verify = super::verify(msg.as_bytes(), pk, &signature).unwrap();
197 assert_eq!(verify, true);
198
199 let secret = "ZTPkMS00ZNTP5NzPwNjAu";
201 let signature = super::sign_body(msg, secret).unwrap();
202 assert_eq!(signature, "ZTVlOGU0YzZmYjk0N2JiZDQxNDdmZjgyNTgwYTVhMzgxMjVmN2U5M2Q1MzA0NTg2YmJkNjljMmJiYWZlNWMyZWZlY2JiOWI0YmQzNWQ1YWE3OTZlYTkzY2Q0M2RmNmM2ZGEyMzA1NGJiOTEzMTJmMDE5YzI2YzVjOTZhYWVmYmNmMzkwYjMzZTNlY2Q3MzQzMjMwNWM1YzYzNTQ3ZmI0OQ==");
203 }
204
205 #[test]
206 fn test_verify() {
207 let signature = "MzA0NTAyMjEwMGVkOWQ3ZjY3YzhkNmU3NGVmODJjZDJjNDI2N2IwMDQ4ZDliZjc0NDcwNThmNGY4Mzc4NmUyZjI1OGVhNjRhYjQwMjIwMTE1NjM3ZTRmNGY5YWE4Yzg5NmQ3MTE0NjNkN2E3OGEzZGE1NjQ0NDQyOWU2NTlmNTk2NWMwMjJkNmVhNzMxYw==";
208 let body = "M2YyZWFlOTU4MzBkZTUxMGQyOTNjNmUzYzA1ODg2NjM=";
209 let secret = "ZTPkMS00ZNTP5NzPwNjAu";
210 let spdb_pk = "04049bc3c83c5709b1b9d7fce408095809f20ee9cd16fde7944f95fa21392f109bd3c7caed077e41682126f383e547bd48899f9c279cff5f2f06ca0e41013abf11";
211
212 let msg = crate::decrypt(&body, secret).unwrap();
214 assert_eq!(msg, "hello world");
215 let verify = super::verify(crate::sha1_base64(&msg).as_bytes(), spdb_pk, &signature).unwrap();
217 assert_eq!(verify, true);
218 }
219}