ecsimple/
point.rs

1
2use crate::bngf2m::*;
3use crate::group::*;
4use crate::utils::*;
5use crate::mont::*;
6//use crate::consts::*;
7use num_bigint::{BigInt};
8use num_traits::{zero,one};
9use std::error::Error;
10use std::cmp::PartialEq;
11
12#[allow(unused_imports)]
13use crate::logger::*;
14#[allow(unused_imports)]
15use crate::randop::*;
16
17
18ecsimple_error_class!{BnGf2mPointError}
19
20#[derive(Clone)]
21pub (crate) struct ECGf2mPoint {
22	x :BnGf2m,
23	y :BnGf2m,
24	z :BnGf2m,
25	pub (crate) group :ECGroupBnGf2m,
26	infinity : bool,
27}
28
29
30impl std::fmt::Display for ECGf2mPoint {
31	fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32		write!(f,"curve[{}] isinfinity {} x 0x{:x} y 0x{:x} z 0x{:x}", self.group,self.infinity,self.x,self.y,self.z)
33	}
34}
35
36impl std::default::Default for ECGf2mPoint {
37	fn default() -> Self {
38		ECGf2mPoint {
39			x : BnGf2m::default(),
40			y :BnGf2m::default(),
41			z :BnGf2m::default(),
42			group : ECGroupBnGf2m::default(),
43			infinity : true,
44		}
45	}
46}
47
48impl PartialEq for ECGf2mPoint {
49	fn eq(&self, other :&ECGf2mPoint) -> bool {
50		return self.eq_op(other);
51	}
52
53	fn ne(&self, other :&ECGf2mPoint) -> bool {
54		return !self.eq(other);
55	}
56}
57
58
59impl ECGf2mPoint {
60	pub fn is_infinity(&self) -> bool {
61		return self.infinity;
62	}
63
64	pub fn new(grp :&ECGroupBnGf2m) -> ECGf2mPoint {
65		ECGf2mPoint {
66			x : grp.generator.x.clone(),
67			y : grp.generator.y.clone(),
68			z : grp.generator.z.clone(),
69			group : grp.clone(),
70			infinity : false,
71		}
72	}
73
74	pub  fn eq_op(&self, other :&ECGf2mPoint) -> bool {
75		if self.x != other.x {
76			return false;
77		}
78
79		if self.y != other.y {
80			return false;
81		}
82
83		if self.z != other.z {
84			return false;
85		}
86
87		if self.group != other.group {
88			return false;
89		}
90
91		if self.infinity != other.infinity {
92			return false;
93		}
94		return true;
95	}
96
97	pub fn new_point(x :&BnGf2m, y :&BnGf2m,z :&BnGf2m, grp :&ECGroupBnGf2m) -> Self {
98		Self {
99			x :x.clone(),
100			y :y.clone(),
101			z :z.clone(),
102			group :grp.clone(),
103			infinity : false,
104		}
105	}
106
107
108
109	pub fn set_x(&mut self, x :&BnGf2m) {
110		self.x = x.clone();
111	}
112
113	pub fn set_y(&mut self, y :&BnGf2m) {
114		self.y = y.clone();
115	}
116
117	pub fn set_z(&mut self, z :&BnGf2m) {
118		self.z = z.clone();
119	}
120
121	pub fn x(&self) -> BnGf2m {
122		return self.x.clone();
123	}
124
125	pub fn y(&self) -> BnGf2m {
126		return self.y.clone();
127	}
128
129	#[allow(dead_code)]
130	pub fn z(&self) -> BnGf2m {
131		return self.z.clone();
132	}
133
134	pub fn field_mul(&self,a :&BnGf2m, b :&BnGf2m) -> BnGf2m {
135		let retv :BnGf2m ;
136		retv = a * b;
137		let ord :BnGf2m = BnGf2m::new_from_bigint(&self.group.p);
138		ecsimple_log_trace!("a 0x{:X} * b 0x{:X} % ord 0x{:X} = 0x{:X}",a,b,ord, retv.clone() % ord.clone());
139		return retv % ord;
140	}
141
142	pub fn field_sqr(&self,a :&BnGf2m) -> BnGf2m {
143		let retv :BnGf2m;
144		retv = a * a;
145		let ord :BnGf2m = BnGf2m::new_from_bigint(&self.group.p);
146		ecsimple_log_trace!("a 0x{:X} * a 0x{:X} % ord 0x{:X} = 0x{:X}",a,a, ord,retv.clone() % ord.clone());
147		return retv % ord;		
148	}
149
150	pub fn field_div(&self,a :&BnGf2m, b:&BnGf2m) -> Result<BnGf2m,Box<dyn Error>> {
151		let fp :BnGf2m = BnGf2m::new_from_bigint(&self.group.p);
152		let invb :BnGf2m = b.inv_op(&fp)?;
153		ecsimple_log_trace!("0x{:X} * 0x{:X} = 1 % 0x{:X}",invb,b,fp);
154		let retv :BnGf2m = invb.mul_op(&a).mod_op(&fp);
155		ecsimple_log_trace!("r 0x{:X} = ( y 0x{:X} * xinv 0x{:X} % p 0x{:X} )",retv,a,invb,fp);
156		Ok(retv)
157	}
158
159	fn ladder_pre(&self, r :&mut ECGf2mPoint, s :&mut ECGf2mPoint, p :&ECGf2mPoint, bits :u64) {
160		let mut bs :BigInt;
161		bs = ecsimple_rand_bits(bits,-1,0);
162		s.z = BnGf2m::new_from_bigint(&bs);
163		//ecsimple_log_trace!("random s->Z 0x{:X}", s.z);
164
165		s.x = self.field_mul(&(p.x),&(s.z));
166		//ecsimple_log_trace!("s->X 0x{:X}", s.x);
167
168
169		bs = ecsimple_rand_bits(bits,-1,0);
170		r.y = BnGf2m::new_from_bigint(&bs);
171		//ecsimple_log_trace!("random r->Y 0x{:X}",r.y);
172		r.z = self.field_sqr(&(p.x));
173		r.x = self.field_sqr(&(r.z));
174		r.x = &r.x + &self.group.b;
175		r.z = self.field_mul(&(r.z),&(r.y));
176		r.x = self.field_mul(&(r.x),&(r.y));
177
178		ecsimple_log_trace!("r->X 0x{:X} r->Y 0x{:X} r->Z 0x{:X}", r.x,r.y,r.z);
179
180		return;
181	}
182
183	fn ladder_step(&self, r :&mut ECGf2mPoint, s :&mut ECGf2mPoint, p :&ECGf2mPoint) {
184		r.y = self.field_mul(&(r.z),&(s.x));
185		s.x = self.field_mul(&(r.x),&(s.z));
186		s.y = self.field_sqr(&(r.z));
187
188		r.z = self.field_sqr(&(r.x));
189		s.z = &r.y + &s.x;
190		s.z = self.field_sqr(&(s.z));
191		s.x = self.field_mul(&(r.y),&(s.x));
192		r.y = self.field_mul(&(s.z),&(p.x));
193		s.x = &s.x + &r.y;
194
195		r.y = self.field_sqr(&(r.z));
196		r.z = self.field_mul(&(r.z),&(s.y));
197		s.y = self.field_sqr(&(s.y));
198		s.y = self.field_mul(&(s.y),&(self.group.b));
199		r.x = &r.y + &s.y;
200
201		return;
202	}
203
204	fn make_affine(&self, _r :&mut ECGf2mPoint) {
205		return;
206	}
207
208	fn point_invert(&self, r :&mut ECGf2mPoint) {
209		if r.is_infinity() || r.y.is_zero() {
210			return;
211		}
212
213		self.make_affine(r);
214		r.y = &r.x + &r.y;
215		return;
216	}
217
218	fn field_inv(&self,a :&BnGf2m) -> BnGf2m {
219		let pbn :BnGf2m = BnGf2m::new_from_bigint(&self.group.p);
220		let bn = a.inv_op(&pbn).unwrap();
221		ecsimple_log_trace!("r 0x{:X} * a 0x{:X} = 1 % 0x{:X}", bn,a,pbn);
222		return bn;
223	}
224
225	fn ladder_post(&self,r :&mut ECGf2mPoint,s :&ECGf2mPoint,p :&ECGf2mPoint) {
226		if r.z.is_zero() {
227			r.infinity = true;
228			return;
229		}
230		if s.z.is_zero() {
231			*r = p.clone();
232			self.point_invert(r);
233			return;
234		}
235		let t0 :BnGf2m;
236		let mut t1 :BnGf2m;
237		let mut t2 :BnGf2m;
238
239		t0 = self.field_mul(&(r.z),&(s.z));
240		t1 = self.field_mul(&(p.x),&(r.z));
241		t1 = &r.x + &t1;
242		//ecsimple_log_trace!("t1 0x{:X}",t1);
243		t2 = self.field_mul(&(p.x),&(s.z));
244		r.z = self.field_mul(&(r.x),&t2);
245		t2 = &t2 + &s.x;
246		//ecsimple_log_trace!("t2 0x{:X}",t2);
247		t1 = self.field_mul(&t1,&t2);
248		t2 = self.field_sqr(&p.x);
249		t2 = &p.y + &t2;
250		//ecsimple_log_trace!("t2 0x{:X}",t2);
251		t2 = self.field_mul(&t2,&t0);
252		t1 = &t2 + &t1;
253		//ecsimple_log_trace!("t1 0x{:X}",t1);
254		t2 = self.field_mul(&p.x,&t0);
255		t2 = self.field_inv(&t2);
256		t1 = self.field_mul(&t1,&t2);
257		r.x = self.field_mul(&r.z,&t2);
258		t2 = &p.x + &r.x;
259		//ecsimple_log_trace!("t2 0x{:X}",t2);
260		t2 = self.field_mul(&t2,&t1);
261		r.y = &p.y + &t2;
262		//ecsimple_log_trace!("r->Y 0x{:X}",r.y);
263		r.z = BnGf2m::one();
264		//ecsimple_log_trace!("r->Z 0x{:X}",r.z);
265
266		return;
267	}
268
269	pub fn mulex_op(&self,bn1 :&BigInt,bn2 :&BigInt) -> Result<ECGf2mPoint,Box<dyn Error>> {
270		let retv :ECGf2mPoint;
271		let t :ECGf2mPoint = self.mul_op(bn1,false);
272		let r :ECGf2mPoint = self.mul_op(bn2,true);
273		retv = t.add_op_res(&r)?;
274
275		Ok(retv)
276	}
277
278	pub fn add_op_res(&self, other :&ECGf2mPoint) -> Result<ECGf2mPoint,Box<dyn Error>> {
279		if !self.group.eq_op(&other.group) {
280			ecsimple_new_error!{BnGf2mPointError,"self and other not same group"}
281		}
282		let mut retv :ECGf2mPoint = ECGf2mPoint::default();
283		let (x0,y0,x1,y1,mut x2,mut y2) : (BnGf2m,BnGf2m,BnGf2m,BnGf2m,BnGf2m,BnGf2m);
284		let (mut s, t) : (BnGf2m,BnGf2m);
285		if self.infinity || other.infinity {
286			if self.infinity {
287				retv = other.clone();
288			} else {
289				retv = self.clone();
290			}			
291			return Ok(retv);
292		} 
293		x0 = self.x.clone();
294		y0 = self.y.clone();
295		x1 = other.x.clone();
296		y1 = other.y.clone();
297		ecsimple_log_trace!("x0 0x{:X} y0 0x{:X}",x0,y0);
298		ecsimple_log_trace!("x1 0x{:X} y1 0x{:X}",x1,y1);
299		if !x0.eq_op(&x1) {
300			t = &x0 + &x1;
301			ecsimple_log_trace!("t 0x{:X} = x0 0x{:X} + x1 0x{:X}",t,x0,x1);
302			s = &y0 + &y1;
303			ecsimple_log_trace!("s 0x{:X} = y0 0x{:X} + y1 0x{:X}",s,y0,y1);
304			s = self.field_div(&s,&t)?;
305			x2 = self.field_sqr(&s);
306			x2 = &x2 + &self.group.a;
307			ecsimple_log_trace!("x2 0x{:X} group->a 0x{:X}",x2,self.group.a);
308			x2 = &x2 + &s;
309			ecsimple_log_trace!("x2 0x{:X} s 0x{:X}",x2,s);
310			x2 = &x2 + &t;
311			ecsimple_log_trace!("x2 0x{:X} t 0x{:X}",x2,t);
312		} else {
313			if y0.eq_op(&y1) || x1.is_one() {
314				retv = ECGf2mPoint::default();
315				retv.infinity = true;
316				return Ok(retv);
317			}
318			s = self.field_div(&y1,&x1)?;
319			s = &s + &x1;
320			ecsimple_log_trace!("s 0x{:X} x1 0x{:X}", s, x1);
321			x2 = self.field_sqr(&s);
322			x2 = &x2 + &s;
323			ecsimple_log_trace!("x2 0x{:X} s 0x{:X}",x2,s);
324			x2 = &x2 + &self.group.a;
325			ecsimple_log_trace!("x2 0x{:X} group->a 0x{:X}",x2,self.group.a);
326		}
327
328		y2 = &x1 + &x2;
329		ecsimple_log_trace!("y2 0x{:X} = x1 0x{:X} + x2 0x{:X}",y2,x1,x2);
330		y2 = self.field_mul(&y2,&s);
331		y2 = &y2 + &x2;
332		ecsimple_log_trace!("y2 0x{:X} x2 0x{:X}",y2,x2);
333		y2 = &y2 + &y1;
334		ecsimple_log_trace!("y2 0x{:X} y1 0x{:X}",y2,y1);
335
336		retv.x = x2.clone();
337		retv.y = y2.clone();
338		retv.z = BnGf2m::one();
339		retv.infinity = false;
340
341		ecsimple_log_trace!("r.x 0x{:X} r.y 0x{:X} r.z 0x{:X}", retv.x,retv.y,retv.z);
342
343		Ok(retv)
344	}
345
346
347	pub fn mul_op(&self, bn :&BigInt,copyxy :bool) -> ECGf2mPoint {
348		let zv :BigInt = zero();
349		let  p :ECGf2mPoint ;
350		let mut s :ECGf2mPoint = ECGf2mPoint::new(&self.group);
351		let mut r :ECGf2mPoint = ECGf2mPoint::new(&self.group);
352		let mut tmp :ECGf2mPoint;
353		let cardinal :BigInt;
354		let lamda :BigInt;
355		let mut k :BigInt;
356		if bn <= &zv {
357			r = self.clone();
358			r.infinity = true;
359			return r;
360		}
361
362		if self.infinity {
363			return self.clone();
364		}
365
366		if copyxy {
367			p = self.clone();
368		} else {
369			p = ECGf2mPoint::new(&self.group);
370		}
371
372
373		if self.group.order == zv || self.group.cofactor == zv {
374			panic!("group order 0x{:x} or group cofactor 0x{:x}", self.group.order, self.group.cofactor);
375		}
376
377		cardinal = &self.group.order * &self.group.cofactor;
378
379		//ecsimple_log_trace!("field 0x{:X} p 0x{:X}", self.group.p,self.group.p);
380		//ecsimple_log_trace!("group->a 0x{:X} a 0x{:X}", self.group.a,self.group.a);
381		//ecsimple_log_trace!("group->b 0x{:X} b 0x{:X}", self.group.b,self.group.b);
382		//ecsimple_log_trace!("cardinality 0x{:X} order 0x{:X} cofactor 0x{:X}",cardinal,self.group.order,self.group.cofactor);
383		//ecsimple_log_trace!("k 0x{:X} lambda 0x{:X}", k, lamda);
384		//ecsimple_log_trace!("k 0x{:X} lambda 0x{:X}", k, lamda);
385
386		k = bn.clone();
387		lamda = &k + &cardinal;
388		ecsimple_log_trace!("scalar 0x{:X} k 0x{:X}",k,k);
389		ecsimple_log_trace!("lambda 0x{:X}",lamda);
390
391		k = &lamda + &cardinal;
392		//ecsimple_log_trace!("k 0x{:X} cardinality 0x{:X}",k,cardinal);
393
394		let cardbits = get_max_bits(&cardinal);
395		let mut i :i32;
396		let mut pbit :i32 = 1;
397		let mut kbit :i32;
398		kbit = get_bit_set(&lamda,cardbits as i32);
399		if kbit != 0 {
400			//(lamda,k) = (k,lamda);
401			k = lamda;
402		}
403		//ecsimple_log_trace!("k 0x{:X} lambda 0x{:X} cardinality_bits 0x{:x}",k,lamda,cardbits);
404
405		s.x = BnGf2m::zero();
406		s.y = BnGf2m::zero();
407		s.z = BnGf2m::zero();
408
409		r.x = BnGf2m::zero();
410		r.y = BnGf2m::zero();
411		r.z = BnGf2m::zero();
412
413		//ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
414		//ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
415		//ecsimple_log_trace!("p.X 0x{:X} p.Y 0x{:X} p.Z 0x{:X}",p.x,p.y,p.z);
416
417
418
419		ecsimple_log_trace!("p.X 0x{:X} p.Y 0x{:X} p.Z 0x{:X}",p.x,p.y,p.z);
420
421		self.ladder_pre(&mut r,&mut s, &p, (get_max_bits(&self.group.p) - 1 ) as u64);
422
423		i = (cardbits - 1) as i32;
424		while i >= 0 {
425			kbit = get_bit_set(&k,i) ^ pbit;
426			ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
427			ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
428			ecsimple_log_trace!("[{}]kbit 0x{:x} pbit 0x{:x} [0x{:x}] bitset [0x{:x}]", i,kbit,pbit,i, get_bit_set(&k,i));
429
430			if kbit != 0 {
431				tmp = s.clone();
432				s = r.clone();
433				r = tmp.clone();
434			}
435
436			ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
437			ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
438
439			self.ladder_step(&mut r,&mut s,&p);
440
441			ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
442			ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
443			ecsimple_log_trace!("p.X 0x{:X} p.Y 0x{:X} p.Z 0x{:X}",p.x,p.y,p.z);
444
445			pbit ^= kbit;
446			i -= 1;
447		}
448
449		ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
450		ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
451
452		if pbit != 0 {
453			tmp = s.clone();
454			s = r.clone();
455			r = tmp.clone();
456		}
457
458		
459		ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
460		ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
461
462		self.ladder_post(&mut r,&mut s,&p);
463		//ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
464		ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
465		//ecsimple_log_trace!("p.X 0x{:X} p.Y 0x{:X} p.Z 0x{:X}",p.x,p.y,p.z);
466
467		return r;
468	}
469
470	pub fn get_affine_points(&self) -> Result<(BnGf2m,BnGf2m),Box<dyn Error>> {
471		if self.infinity {
472			ecsimple_new_error!{BnGf2mPointError,"is infinity"}
473		}
474		if ! self.z.is_one() {
475			ecsimple_new_error!{BnGf2mPointError,"z 0x{:X}",self.z}
476		}
477
478
479		Ok((self.x.clone(),self.y.clone()))
480	}
481
482	pub fn check_on_curve(&self) -> Result<(),Box<dyn Error>> {
483		let mut lh :BnGf2m;
484		let y2 :BnGf2m;
485		if self.infinity {
486			return Ok(());
487		}
488		if !self.z.is_one() {
489			ecsimple_new_error!{BnGf2mPointError,"z 0x{:X} not one",self.z}
490		}
491		lh = self.x.add_op(&self.group.a);
492		lh = self.field_mul(&lh,&self.x);
493		lh = lh.add_op(&self.y);
494		lh =self.field_mul(&lh,&self.x);
495		lh = lh.add_op(&self.group.b);
496		y2 = self.field_sqr(&self.y);
497		lh = lh.add_op(&y2);
498		if !lh.is_zero() {
499			ecsimple_new_error!{BnGf2mPointError,"x 0x{:X} y 0x{:X} not on group {}",self.x,self.y,self.group.curvename}
500		}
501		Ok(())
502	}
503
504
505}
506
507
508ecsimple_error_class!{ECPrimePointError}
509
510#[derive(Clone)]
511pub (crate) struct ECPrimePoint {
512	x :BigInt,
513	y :BigInt,
514	z :BigInt,
515	pub (crate) group :ECGroupPrime,
516	montv : MontNum,
517	infinity : bool,
518	z_is_one : bool,
519}
520
521impl std::fmt::Display for ECPrimePoint {
522	fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result {
523		write!(f,"curve[{}] isinfinity {} x 0x{:x} y 0x{:x} z 0x{:x}", self.group,self.infinity,self.x,self.y,self.z)
524	}
525}
526
527impl PartialEq for ECPrimePoint {
528	fn eq(&self, other:&Self) -> bool {
529		return self.eq_op(other);
530	}
531
532	fn ne(&self, other:&Self) -> bool {
533		return ! self.eq_op(other);
534	}
535}
536
537
538impl std::default::Default for ECPrimePoint {
539	fn default() -> Self {
540		let ov :BigInt = one();
541		let tv :BigInt = ov.clone() + ov.clone() + ov.clone();
542		ECPrimePoint {
543			x : zero(),
544			y : zero(),
545			z : zero(),
546			group : ECGroupPrime::default(),
547			montv : MontNum::new(&tv).unwrap(),
548			infinity : true,
549			z_is_one : true,
550		}
551	}
552}
553
554impl ECPrimePoint {
555	pub (crate) fn new(grp :&ECGroupPrime) -> ECPrimePoint {
556		let pnt :ECPrimePoint = ECPrimePoint {
557			x : grp.generator.x.clone(),
558			y : grp.generator.y.clone(),
559			z : grp.generator.z.clone(),
560			group : grp.clone(),
561			montv : MontNum::new(&grp.p).unwrap(),
562			infinity : false,
563			z_is_one : true,
564		};
565		return pnt;
566	}
567
568	pub (crate) fn new_point(x :&BigInt, y :&BigInt,z :&BigInt, grp :&ECGroupPrime) -> Self {
569		let pnt : ECPrimePoint = Self {
570			x :x.clone(),
571			y :y.clone(),
572			z :z.clone(),
573			group :grp.clone(),
574			montv : MontNum::new(&grp.p).unwrap(),
575			infinity : false,
576			z_is_one : true,
577		};
578		return pnt;
579	}
580
581
582	pub fn set_x(&mut self, x :&BigInt) {
583		self.x = x.clone();
584	}
585
586	pub fn set_y(&mut self, y :&BigInt) {
587		self.y = y.clone();
588	}
589
590	pub fn set_z(&mut self, z :&BigInt) {
591		self.z = z.clone();
592	}
593
594
595	pub fn x(&self) -> BigInt {
596		return self.x.clone();
597	}
598
599	pub fn y(&self) -> BigInt {
600		return self.y.clone();
601	}
602
603	#[allow(dead_code)]
604	pub fn z(&self) -> BigInt {
605		return self.z.clone();
606	}
607
608
609	pub fn field_sqr(&self,a :&BigInt) -> BigInt {
610		let retv :BigInt = self.montv.mont_mul(a,a);
611		ecsimple_log_trace!("r 0x{:X} = a 0x{:X} ^ 2 % group.field 0x{:X}",retv,a,self.group.p);
612		return retv;
613	}
614
615	pub fn field_mul(&self,a :&BigInt,b :&BigInt) -> BigInt {
616		let retv :BigInt = self.montv.mont_mul(a,b);
617		ecsimple_log_trace!("r 0x{:X} = a 0x{:X} * b 0x{:X} % m 0x{:X}",retv,a,b,self.group.p);
618		return retv;
619	}
620
621	pub fn sub_mod_quick(&self,a :&BigInt,b :&BigInt,m :&BigInt) -> BigInt {
622		let mut r :BigInt;
623		let zv :BigInt = zero();
624		r = a - b;
625		if r < zv {
626			r += m;
627		}
628		return r;
629	}
630
631	pub (crate) fn lshift_mod_quick(&self,a :&BigInt,sn :i64, m :&BigInt) -> BigInt {
632		let r :BigInt;
633		r = a << sn;
634		return r % m;
635	}
636
637	pub (crate) fn lshift1_mod_quick(&self,a :&BigInt,m :&BigInt) -> BigInt {
638		let r :BigInt;
639		r = a << 1;
640		return r % m;
641	}
642
643	pub (crate) fn add_mod_quick(&self,a :&BigInt,b :&BigInt, m :&BigInt) -> BigInt {
644		let retv :BigInt;
645		retv = a + b;
646		return retv % m;
647	}
648
649	fn field_encode(&self,a :&BigInt) -> BigInt {
650		let retv :BigInt;
651		retv = self.montv.mont_to(a);
652		ecsimple_log_trace!("r 0x{:X} = BN_to_montgomery(a 0x{:X},field 0x{:X});",retv,a,self.group.p);
653		return retv;
654	}
655
656
657	#[allow(unused_variables)]
658	fn ladder_pre(&self, r :&mut ECPrimePoint, s :&mut ECPrimePoint, p :&ECPrimePoint, bits :u64) {
659		let mut rndv :BigInt;
660		let zv :BigInt = zero();
661		ecsimple_log_trace!("ladder_pre");
662		/*
663		* t1 s.z
664		* t2 r.z
665		* t3 s.x
666		* t4 r.x
667		* t5 s.y
668		*/
669		s.x = self.field_sqr(&p.x);
670		r.x = self.sub_mod_quick(&s.x,&self.group.a,&self.group.p);
671		ecsimple_log_trace!("r.x 0x{:X} = sub_mod_quick(s.x 0x{:X},group.a 0x{:X},group.field 0x{:X})",r.x,s.x,self.group.a,self.group.p);
672		r.x = self.field_sqr(&r.x);
673		s.y = self.field_mul(&p.x,&self.group.b);
674		s.y = self.lshift_mod_quick(&s.y,3,&self.group.p);
675		ecsimple_log_trace!("s.y 0x{:X} = s.y << 3 % 0x{:X}",s.y,self.group.p);
676		r.x = self.sub_mod_quick(&r.x,&s.y,&self.group.p);
677		ecsimple_log_trace!("r.X 0x{:X} = sub_mod_quick(r.x 0x{:X},s.y 0x{:X},group.field 0x{:X})",r.x,r.x,s.y,self.group.p);
678		s.z = self.add_mod_quick(&s.x,&self.group.a,&self.group.p);
679		ecsimple_log_trace!("s.z 0x{:X} = add_mod_quick(s.x 0x{:X},group.a 0x{:X},group.field 0x{:X})",s.z,s.x,self.group.a,self.group.p);
680
681		r.z = self.field_mul(&p.x,&s.z);
682		r.z = self.add_mod_quick(&self.group.b,&r.z,&self.group.p);
683		ecsimple_log_trace!("r.z 0x{:X} = add_mod_quick(group.b 0x{:X},r.z,group.field 0x{:X})",r.z,self.group.b,self.group.p);
684		r.z = self.lshift_mod_quick(&r.z,2,&self.group.p);
685		ecsimple_log_trace!("r.z 0x{:X} = lshift_mod_quick(r.z,2,group.field 0x{:X})", r.z,self.group.p);
686		ecsimple_log_trace!("before rnd points");
687		loop {
688			rndv = ecsimple_private_rand_range(&self.group.p);
689			if rndv != zv {
690				r.y = rndv.clone();
691				break;
692			}	
693		}
694		
695		loop {
696			rndv = ecsimple_private_rand_range(&self.group.p);
697			if rndv != zv {
698				s.z = rndv.clone();
699				break;
700			}
701		}
702		ecsimple_log_trace!("after rnd points");
703
704		r.y = self.field_encode(&r.y);
705		s.z = self.field_encode(&s.z);
706
707		r.z = self.field_mul(&r.z,&r.y);
708		r.x = self.field_mul(&r.x,&r.y);
709
710		s.x = self.field_mul(&p.x,&s.z);
711
712
713
714		return;
715	}
716
717	fn ladder_step(&self, r :&mut ECPrimePoint, s :&mut ECPrimePoint, p :&ECPrimePoint) {
718		let mut t0 :BigInt;
719		let mut t1 :BigInt;
720		let t2 :BigInt;
721		let mut t3 :BigInt;
722		let mut t4 :BigInt;
723		let mut t5 :BigInt;
724		let mut t6 :BigInt;
725
726		t6 = self.field_mul(&r.x,&s.x);
727		t0 = self.field_mul(&r.z,&s.z);
728		t4 = self.field_mul(&r.x,&s.z);
729		t3 = self.field_mul(&r.z,&s.x);
730		t5 = self.field_mul(&self.group.a,&t0);
731		t5 = self.add_mod_quick(&t6,&t5,&self.group.p);
732		ecsimple_log_trace!("add_mod_quick(t5 0x{:X},t6 0x{:X},t5,group.field 0x{:X})",t5,t6,self.group.p);
733		t6 = self.add_mod_quick(&t3,&t4,&self.group.p);
734		ecsimple_log_trace!("add_mod_quick(t6 0x{:X},t3 0x{:X},t4 0x{:X},group.field 0x{:X})",t6,t3,t4,self.group.p);
735		t5 = self.field_mul(&t6,&t5);
736		t0 = self.field_sqr(&t0);
737		t2 = self.lshift_mod_quick(&self.group.b,2,&self.group.p);
738		ecsimple_log_trace!("mod_lshift_quick(t2 0x{:X},group.b 0x{:X},2,group.field 0x{:X})",t2,self.group.b,self.group.p);
739		t0 = self.field_mul(&t2,&t0);
740		t5 = self.lshift1_mod_quick(&t5 , &self.group.p);
741		ecsimple_log_trace!("lshift1_mod_quick(t5 0x{:X},t5,group.field 0x{:X})",t5,self.group.p);
742		t3 = self.sub_mod_quick(&t4,&t3,&self.group.p);
743		ecsimple_log_trace!("sub_mod_quick(t3 0x{:X},t4 0x{:X},t3,group.field 0x{:X})",t3,t4,self.group.p);
744		s.z = self.field_sqr(&t3);
745		t4 = self.field_mul(&s.z,&p.x);
746		t0 = self.add_mod_quick(&t0,&t5,&self.group.p);
747		ecsimple_log_trace!("add_mod_quick(t0 0x{:X},t0,t5 0x{:X},group.field 0x{:X})",t0,t5,self.group.p);
748		s.x = self.sub_mod_quick(&t0,&t4,&self.group.p);
749		ecsimple_log_trace!("sub_mod_quick(s.x 0x{:X},t0 0x{:X},t4 0x{:X},group.field 0x{:X})",s.x,t0,t4,self.group.p);
750		t4 = self.field_sqr(&r.x);
751		t5 = self.field_sqr(&r.z);
752		t6 = self.field_mul(&t5,&self.group.a);
753		ecsimple_log_trace!("new t6 0x{:X}",t6);
754		t1 = self.add_mod_quick(&r.x,&r.z,&self.group.p);
755		ecsimple_log_trace!("add_mod_quick(t1 0x{:X},r.x 0x{:X},r.z 0x{:X},group.field 0x{:X})",t1,r.x,r.z,self.group.p);
756		t1 = self.field_sqr(&t1);
757		t1 = self.sub_mod_quick(&t1,&t4,&self.group.p);
758		ecsimple_log_trace!("sub_mod_quick(t1 0x{:X},t1,t4 0x{:X},group.field 0x{:X})",t1,t4,self.group.p);
759		t1 = self.sub_mod_quick(&t1,&t5,&self.group.p);
760		ecsimple_log_trace!("sub_mod_quick(t1 0x{:X},t1,t5 0x{:X},group.field 0x{:X})",t1,t5,self.group.p);
761		t3 = self.sub_mod_quick(&t4,&t6,&self.group.p);
762		ecsimple_log_trace!("sub_mod_quick(t3 0x{:X},t4 0x{:X},t6 0x{:X},group.field 0x{:X})",t3,t4,t6,self.group.p);
763		t3 = self.field_sqr(&t3);
764		t0 = self.field_mul(&t5,&t1);
765		t0 = self.field_mul(&t2,&t0);
766		r.x = self.sub_mod_quick(&t3,&t0,&self.group.p);
767		ecsimple_log_trace!("sub_mod_quick(r.x 0x{:X},t3 0x{:X},t0 0x{:X},group.field 0x{:X})",r.x,t3,t0,self.group.p);
768		t3 = self.add_mod_quick(&t4,&t6,&self.group.p);
769		ecsimple_log_trace!("add_mod_quick(t3 0x{:X},t4 0x{:X},t6 0x{:X},group.field 0x{:X})",t3,t4,t6,self.group.p);
770		t4 = self.field_sqr(&t5);
771		t4 = self.field_mul(&t4,&t2);
772		t1 = self.field_mul(&t1,&t3);
773		t1 = self.lshift1_mod_quick(&t1,&self.group.p);
774		ecsimple_log_trace!("lshift1_mod_quick(t1 0x{:X},t1,group.field 0x{:X})",t1,self.group.p);
775		r.z = self.add_mod_quick(&t4,&t1,&self.group.p);
776		ecsimple_log_trace!("add_mod_quick(r.z 0x{:X},t4 0x{:X},t1 0x{:X},group.field 0x{:X})",r.z,t4,t1,self.group.p);
777		return;
778	}
779
780	pub (crate) fn field_decode(&self,a :&BigInt) -> BigInt {
781		let retv :BigInt =  self.montv.mont_from(a);
782		return retv;
783	}
784
785	fn field_inv(&self,a :&BigInt) -> BigInt {
786		let ov :BigInt = one();
787
788		let e :BigInt = &self.group.p - &ov - &ov;
789		let retv:BigInt =  self.montv.mont_pow(a,&e);
790		ecsimple_log_trace!("field_inv(r 0x{:X},a 0x{:X},e 0x{:X},group.field 0x{:X})",retv,a,e,self.group.p);
791		return retv;
792	}
793
794	fn field_set_to_one(&self) -> BigInt {
795		let retv :BigInt = self.group.generator.z.clone();
796		ecsimple_log_trace!("set_to_one(r 0x{:X})",retv);
797		return retv;
798	}
799
800	fn ladder_post(&self, r :&mut ECPrimePoint, s :&mut ECPrimePoint, p :&ECPrimePoint) {
801		let mut t0 :BigInt;
802		let mut t1 :BigInt;
803		let t2 :BigInt;
804		let t3 :BigInt;
805		let t4 :BigInt;
806		let t5 :BigInt;
807		let mut t6 :BigInt;
808
809		t4 = self.lshift1_mod_quick(&p.y,&self.group.p);
810		ecsimple_log_trace!("lshift1_mod_quick(t4 0x{:X},p.y 0x{:X},group.field 0x{:X})",t4,p.y,self.group.p);
811		t6 = self.field_mul(&r.x,&t4);
812		t6 = self.field_mul(&s.z,&t6);
813		t5 = self.field_mul(&r.z,&t6);
814
815		t1 = self.lshift1_mod_quick(&self.group.b,&self.group.p);
816		ecsimple_log_trace!("lshift1_mod_quick(t1 0x{:X},group.b 0x{:X},group.field 0x{:X})",t1,self.group.b,self.group.p);
817		t1 = self.field_mul(&s.z,&t1);
818		t3 = self.field_sqr(&r.z);
819		t2 = self.field_mul(&t3,&t1);
820		t6 = self.field_mul(&r.z,&self.group.a);
821		t1 = self.field_mul(&p.x,&r.x);
822		t1 = self.add_mod_quick(&t1,&t6,&self.group.p);
823		ecsimple_log_trace!("add_mod_quick(t1 0x{:X},t1,t6 0x{:X},group.field 0x{:X})",t1,t6,self.group.p);
824		t1 = self.field_mul(&s.z,&t1);
825		t0 = self.field_mul(&p.x,&r.z);
826		t6 = self.add_mod_quick(&r.x,&t0,&self.group.p);
827		ecsimple_log_trace!("add_mod_quick(t6 0x{:X},r.x 0x{:X},t0 0x{:X},group.field 0x{:X})",t6,r.x,t0,self.group.p);
828		t6 = self.field_mul(&t6,&t1);
829		t6 = self.add_mod_quick(&t6,&t2,&self.group.p);
830		ecsimple_log_trace!("add_mod_quick(t6 0x{:X},t6,t2 0x{:X},group.field 0x{:X})",t6,t2,self.group.p);
831		t0 = self.sub_mod_quick(&t0,&r.x,&self.group.p);
832		ecsimple_log_trace!("sub_mod_quick(t0 0x{:X},t0,r.x 0x{:X},group.field 0x{:X})",t0,r.x,self.group.p);
833		t0 = self.field_sqr(&t0);
834		t0 = self.field_mul(&t0,&s.x);
835		t0 = self.sub_mod_quick(&t6,&t0,&self.group.p);
836		ecsimple_log_trace!("sub_mod_quick(t0 0x{:X},t6 0x{:X},t0,group.field 0x{:X})",t0,t6,self.group.p);
837		t1 = self.field_mul(&s.z,&t4);
838		t1 = self.field_mul(&t3,&t1);
839		t1 = self.field_decode(&t1);
840		t1 = self.field_inv(&t1);
841		t1 = self.field_encode(&t1);
842		r.x = self.field_mul(&t5,&t1);
843		r.y = self.field_mul(&t0,&t1);
844		r.z = self.field_set_to_one();
845
846		return;
847	}
848
849	pub fn get_affine_coordinates(&self,r :&ECPrimePoint) -> ECPrimePoint  {
850		ecsimple_log_trace!("point.X 0x{:X} point.Y 0x{:X} point.Z 0x{:X}",r.x,r.y,r.z);
851		let mut retv :ECPrimePoint = r.clone();
852		retv.z = self.montv.mont_from(&r.z);
853		retv.x = self.montv.mont_from(&r.x);
854		retv.y = self.montv.mont_from(&r.y);
855		ecsimple_log_trace!("x 0x{:X} y 0x{:X} z 0x{:X}",retv.x,retv.y,retv.z);
856		return retv;
857	}
858
859	pub fn set_affine_coordinates(&self,x :&BigInt,y :&BigInt,z :&BigInt) -> Result<ECPrimePoint,Box<dyn Error>> {
860		let mut retv :ECPrimePoint = ECPrimePoint::new(&self.group);
861		ecsimple_log_trace!("field 0x{:X}",self.group.p);
862		ecsimple_log_trace!("x 0x{:X} y 0x{:X} z 0x{:X}",x,y,z);
863		retv.x = nmod(x,&self.group.p);
864		ecsimple_log_trace!("point->X 0x{:X} = x 0x{:X} % group->field 0x{:X}", retv.x,x,self.group.p);
865		retv.x = self.field_encode(&retv.x);
866		ecsimple_log_trace!("field_encode point->X 0x{:X}",retv.x);
867
868		retv.y = nmod(y,&self.group.p);
869		ecsimple_log_trace!("point->Y 0x{:X} = y 0x{:X} % group->field 0x{:X}", retv.y,y,self.group.p);
870		retv.y = self.field_encode(&retv.y);
871		ecsimple_log_trace!("field_encode point->Y 0x{:X}",retv.y);
872
873		retv.z = nmod(z,&self.group.p);
874		ecsimple_log_trace!("point->Z 0x{:X} = z 0x{:X} % group->field 0x{:X}",retv.z,z,self.group.p);
875		retv.z = self.field_set_to_one();
876		ecsimple_log_trace!("field_set_to_one point->Z 0x{:X}",retv.z);
877
878		Ok(retv)
879	}
880
881
882
883
884
885	#[allow(unused_assignments)]
886	#[allow(unused_variables)]
887	pub fn mul_op(&self, bn :&BigInt,copyxy :bool ) -> ECPrimePoint {
888		let zv :BigInt = zero();
889		let  p :ECPrimePoint ;
890		let mut s :ECPrimePoint = ECPrimePoint::new(&self.group);
891		let mut r :ECPrimePoint = ECPrimePoint::new(&self.group);
892		let mut tmp :ECPrimePoint;
893		let cardinal :BigInt;
894		let mut lamda :BigInt = zero();
895		let mut k :BigInt = zero();
896		if bn <= &zv {
897			r = self.clone();
898			r.infinity = true;
899			return r;
900		}
901
902		if self.infinity {
903			return self.clone();
904		}
905
906		if copyxy {
907			p = self.clone();
908		} else {
909			p = ECPrimePoint::new(&self.group);
910		}
911		ecsimple_log_trace!("p.x 0x{:X} p.y 0x{:X} p.z 0x{:X}",p.x,p.y,p.z);
912
913
914		if self.group.order == zv || self.group.cofactor == zv {
915			panic!("group order 0x{:x} or group cofactor 0x{:x}", self.group.order, self.group.cofactor);
916		}
917
918		cardinal = &self.group.order * &self.group.cofactor;
919
920		//ecsimple_log_trace!("field 0x{:X} p 0x{:X}", self.group.p,self.group.p);
921		//ecsimple_log_trace!("group->a 0x{:X} a 0x{:X}", self.group.a,self.group.a);
922		//ecsimple_log_trace!("group->b 0x{:X} b 0x{:X}", self.group.b,self.group.b);
923		//ecsimple_log_trace!("cardinality 0x{:X} order 0x{:X} cofactor 0x{:X}",cardinal,self.group.order,self.group.cofactor);
924		ecsimple_log_trace!("k 0x{:X} lambda 0x{:X}", k, lamda);
925		//ecsimple_log_trace!("k 0x{:X} lambda 0x{:X}", k, lamda);
926
927		k = bn.clone();
928		lamda = &k + &cardinal;
929		ecsimple_log_trace!("scalar 0x{:X} k 0x{:X}",k,k);
930		ecsimple_log_trace!("lambda 0x{:X}",lamda);
931
932		let mut kbit :i32;
933		k = &lamda + &cardinal;
934		ecsimple_log_trace!("k 0x{:X} cardinality 0x{:X}",k,cardinal);
935
936		let cardbits = get_max_bits(&cardinal);
937		kbit = get_bit_set(&lamda,cardbits as i32);
938		if kbit != 0 {
939			(lamda,k) = (k,lamda);
940		}
941
942		let mut i :i32;
943		let mut pbit :i32 = 1;
944		ecsimple_log_trace!("k 0x{:X} lambda 0x{:X} cardinality_bits 0x{:x}",k,lamda,cardbits);
945
946		s.x = zero();
947		s.y = zero();
948		s.z = zero();
949
950		r.x = zero();
951		r.y = zero();
952		r.z = zero();
953
954		//ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
955		//ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
956		//ecsimple_log_trace!("p.X 0x{:X} p.Y 0x{:X} p.Z 0x{:X}",p.x,p.y,p.z);
957
958
959
960		ecsimple_log_trace!("p.X 0x{:X} p.Y 0x{:X} p.Z 0x{:X}",p.x,p.y,p.z);
961
962
963		ecsimple_log_trace!("p.X 0x{:X} p.Y 0x{:X} p.Z 0x{:X}",p.x,p.y,p.z);
964		self.ladder_pre(&mut r,&mut s, &p, (get_max_bits(&self.group.p) - 1 ) as u64);
965
966		i = (cardbits - 1) as i32;
967		while i >= 0 {
968			kbit = get_bit_set(&k,i) ^ pbit;
969			ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
970			ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
971			ecsimple_log_trace!("[{}]kbit 0x{:x} pbit 0x{:x} [0x{:x}] bitset [0x{:x}]", i,kbit,pbit,i, get_bit_set(&k,i));
972
973			if kbit != 0 {
974				tmp = s.clone();
975				s = r.clone();
976				r = tmp.clone();
977			}
978
979			ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
980			ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
981
982			self.ladder_step(&mut r,&mut s,&p);
983
984			ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
985			ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
986			ecsimple_log_trace!("p.X 0x{:X} p.Y 0x{:X} p.Z 0x{:X}",p.x,p.y,p.z);
987
988			pbit ^= kbit;
989			i -= 1;
990		}
991
992		ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
993		ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
994
995		if pbit != 0 {
996			tmp = s.clone();
997			s = r.clone();
998			r = tmp.clone();
999		}
1000
1001		
1002		ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
1003		ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
1004
1005		self.ladder_post(&mut r,&mut s,&p);
1006		//ecsimple_log_trace!("s.X 0x{:X} s.Y 0x{:X} s.Z 0x{:X}",s.x,s.y,s.z);
1007		ecsimple_log_trace!("r.X 0x{:X} r.Y 0x{:X} r.Z 0x{:X}",r.x,r.y,r.z);
1008		//ecsimple_log_trace!("p.X 0x{:X} p.Y 0x{:X} p.Z 0x{:X}",p.x,p.y,p.z);
1009
1010		r = self.get_affine_coordinates(&r);
1011
1012		return r;
1013	}
1014
1015	pub fn check_on_curve(&self) -> Result<(),Box<dyn Error>> {
1016		let mut rh :BigInt;
1017		let ov :BigInt = one();
1018		let z4 :BigInt;
1019		let z6 :BigInt;
1020		let mut tmp :BigInt;
1021		let field :BigInt = self.group.p.clone();
1022
1023		rh = self.field_sqr(&self.x);
1024		if self.z != ov {
1025			tmp = self.field_sqr(&self.z);
1026			z4 = self.field_sqr(&tmp);
1027			z6 = self.field_mul(&z4,&tmp);
1028
1029			if self.group.is_minus3 {
1030				tmp = self.lshift1_mod_quick(&z4,&field);
1031				ecsimple_log_trace!("lshift1_mod_quick(tmp 0x{:X},Z4 0x{:X},p 0x{:X})",tmp,z4,field);
1032				tmp = self.add_mod_quick(&tmp,&z4,&field);
1033				ecsimple_log_trace!("add_mod_quick(tmp 0x{:X},tmp,Z4 0x{:X},p 0x{:X})",tmp,z4,field);
1034				rh = self.sub_mod_quick(&rh,&tmp,&field);
1035				ecsimple_log_trace!("sub_mod_quick(rh 0x{:X},rh,tmp 0x{:X},p 0x{:X})",rh,tmp,field);
1036				rh = self.field_mul(&rh,&self.x);
1037			} else {
1038				tmp = self.field_mul(&z4,&self.group.a);
1039				rh = self.add_mod_quick(&rh,&tmp,&field);
1040				ecsimple_log_trace!("add_mod_quick(rh 0x{:X},rh,tmp 0x{:X},p 0x{:X})",rh,tmp,field);
1041				rh = self.field_mul(&rh,&self.x);
1042			}
1043			tmp = self.field_mul(&self.group.b,&z6);
1044			rh = self.add_mod_quick(&rh,&tmp,&field);
1045			ecsimple_log_trace!("add_mod_quick(rh 0x{:X},rh,tmp 0x{:X},p 0x{:X})",rh,tmp,field);
1046		} else {
1047			rh = self.add_mod_quick(&rh,&self.group.a,&field);
1048			ecsimple_log_trace!("add_mod_quick(rh 0x{:X},rh,group.a 0x{:X},p 0x{:X})",rh, self.group.a,field);
1049			rh = self.field_mul(&rh,&self.x);
1050			rh = self.add_mod_quick(&rh,&self.group.b,&field);
1051			ecsimple_log_trace!("add_mod_quick(rh 0x{:X},rh,group.b 0x{:X},p 0x{:X})",rh,self.group.b,field);
1052		}
1053
1054		tmp = self.field_sqr(&self.y);
1055		if tmp != rh {
1056			ecsimple_new_error!{ECPrimePointError,"tmp 0x{:X} != rh 0x{:X}",tmp,rh}
1057		}
1058		Ok(())
1059	}
1060
1061	fn get_wnaf_variable(&self,bn :&BigInt) -> Result<(Vec<u8>,i32),Box<dyn Error>> {
1062		let wnaf_bit :i32 = get_wnaf_bits(bn);
1063		let curnaf :Vec<u8> = wnaf_value(bn,wnaf_bit)?;
1064		Ok((curnaf,wnaf_bit))
1065	}
1066
1067	fn dbl(&self) -> Result<ECPrimePoint,Box<dyn Error>> {
1068		let mut retv :ECPrimePoint = ECPrimePoint::new(&self.group);
1069		let zv :BigInt = zero();
1070		let field :BigInt = self.group.p.clone();
1071		let mut n0 :BigInt;
1072		let mut n1 :BigInt;
1073		let mut n2 :BigInt;
1074		let mut n3 :BigInt;
1075
1076		if self.infinity {
1077			retv.z = zv.clone();
1078			retv.z_is_one = false;
1079			return Ok(retv);
1080		}
1081
1082		if self.z_is_one {
1083			n0 = self.field_sqr(&self.x);
1084			n1 = self.lshift1_mod_quick(&n0,&field);
1085			ecsimple_log_trace!("mod_lshift_quick(n1 0x{:X},n0 0x{:X},p 0x{:X})",n1,n0,field);
1086			n0 = self.add_mod_quick(&n0,&n1,&field);
1087			ecsimple_log_trace!("mod_add_quick(n0 0x{:X},n0,n1 0x{:X},p 0x{:X})",n0,n1,field);
1088			n1 = self.add_mod_quick(&n0,&self.group.a,&field);
1089			ecsimple_log_trace!("mod_add_quick(n1 0x{:X},n0 0x{:X},group.a 0x{:X},p 0x{:X})",n1,n0,self.group.a,field);
1090			/* n1 = 3 * X_a^2 + a_curve */
1091		} else if self.group.is_minus3 {
1092			n1 = self.field_sqr(&self.z);
1093			n0 = self.add_mod_quick(&self.x,&n1,&field);
1094			ecsimple_log_trace!("mod_add_quick(n0 0x{:X},a.x 0x{:X},n1 0x{:X},p 0x{:X})",n0,self.x,n1,field);
1095			n2 = self.sub_mod_quick(&self.x,&n1,&field);
1096			ecsimple_log_trace!("mod_sub_quick(n2 0x{:X},a.x 0x{:X},n1 0x{:X},p 0x{:X})",n2,self.x,n1,field);
1097			n1 = self.field_mul(&n0,&n2);
1098			n0 = self.lshift1_mod_quick(&n1,&field);
1099			ecsimple_log_trace!("mod_lshift_quick(n0 0x{:X},n1 0x{:X},p 0x{:X})",n0, n1,field);
1100			n1 = self.add_mod_quick(&n0,&n1,&field);
1101			ecsimple_log_trace!("mod_add_quick(n1 0x{:X},n0 0x{:X},n1,p 0x{:X})",n1,n0,field);
1102	        /*-
1103	         * n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
1104	         *    = 3 * X_a^2 - 3 * Z_a^4
1105	         */
1106	     } else {
1107	     	n0 = self.field_sqr(&self.x);
1108	     	n1 = self.lshift1_mod_quick(&n0,&field);
1109	     	ecsimple_log_trace!("mod_lshift_quick(n1 0x{:X},n0 0x{:X},p 0x{:X})",n1,n0,field);
1110	     	n0 = self.add_mod_quick(&n0,&n1,&field);
1111	     	ecsimple_log_trace!("mod_add_quick(n0 0x{:X},n0,n1 0x{:X},p 0x{:X})",n0,n1,field);
1112	     	n1 = self.field_sqr(&self.z);
1113	     	n1 = self.field_sqr(&n1);
1114	     	n1 = self.field_mul(&n1,&self.group.a);
1115	     	n1 = self.add_mod_quick(&n1,&n0,&field);
1116	     	ecsimple_log_trace!("mod_add_quick(n1 0x{:X},n1,n0 0x{:X},p 0x{:X})",n1,n0,field);
1117	     	/* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
1118	     }
1119
1120	     if self.z_is_one {
1121	     	n0 = self.y.clone();
1122	     	ecsimple_log_trace!("BN_copy(n0 0x{:X},a.y 0x{:X})",n0,self.y);
1123	     } else {
1124	     	n0 = self.field_mul(&self.y,&self.z);
1125	     }
1126	     retv.z = self.lshift1_mod_quick(&n0,&field);
1127	     ecsimple_log_trace!("mod_lshift_quick(r.z 0x{:X},n0 0x{:X},p 0x{:X})",retv.z,n0,field);
1128	     retv.z_is_one = false;
1129	     /* Z_r = 2 * Y_a * Z_a */
1130
1131	     n3 = self.field_sqr(&self.y);
1132	     n2 = self.field_mul(&self.x,&n3);
1133	     n2 = self.lshift_mod_quick(&n2,2,&field);
1134	     ecsimple_log_trace!("mod_lshift_quick(n2 0x{:X},n2,0x2,p 0x{:X})",n2,field);
1135	     /* n2 = 4 * X_a * Y_a^2 */
1136
1137	     n0 = self.lshift1_mod_quick(&n2,&field);
1138	     ecsimple_log_trace!("mod_lshift_quick(n0 0x{:X},n2 0x{:X},p 0x{:X})",n0,n2,field);
1139	     retv.x = self.field_sqr(&n1);
1140	     retv.x = self.sub_mod_quick(&retv.x,&n0,&field);
1141	     ecsimple_log_trace!("mod_sub_quick(r.x 0x{:X},r.x,n0 0x{:X},p 0x{:X})",retv.x,n0,field);
1142	     /* X_r = n1^2 - 2 * n2 */
1143
1144
1145	     n0 = self.field_sqr(&n3);
1146	     n3 = self.lshift_mod_quick(&n0,0x3,&field);
1147	     ecsimple_log_trace!("mod_lshift_quick(n3 0x{:X},n0 0x{:X},0x3,p 0x{:X})",n3,n0,field);
1148	     /* n3 = 8 * Y_a^4 */
1149
1150	     n0 = self.sub_mod_quick(&n2,&retv.x,&field);
1151	     ecsimple_log_trace!("mod_sub_quick(n0 0x{:X},n2 0x{:X},r.x 0x{:X},p 0x{:X})",n0,n2,retv.x,field);
1152	     n0 = self.field_mul(&n1,&n0);
1153	     retv.y = self.sub_mod_quick(&n0,&n3,&field);
1154	     ecsimple_log_trace!("mod_sub_quick(r.y 0x{:X},n0 0x{:X},n3 0x{:X},p 0x{:X})",retv.y,n0,n3,field);
1155	     /* Y_r = n1 * (n2 - X_r) - n3 */
1156
1157	     Ok(retv)
1158	 }
1159
1160	 fn add(&self,b :&ECPrimePoint) -> Result<ECPrimePoint,Box<dyn Error>> {
1161	 	let mut retv :ECPrimePoint = ECPrimePoint::new(&self.group);
1162	 	let mut n0 :BigInt;
1163	 	let mut n1 :BigInt;
1164	 	let mut n2 :BigInt;
1165	 	let mut n3 :BigInt;
1166	 	let mut n4 :BigInt;
1167	 	let mut n5 :BigInt;
1168	 	let n6 :BigInt;
1169	 	let field :BigInt = self.group.p.clone();
1170	 	let zv :BigInt = zero();
1171	 	let ov :BigInt = one();
1172	 	let tv :BigInt = ov.clone() + ov.clone();
1173	 	if self.group != b.group {
1174	 		ecsimple_new_error!{ECPrimePointError,"not valid group point"}
1175	 	}
1176	 	if self == b {
1177	 		return self.dbl();
1178	 	} else if self.infinity {
1179	 		retv = b.clone();
1180	 		return Ok(retv);
1181	 	} else if b.infinity {
1182	 		retv= self.clone();
1183	 		return Ok(retv);
1184	 	}
1185
1186	 	if b.z_is_one {
1187	 		n1 = self.x.clone();
1188	 		ecsimple_log_trace!("BN_copy(n1 0x{:X},a.x 0x{:X})",n1,self.x);
1189	 		n2 = self.y.clone();
1190	 		ecsimple_log_trace!("BN_copy(n2 0x{:X},a.y 0x{:X})",n2,self.y);
1191	 		/* n1 = X_a */
1192	 		/* n2 = Y_a */
1193	 	} else {
1194	 		n0 = self.field_sqr(&b.z);
1195	 		n1 = self.field_mul(&self.x,&n0);
1196	 		/* n1 = X_a * Z_b^2 */
1197
1198	 		n0 = self.field_mul(&n0,&b.z);
1199	 		n2 = self.field_mul(&self.y,&n0);
1200	 		/* n2 = Y_a * Z_b^3 */
1201	 	}
1202
1203	 	if self.z_is_one {
1204	 		n3 = b.x.clone();
1205	 		ecsimple_log_trace!("BN_copy(n3 0x{:X},b.x 0x{:X})",n3,b.x);
1206	 		n4 = b.y.clone();
1207	 		ecsimple_log_trace!("BN_copy(n4 0x{:X},b.y 0x{:X})",n4,b.y);
1208	 		/* n3 = X_b */
1209	 		/* n4 = Y_b */
1210	 	} else {
1211	 		n0 = self.field_sqr(&self.z);
1212	 		n3 = self.field_mul(&b.x,&n0);
1213	 		/* n3 = X_b * Z_a^2 */
1214
1215	 		n0 = self.field_mul(&n0,&self.z);
1216	 		n4 = self.field_mul(&b.y,&n0);
1217	 		/* n4 = Y_b * Z_a^3 */
1218	 	}
1219
1220	 	n5 = self.sub_mod_quick(&n1,&n3,&field);
1221	 	ecsimple_log_trace!("mod_sub_quick(n5 0x{:X},n1 0x{:X},n3 0x{:X},p 0x{:X})",n5,n1,n3,field);
1222	 	n6 = self.sub_mod_quick(&n2,&n4,&field);
1223	 	ecsimple_log_trace!("mod_sub_quick(n6 0x{:X},n2 0x{:X},n4 0x{:X},p 0x{:X})",n6,n2,n4,field);
1224	 	/* n5 = n1 - n3 */
1225	 	/* n6 = n2 - n4 */
1226
1227	 	if n5 == zv {
1228	 		if n6 == zv {
1229	 			retv = self.dbl()?;
1230	 			ecsimple_log_trace!("a.x 0x{:X} a.y 0x{:X} a.z 0x{:X}",self.x,self.y,self.z);
1231	 			ecsimple_log_trace!("r.x 0x{:X} r.y 0x{:X} r.z 0x{:X}",retv.x,retv.y,retv.z);
1232	 			return Ok(retv);
1233	 		} else {
1234	 			retv.z = zv.clone();
1235	 			retv.z_is_one = false;
1236	 			ecsimple_log_trace!("r.z 0");
1237	 			return Ok(retv);
1238	 		}
1239	 	}
1240
1241	 	n1 = self.add_mod_quick(&n1,&n3,&field);
1242	 	ecsimple_log_trace!("mod_add_quick(n1 0x{:X},n1,n3 0x{:X},p 0x{:X})",n1,n3,field);
1243	 	n2 = self.add_mod_quick(&n2,&n4,&field);
1244	 	ecsimple_log_trace!("mod_add_quick(n2 0x{:X},n2,n4 0x{:X},p 0x{:X})",n2,n4,field);
1245	 	/* 'n7' = n1 + n3 */
1246	 	/* 'n8' = n2 + n4 */
1247
1248	 	if self.z_is_one && b.z_is_one {
1249	 		retv.z = n5.clone();
1250	 		ecsimple_log_trace!("BN_copy(r.z 0x{:X},n5 0x{:X})",retv.z,n5);
1251	 	} else {
1252	 		if self.z_is_one {
1253	 			n0 = b.z.clone();
1254	 			ecsimple_log_trace!("BN_copy(n0 0x{:X},b.z 0x{:X})",n0,b.z);
1255	 		} else if b.z_is_one {
1256	 			n0 = self.z.clone();
1257	 			ecsimple_log_trace!("BN_copy(n0 0x{:X},a.z 0x{:X})",n0,self.z);
1258	 		} else {
1259	 			n0 = self.field_mul(&self.z,&b.z);
1260	 		}
1261
1262	 		retv.z = self.field_mul(&n0,&n5);
1263	 	}
1264	 	retv.z_is_one = false;
1265	 	/* Z_r = Z_a * Z_b * n5 */
1266
1267	 	n0 = self.field_sqr(&n6);
1268	 	n4 = self.field_sqr(&n5);
1269	 	n3 = self.field_mul(&n1,&n4);
1270	 	retv.x = self.sub_mod_quick(&n0,&n3,&field);
1271	 	ecsimple_log_trace!("mod_sub_quick(r.x 0x{:X},n0 0x{:X},n3 0x{:X},p 0x{:X})",retv.x,n0,n3,field);
1272	 	/* X_r = n6^2 - n5^2 * 'n7' */
1273
1274	 	n0 = self.lshift1_mod_quick(&retv.x,&field);
1275	 	ecsimple_log_trace!("mod_lshift_quick(n0 0x{:X},r.x 0x{:X},p 0x{:X})",n0,retv.x,field);
1276	 	n0 = self.sub_mod_quick(&n3,&n0,&field);
1277	 	ecsimple_log_trace!("mod_sub_quick(n0 0x{:X},n3 0x{:X},n0,p 0x{:X})",n0,n3,field);
1278	 	/* n9 = n5^2 * 'n7' - 2 * X_r */
1279
1280	 	n0 = self.field_mul(&n0,&n6);
1281	 	n5 = self.field_mul(&n4,&n5);
1282	 	n1 = self.field_mul(&n2,&n5);
1283	 	n0 = self.sub_mod_quick(&n0,&n1,&field);
1284	 	ecsimple_log_trace!("mod_sub_quick(n0 0x{:X},n0,n1 0x{:X},p 0x{:X})",n0,n1,field);
1285
1286	 	if (n0.clone() % tv.clone()) != zv {
1287	 		n0 = n0.clone() + field.clone();
1288	 		ecsimple_log_trace!("BN_add(n0 0x{:X},n0,p 0x{:X})",n0,field);
1289	 	}
1290	 	/* now  0 <= n0 < 2*p,  and n0 is even */
1291
1292	 	retv.y = n0.clone() >> 1;
1293	 	ecsimple_log_trace!("BN_rshift1(r.y 0x{:X},n0 0x{:X})",retv.y,n0);
1294	 	/* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
1295
1296	 	Ok(retv)
1297	 }
1298
1299	 pub fn eq_op(&self, other :&ECPrimePoint) -> bool {
1300	 	if self.group != other.group {
1301	 		return false;
1302	 	}
1303	 	if self.infinity != other.infinity {
1304	 		return false;
1305	 	}
1306
1307	 	if self.infinity && other.infinity {
1308	 		return true;
1309	 	}
1310
1311	 	if self.x != other.x {
1312	 		return false;
1313	 	}
1314
1315	 	if self.y != other.y {
1316	 		return false;
1317	 	}
1318
1319	 	if self.z != other.z {
1320	 		return false;
1321	 	}
1322
1323	 	return true;
1324	 }
1325
1326	 fn points_make_affine(&self,points :&mut [ECPrimePoint]) -> Result<(),Box<dyn Error>> {
1327	 	let mut tmp :BigInt;
1328	 	let mut tmp_z :BigInt;
1329	 	let mut prod_z :Vec<BigInt> = Vec::new();
1330	 	let zv :BigInt = zero();
1331	 	let mut idx :usize;
1332	 	if points.len() == 0 {
1333	 		return Ok(());
1334	 	}
1335	 	while prod_z.len() < points.len() {
1336	 		prod_z.push(zv.clone());
1337	 	}
1338
1339	 	if points[0].z != zv {
1340	 		prod_z[0] = points[0].z.clone();
1341	 		ecsimple_log_trace!("BN_copy(prod_Z[0] 0x{:X},points[0].z 0x{:X})",prod_z[0],points[0].z);
1342	 	} else {
1343	 		prod_z[0] = self.field_set_to_one();
1344	 	}
1345
1346	 	idx = 1;
1347	 	while idx < points.len() {
1348	 		if points[idx].z != zv {
1349	 			prod_z[idx] = self.field_mul(&prod_z[idx-1],&points[idx].z);
1350	 		} else {
1351	 			prod_z[idx] = prod_z[idx-1].clone();
1352	 			ecsimple_log_trace!("BN_copy(prod_Z[{}] 0x{:X},prod_Z[{}] 0x{:X})",idx,prod_z[idx],idx-1,prod_z[idx-1]);
1353	 		}
1354	 		idx += 1;
1355	 	}
1356
1357	 	tmp = self.field_inv(&prod_z[prod_z.len() - 1]);
1358
1359	 	tmp = self.field_encode(&tmp);
1360	 	tmp = self.field_encode(&tmp);
1361
1362	 	idx = points.len() - 1;
1363	 	while idx > 0 {
1364	 		if points[idx].z != zv {
1365	 			tmp_z = self.field_mul(&prod_z[idx-1],&tmp);
1366	 			tmp = self.field_mul(&tmp,&points[idx].z);
1367	 			points[idx].z = tmp_z.clone();
1368	 		}
1369	 		idx -= 1;
1370	 	}
1371
1372	 	if points[0].z != zv  {
1373	 		points[0].z = tmp.clone();
1374	 	}
1375
1376	 	idx = 0;
1377	 	while idx < points.len() {
1378	 		if points[idx].z != zv {
1379	 			tmp = self.field_sqr(&points[idx].z);
1380	 			points[idx].x = self.field_mul(&points[idx].x,&tmp);
1381	 			tmp = self.field_mul(&tmp,&points[idx].z);
1382	 			points[idx].y = self.field_mul(&points[idx].y,&tmp);
1383	 			points[idx].z = self.field_set_to_one();
1384	 			points[idx].z_is_one = true;
1385	 		}
1386	 		idx += 1;
1387	 	}
1388	 	Ok(())
1389	 }
1390
1391	 fn invert(&self) -> Result<ECPrimePoint,Box<dyn Error>> {
1392	 	let mut retv :ECPrimePoint = self.clone();
1393	 	let zv :BigInt = zero();
1394	 	let field :BigInt = self.group.p.clone();
1395	 	if retv.z == zv || retv.y == zv {
1396	 		return Ok(retv);
1397	 	}
1398
1399	 	retv.y = bnusub(&field,&retv.y);
1400	 	ecsimple_log_trace!("BN_usub(p.y 0x{:X},group.field 0x{:X},p.y)",retv.y,field);
1401	 	Ok(retv)
1402	 }
1403
1404	 fn blind_coordinate(&self) -> Result<ECPrimePoint,Box<dyn Error>> {
1405	 	let mut retv :ECPrimePoint = self.clone();
1406	 	let zv :BigInt = zero();
1407	 	let mut lambda :BigInt;
1408	 	let mut temp :BigInt;
1409	 	loop {
1410	 		lambda = ecsimple_private_rand_range(&self.group.p);
1411	 		if lambda != zv {
1412	 			break;
1413	 		}
1414	 	}
1415
1416	 	lambda = self.field_encode(&lambda);
1417	 	ecsimple_log_trace!("field_encode");
1418	 	retv.z = self.field_mul(&retv.z,&lambda);
1419	 	ecsimple_log_trace!("field_mul");
1420	 	temp = self.field_sqr(&lambda);
1421	 	ecsimple_log_trace!("field_sqr");
1422	 	retv.x = self.field_mul(&retv.x,&temp);
1423	 	ecsimple_log_trace!("field_mul");
1424	 	temp = self.field_mul(&temp,&lambda);
1425	 	ecsimple_log_trace!("field_mul");
1426	 	retv.y = self.field_mul(&retv.y,&temp);
1427	 	ecsimple_log_trace!("field_mul");
1428	 	retv.z_is_one = false;
1429
1430	 	Ok(retv)
1431	 }
1432
1433	 fn point_set_infinity(&mut self) {
1434	 	self.z_is_one = false;
1435	 	self.z = zero();
1436	 	self.infinity = true;
1437	 	return;
1438	 }
1439
1440	 pub fn mulex_op(&self,bn1 :&BigInt,bn2 :&BigInt) -> Result<ECPrimePoint,Box<dyn Error>> {
1441	 	let mut retv :ECPrimePoint = self.clone();
1442
1443	 	let mut val_sub :Vec<Vec<ECPrimePoint>> = Vec::new();
1444	 	let mut wnaf_bits :Vec<i32> = Vec::new();
1445	 	let mut wnaf :Vec<Vec<u8>> = Vec::new();
1446	 	let mut curnaf :Vec<u8>;
1447	 	let mut bits :i32;
1448	 	let mut cv :Vec<ECPrimePoint>;
1449	 	let mut idx :usize;
1450	 	let mut tmp :ECPrimePoint;
1451	 	let mut jdx :usize;
1452	 	let mut affinepoints :Vec<ECPrimePoint>;
1453	 	let mut affidx :usize;
1454	 	let mut r_is_at_infinity :bool;
1455	 	let mut max_len :i32=0;
1456	 	let mut k :i32;
1457	 	let mut r_is_inversted :bool = false;
1458	 	(curnaf,bits) = self.get_wnaf_variable(bn2)?;
1459	 	wnaf_bits.push(bits);
1460	 	wnaf.push(curnaf.clone());
1461	 	ecsimple_log_trace!("scalars[0] 0x{:X}",bn2);
1462	 	ecsimple_debug_buffer_trace!(curnaf.as_ptr(),curnaf.len(),"wNAF wsize[0] 0x{:x}",wnaf_bits[0]);
1463	 	cv = Vec::new();
1464	 	cv.push(self.clone());
1465	 	val_sub.push(cv.clone());
1466	 	ecsimple_log_trace!("val_sub[0][0].X 0x{:X} val_sub[0][0].Y 0x{:X} val_sub[0][0].Z 0x{:X}",val_sub[0][0].x(),val_sub[0][0].y(),val_sub[0][0].z());
1467
1468
1469
1470	 	(curnaf,bits) = self.get_wnaf_variable(bn1)?;
1471	 	wnaf_bits.push(bits);
1472	 	ecsimple_log_trace!("scalar 0x{:X}",bn1);
1473	 	ecsimple_debug_buffer_trace!(curnaf.as_ptr(),curnaf.len(),"wNAF wsize[1] 0x{:x}",wnaf_bits[1]);
1474	 	wnaf.push(curnaf.clone());
1475	 	cv = Vec::new();
1476	 	cv.push(ECPrimePoint::new(&self.group));
1477	 	val_sub.push(cv.clone());
1478	 	ecsimple_log_trace!("val_sub[1][0].X 0x{:X} val_sub[1][0].Y 0x{:X} val_sub[1][0].Z 0x{:X}",val_sub[1][0].x(),val_sub[1][0].y(),val_sub[1][0].z());
1479
1480	 	idx = 0;
1481	 	while idx < wnaf_bits.len() {
1482	 		while val_sub[idx].len() < (1 << (wnaf_bits[idx] - 1)) as usize {
1483	 			val_sub[idx].push(ECPrimePoint::new(&self.group));
1484	 		}
1485	 		idx += 1;
1486	 	}
1487
1488	 	idx = 0;
1489	 	while idx < wnaf.len() {
1490	 		if max_len < wnaf[idx].len() as i32 {
1491	 			max_len = wnaf[idx].len() as i32;
1492	 		}
1493	 		idx += 1;
1494	 	}
1495
1496	 	idx = 0;
1497	 	while idx < val_sub.len() {
1498	 		if idx == 0 {
1499	 			ecsimple_log_trace!("[{}] copy points [{}]",idx,idx);
1500	 			val_sub[idx][0] = self.clone();
1501	 		} else {
1502	 			ecsimple_log_trace!("[{}] copy generator",idx);
1503	 			val_sub[idx][0] = ECPrimePoint::new(&self.group);
1504	 		}
1505
1506	 		ecsimple_log_trace!("val_sub[{}][0].X 0x{:X} val_sub[{}][0].Y 0x{:X} val_sub[{}][0].Z 0x{:X}",idx,val_sub[idx][0].x(),idx,val_sub[idx][0].y(),idx,val_sub[idx][0].z());
1507
1508	 		if wnaf[idx].len() > 1 {
1509	 			tmp = val_sub[idx][0].dbl()?;
1510	 			ecsimple_log_trace!("val_sub[{}][0].x 0x{:X} val_sub[{}][0].y 0x{:X} val_sub[{}][0].z 0x{:X}",idx,val_sub[idx][0].x,idx,val_sub[idx][0].y,idx,val_sub[idx][0].z);
1511	 			ecsimple_log_trace!("tmp.x 0x{:X} tmp.y 0x{:X} tmp.z 0x{:X}",tmp.x,tmp.y,tmp.z);
1512	 			jdx = 1;
1513	 			while jdx < (1 << (wnaf_bits[idx]-1)) as usize {
1514	 				val_sub[idx][jdx] = val_sub[idx][jdx-1].add(&tmp)?;
1515	 				ecsimple_log_trace!("val_sub[{}][{}].x 0x{:X} val_sub[{}][{}].y 0x{:X} val_sub[{}][{}].z 0x{:X}",idx,jdx-1,val_sub[idx][jdx-1].x,idx,jdx-1,val_sub[idx][jdx-1].y,idx,jdx-1,val_sub[idx][jdx-1].z);
1516	 				ecsimple_log_trace!("val_sub[{}][{}].x 0x{:X} val_sub[{}][{}].y 0x{:X} val_sub[{}][{}].z 0x{:X}",idx,jdx,val_sub[idx][jdx].x,idx,jdx,val_sub[idx][jdx].y,idx,jdx,val_sub[idx][jdx].z);
1517	 				jdx += 1;
1518	 			}
1519
1520	 		}
1521
1522	 		idx += 1;
1523	 	}
1524
1525	 	idx = 0;
1526	 	affinepoints = Vec::new();
1527	 	while idx < val_sub.len() {
1528	 		jdx = 0;
1529	 		while jdx < val_sub[idx].len() {
1530	 			affinepoints.push(val_sub[idx][jdx].clone());
1531	 			jdx += 1;
1532	 		}
1533	 		idx += 1;
1534	 	}
1535
1536	 	idx = 0;
1537	 	while idx < affinepoints.len() {
1538	 		ecsimple_log_trace!("val[{}].x 0x{:X} val[{}].y 0x{:X} val[{}].z 0x{:X}",idx,affinepoints[idx].x,idx,affinepoints[idx].y,idx,affinepoints[idx].z);
1539	 		idx += 1;
1540	 	}
1541
1542	 	self.points_make_affine(&mut affinepoints)?;
1543
1544	 	idx = 0;
1545	 	affidx = 0;
1546	 	while idx < val_sub.len() {
1547	 		jdx = 0;
1548	 		while jdx < val_sub[idx].len() {
1549	 			val_sub[idx][jdx] = affinepoints[affidx].clone();
1550	 			affidx += 1;
1551	 			jdx += 1;
1552	 		}
1553	 		idx += 1;
1554	 	}
1555
1556	 	r_is_at_infinity = true;
1557	 	ecsimple_log_trace!("max_len {} wnaf.len() {}",max_len,wnaf.len());
1558	 	k = max_len -1 ;
1559	 	while k >= 0 {
1560	 		if ! r_is_at_infinity {
1561	 			retv = retv.dbl()?;
1562	 		}
1563	 		idx = 0;			
1564	 		while idx < wnaf.len() {
1565	 			if wnaf[idx].len() as i32 > k {
1566	 				let mut digit :u8 = wnaf[idx][k as usize];
1567	 				let mut is_neg :bool = false;
1568	 				ecsimple_log_trace!("wnaf[{}][{}] 0x{:x}",idx,k,digit);
1569	 				if digit != 0 {
1570	 					if (digit & 0x80) != 0 {
1571	 						is_neg = true;
1572	 						digit = 0xff - digit + 1;
1573	 					}
1574	 					ecsimple_log_trace!("digit [{}]",digit);
1575
1576	 					if is_neg != r_is_inversted {
1577	 						if ! r_is_at_infinity {
1578	 							retv = retv.invert()?;
1579	 						}
1580	 						r_is_inversted = !r_is_inversted;
1581	 					}
1582
1583	 					if r_is_at_infinity {
1584	 						ecsimple_log_trace!("digit [{}]",digit);
1585	 						retv = val_sub[idx][(digit >> 1) as usize].clone();
1586	 						retv = retv.blind_coordinate()?;
1587	 						r_is_at_infinity = false;
1588	 					} else {
1589	 						ecsimple_log_trace!("digit [{}]",digit);
1590	 						ecsimple_log_trace!("will get [{}][{}]",idx,(digit >> 1));
1591	 						retv = retv.add(&val_sub[idx][(digit >> 1) as usize])?;
1592	 					}
1593	 				}
1594	 			}
1595	 			idx += 1;
1596	 		}
1597
1598	 		k -= 1;
1599	 	}
1600
1601	 	if r_is_at_infinity {
1602	 		retv.point_set_infinity();
1603	 	} else {
1604	 		if r_is_inversted {
1605	 			retv = retv.invert()?;
1606	 		}
1607	 	}
1608	 	Ok(retv)
1609	 }
1610
1611	 pub fn get_affine_points(&self) -> Result<(BigInt,BigInt),Box<dyn Error>> {
1612	 	let zv :BigInt = zero();
1613	 	let ov :BigInt = one();
1614	 	let x :BigInt;
1615	 	let y :BigInt;
1616	 	let z :BigInt;
1617	 	let z_ :BigInt;
1618	 	let z_1 :BigInt;
1619	 	let z_2 :BigInt;
1620	 	let z_3 :BigInt;
1621	 	if self.z == zv {
1622	 		ecsimple_new_error!{ECPrimePointError,"z == 0"}
1623	 	}
1624
1625	 	ecsimple_log_trace!("point.X 0x{:X} point.Y 0x{:X} point.Z 0x{:X}",self.x,self.y,self.z);
1626
1627	 	z  = self.field_decode(&self.z);
1628	 	z_ = z.clone();
1629	 	if z_ == ov {
1630	 		x = self.x.clone();
1631	 		y = self.y.clone();
1632	 	} else {
1633	 		z_1 = self.field_inv(&z_);
1634	 		z_2 = z_1.clone() * z_1.clone() % self.group.p.clone();
1635	 		ecsimple_log_trace!("BN_mod_sqr(Z_2 0x{:X},Z_1 0x{:X},group.field 0x{:X})",z_2,z_1,self.group.p);
1636	 		x = self.field_mul(&self.x,&z_2);
1637	 		z_3 = z_2.clone() * z_1.clone() % self.group.p.clone();
1638	 		y = self.field_mul(&self.y,&z_3);
1639	 	}
1640
1641	 	ecsimple_log_trace!("x 0x{:X}",x);
1642	 	ecsimple_log_trace!("y 0x{:X}",y);
1643	 	Ok((x,y))
1644	 }
1645
1646}
1647