gm_rs/sm2/
p256_field.rs

1use core::ops::Add;
2use std::io::Cursor;
3use std::ops::{Mul, Sub};
4
5use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
6use num_bigint::BigUint;
7use num_traits::Num;
8
9use crate::sm2::error::{Sm2Error, Sm2Result};
10use crate::sm2::p256_ecc::P256C_PARAMS;
11use crate::sm2::{FeOperation};
12use crate::{forward_ref_ref_binop, forward_ref_val_binop, forward_val_val_binop};
13
14pub type Fe = [u32; 8];
15
16pub trait Conversion {
17    fn fe_to_bigunit(&self) -> BigUint;
18
19    fn bigunit_fe(&self) -> Fe;
20}
21
22// p = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF
23// p = 2^256 − 2^224 − 2^96 + 2^32 − 1
24pub const ECC_P: Fe = [
25    0xffff_fffe,
26    0xffff_ffff,
27    0xffff_ffff,
28    0xffff_ffff,
29    0xffff_ffff,
30    0x0000_0000,
31    0xffff_ffff,
32    0xffff_ffff,
33];
34
35/// 素域Fp的域元素
36///
37/// 这里我们规定一个有限域Fp
38///
39/// * 取大质数p,则有限域中有p-1个有限元:0,1,2...p-1
40/// * 域元素的加法是整数的模p加法,即若a,b ∈ Fp,则a+b = (a+b) mod p;
41/// * 域元素的乘法是整数的模p乘法,即若a,b ∈ Fp,则a · b = (a · b) mod p
42/// * 域元素的减法是整数的模p减法,即若a,b ∈ Fp,则a - b = (a - b) mod p
43/// * Fp上的除法就是乘除数的乘法逆元`a÷b≡c(mod p)`,即 `a×b^(-1)≡c (mod p)`
44/// * Fp的乘法单位元是整数1
45/// * Fp的加法单位元是整数0
46/// * Fp域上满足交换律,结合律,分配律
47#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
48pub struct FieldElement {
49    pub(crate) inner: Fe,
50}
51
52impl FieldElement {
53    pub fn new(x: Fe) -> FieldElement {
54        FieldElement { inner: x }
55    }
56
57    #[inline]
58    pub fn from_slice(x: &[u32]) -> FieldElement {
59        let mut arr: Fe = [0; 8];
60        arr.copy_from_slice(&x[..]);
61        FieldElement::new(arr)
62    }
63
64    #[inline]
65    pub fn from_number(x: u64) -> FieldElement {
66        let mut arr: Fe = [0; 8];
67        arr[7] = (x & 0xffff_ffff) as u32;
68        arr[6] = (x >> 32) as u32;
69        FieldElement { inner: arr }
70    }
71
72    #[inline]
73    pub fn to_bytes_be(&self) -> Vec<u8> {
74        let mut ret: Vec<u8> = Vec::new();
75        for i in 0..8 {
76            ret.write_u32::<BigEndian>(self.inner[i]).unwrap();
77        }
78        ret
79    }
80
81    #[inline]
82    pub fn from_bytes_be(bytes: &[u8]) -> Sm2Result<FieldElement> {
83        if bytes.len() != 32 {
84            return Err(Sm2Error::InvalidFieldLen);
85        }
86        let mut elem = FieldElement::zero();
87        let mut c = Cursor::new(bytes);
88        for i in 0..8 {
89            elem.inner[i] = c.read_u32::<BigEndian>().unwrap();
90        }
91        Ok(elem)
92    }
93
94    #[inline]
95    pub fn to_biguint(&self) -> BigUint {
96        let v = self.to_bytes_be();
97        BigUint::from_bytes_be(&v[..])
98    }
99
100    #[inline]
101    pub fn from_biguint(bi: &BigUint) -> Sm2Result<FieldElement> {
102        let v = bi.to_bytes_be();
103        let mut num_v = [0; 32];
104        num_v[32 - v.len()..32].copy_from_slice(&v[..]);
105        FieldElement::from_bytes_be(&num_v[..])
106    }
107
108    pub fn sqrt(&self) -> Sm2Result<FieldElement> {
109        // p = 4 * u + 3
110        // u = u + 1
111        let u = BigUint::from_str_radix(
112            "28948022302589062189105086303505223191562588497981047863605298483322421248000",
113            10,
114        )
115        .unwrap();
116        let y = self.modpow(&u);
117        let z = &y.square();
118        if z == self {
119            Ok(y)
120        } else {
121            Err(Sm2Error::FieldSqrtError)
122        }
123    }
124
125    #[inline]
126    pub fn to_str_radix(&self, radix: u32) -> String {
127        self.to_biguint().to_str_radix(radix)
128    }
129
130    pub fn zero() -> FieldElement {
131        FieldElement::new([0; 8])
132    }
133
134    pub fn one() -> FieldElement {
135        FieldElement::from_number(1)
136    }
137
138    pub fn is_even(&self) -> bool {
139        self.inner[7] & 0x01 == 0
140    }
141
142    pub fn is_zero(&self) -> bool {
143        self.inner == [0; 8]
144    }
145
146    pub fn is_one(&self) -> bool {
147        self.inner[7] == 1
148    }
149
150    #[inline]
151    pub fn square(&self) -> FieldElement {
152        self * self
153    }
154
155    #[inline]
156    pub fn double(&self) -> FieldElement {
157        self + self
158    }
159
160    #[inline]
161    pub fn modpow(&self, exponent: &BigUint) -> Self {
162        let u = FieldElement::from_biguint(exponent).unwrap();
163        let mut q0 = FieldElement::from_number(1);
164        let mut q1 = *self;
165        let mut i = 0;
166        while i < 256 {
167            let index = i as usize / 32;
168            let bit = 31 - i as usize % 32;
169
170            let sum = &q0 * &q1;
171            if (u.inner[index] >> bit) & 0x01 == 0 {
172                q1 = sum;
173                q0 = q0.square();
174            } else {
175                q0 = sum;
176                q1 = q1.square();
177            }
178            i += 1;
179        }
180        q0
181    }
182
183    // calculate x^(-1) mod p
184    #[inline]
185    pub fn modinv(&self) -> FieldElement {
186        let ecc_p = &P256C_PARAMS.p;
187        let ret = self.inner.inv(&ecc_p.inner);
188        FieldElement::new(ret)
189    }
190}
191
192forward_val_val_binop!(impl Add for FieldElement, add);
193forward_ref_ref_binop!(impl Add for FieldElement, add);
194forward_ref_val_binop!(impl Add for FieldElement, add);
195impl<'a> Add<&'a FieldElement> for FieldElement {
196    type Output = FieldElement;
197
198    fn add(mut self, rhs: &FieldElement) -> Self::Output {
199        self.inner = self.inner.mod_add(&rhs.inner, &ECC_P);
200        self
201    }
202}
203
204forward_val_val_binop!(impl Sub for FieldElement, sub);
205forward_ref_ref_binop!(impl Sub for FieldElement, sub);
206forward_ref_val_binop!(impl Sub for FieldElement, sub);
207impl<'a> Sub<&'a FieldElement> for FieldElement {
208    type Output = FieldElement;
209
210    fn sub(mut self, rhs: &'a FieldElement) -> Self::Output {
211        self.inner = self.inner.mod_sub(&rhs.inner, &ECC_P);
212        self
213    }
214}
215
216forward_val_val_binop!(impl Mul for FieldElement, mul);
217forward_ref_ref_binop!(impl Mul for FieldElement, mul);
218forward_ref_val_binop!(impl Mul for FieldElement, mul);
219impl<'a> Mul<&'a FieldElement> for FieldElement {
220    type Output = FieldElement;
221
222    fn mul(mut self, rhs: &'a FieldElement) -> Self::Output {
223        self.inner = self.inner.mod_mul(&rhs.inner, &ECC_P);
224        self
225    }
226}
227
228impl Default for FieldElement {
229    #[inline]
230    fn default() -> FieldElement {
231        FieldElement {
232            inner: [0; 8],
233        }
234    }
235}
236
237
238#[cfg(test)]
239mod test_fe{
240    use crate::sm2::p256_field::FieldElement;
241
242    #[test]
243    fn test_mod_mul(){
244        let a = FieldElement::new([
245            764497930, 2477372445, 473039778, 1327312203, 3110691882, 1307193102, 2665428562, 967816337,
246        ]);
247        let b = FieldElement::new([
248            2873589426, 3315627933, 3055686524, 325110103, 3264434653, 2512214348, 3018997295,
249            3617546169,
250        ]);
251
252        let ret = a * b;
253        println!("{:?}", ret)
254    }
255
256}