miracl_core/bls12381/
mpin.rs1use crate::bls12381::big;
21use crate::bls12381::big::BIG;
22use crate::bls12381::ecp;
23use crate::bls12381::ecp::ECP;
24use crate::bls12381::ecp2::ECP2;
25use crate::bls12381::fp12::FP12;
26use crate::bls12381::pair;
27use crate::bls12381::rom;
28use crate::bls12381::fp::FP;
29use crate::bls12381::dbig::DBIG;
30
31use crate::hmac;
32use crate::rand::RAND;
33
34pub const EFS: usize = big::MODBYTES as usize;
39pub const EGS: usize = big::MODBYTES as usize;
40pub const BAD_PARAMS: isize = -11;
41pub const INVALID_POINT: isize = -14;
42pub const WRONG_ORDER: isize = -18;
43pub const BAD_PIN: isize = -19;
44pub const SHA256: usize = 32;
45pub const SHA384: usize = 48;
46pub const SHA512: usize = 64;
47
48pub const MAXPIN: i32 = 10000; pub const PBLEN: i32 = 14; fn ceil(a: usize,b: usize) -> usize {
54 (a-1)/b+1
55}
56
57#[allow(non_snake_case)]
58pub fn encode_to_curve(dst: &[u8],id: &[u8],hcid: &mut [u8]) {
59 let q = BIG::new_ints(&rom::MODULUS);
60 let k=q.nbits();
61 let r = BIG::new_ints(&rom::CURVE_ORDER);
62 let m=r.nbits();
63 let el=ceil(k+ceil(m,2),8);
64 let mut okm: [u8;512]=[0;512];
65 hmac::xmd_expand(hmac::MC_SHA2,ecp::HASH_TYPE,&mut okm,el,&dst,&id);
66 let mut fd: [u8;256]=[0;256];
67 for j in 0..el {
68 fd[j]=okm[j];
69 }
70 let mut dx=DBIG::frombytes(&fd[0..el]);
71 let u=FP::new_big(&dx.dmod(&q));
72 let mut P=ECP::map2point(&u);
73 P.cfp();
74 P.affine();
75 P.tobytes(hcid,false);
76}
77
78pub fn random_generate(rng: &mut impl RAND, s: &mut [u8]) -> isize {
80 let r = BIG::new_ints(&rom::CURVE_ORDER);
81 let sc = BIG::randtrunc(&r, 16 * ecp::AESKEY, rng);
82 sc.tobytes(s);
83 0
84}
85
86#[allow(non_snake_case)]
88pub fn extract_pin(cid: &[u8], pin: i32, token: &mut [u8]) -> isize {
89 let mut P = ECP::frombytes(&token);
90 if P.is_infinity() {
91 return INVALID_POINT;
92 }
93 let mut R = ECP::frombytes(&cid);
94 if R.is_infinity() {
95 return INVALID_POINT;
96 }
97
98 R = R.pinmul(pin%MAXPIN, PBLEN);
99 P.sub(&R);
100 P.tobytes(token, false);
101 0
102}
103
104#[allow(non_snake_case)]
106pub fn client_2(x: &[u8], y: &[u8], sec: &mut [u8]) -> isize {
107 let r = BIG::new_ints(&rom::CURVE_ORDER);
108 let mut P = ECP::frombytes(sec);
109 if P.is_infinity() {
110 return INVALID_POINT;
111 }
112
113 let mut px = BIG::frombytes(x);
114 let py = BIG::frombytes(y);
115 px.add(&py);
116 px.rmod(&r);
117
118 P = pair::g1mul(&P, &px);
119 P.neg();
120 P.tobytes(sec, false);
121 0
122}
123
124#[allow(non_snake_case)]
126pub fn get_client_secret(s: &mut [u8], idhtc: &[u8], cst: &mut [u8]) -> isize {
127 let sx=BIG::frombytes(s);
128 let P=ECP::frombytes(idhtc);
129 if P.is_infinity() {
130 return INVALID_POINT;
131 }
132 pair::g1mul(&P, &sx).tobytes(cst, false);
133 0
134}
135
136#[allow(non_snake_case)]
138pub fn client_1(
139 cid: &[u8],
140 rng: Option<&mut impl RAND>,
141 x: &mut [u8],
142 pin: usize,
143 token: &[u8],
144 sec: &mut [u8],
145 xid: &mut [u8]
146) -> isize {
147 let r = BIG::new_ints(&rom::CURVE_ORDER);
148 let sx: BIG;
149
150 if let Some(rd) = rng {
151 sx = BIG::randtrunc(&r, 16 * ecp::AESKEY, rd);
152 sx.tobytes(x);
153 } else {
154 sx = BIG::frombytes(x);
155 }
156 let mut P=ECP::frombytes(cid);
157 if P.is_infinity() {
158 return INVALID_POINT;
159 }
160
161 let mut T = ECP::frombytes(&token);
162 if T.is_infinity() {
163 return INVALID_POINT;
164 }
165
166 let W = P.pinmul((pin as i32) % MAXPIN, PBLEN);
167 T.add(&W);
168
169 P = pair::g1mul(&P, &sx);
170 P.tobytes(xid, false);
171
172 T.tobytes(sec, false);
173 0
174}
175
176
177#[allow(non_snake_case)]
179pub fn get_server_secret(s: &[u8], sst: &mut [u8]) -> isize {
180 let mut Q = ECP2::generator();
181 let sc = BIG::frombytes(s);
182 Q = pair::g2mul(&Q, &sc);
183 Q.tobytes(sst,false);
184 0
185}
186
187#[allow(non_snake_case)]
189pub fn server(
190 hid: &[u8],
191 y: &[u8],
192 sst: &[u8],
193 xid: &[u8],
194 msec: &[u8],
195) -> isize {
196 let Q = ECP2::generator();
197 let sQ = ECP2::frombytes(&sst);
198 if sQ.is_infinity() {
199 return INVALID_POINT;
200 }
201 let mut R = ECP::frombytes(&xid);
202 if R.is_infinity() {
203 return INVALID_POINT;
204 }
205
206 let sy = BIG::frombytes(&y);
207 let mut P = ECP::frombytes(&hid);
208 if P.is_infinity() {
209 return INVALID_POINT;
210 }
211
212 P = pair::g1mul(&P, &sy);
213 P.add(&R);
214 R = ECP::frombytes(&msec);
215 if R.is_infinity() {
216 return INVALID_POINT;
217 }
218
219 let mut g: FP12;
220 g = pair::ate2(&Q, &R, &sQ, &P);
221 g = pair::fexp(&g);
222
223 if !g.isunity() {
224 return BAD_PIN;
225 }
226 0
227}
228