File Coverage

blib/lib/Math/Prime/Util/ECProjectivePoint.pm
Criterion Covered Total %
statement 95 108 87.9
branch 14 22 63.6
condition 0 6 0.0
subroutine 16 21 76.1
pod 13 13 100.0
total 138 170 81.1


line stmt bran cond sub pod time code
1             package Math::Prime::Util::ECProjectivePoint;
2 2     2   12 use strict;
  2         4  
  2         66  
3 2     2   9 use warnings;
  2         4  
  2         76  
4 2     2   10 use Carp qw/carp croak confess/;
  2         4  
  2         189  
5              
6             BEGIN {
7 2     2   6 $Math::Prime::Util::ECProjectivePoint::AUTHORITY = 'cpan:DANAJ';
8 2         114 $Math::Prime::Util::ECProjectivePoint::VERSION = '0.69';
9             }
10              
11             BEGIN {
12 2 50   2   1723 do { require Math::BigInt; Math::BigInt->import(try=>"GMP,Pari"); }
  0         0  
  0         0  
13             unless defined $Math::BigInt::VERSION;
14             }
15              
16             # Pure perl (with Math::BigInt) manipulation of Elliptic Curves
17             # in projective coordinates.
18              
19             sub new {
20 22     22 1 85 my ($class, $c, $n, $x, $z) = @_;
21 22 50       87 $c = Math::BigInt->new("$c") unless ref($c) eq 'Math::BigInt';
22 22 100       82 $n = Math::BigInt->new("$n") unless ref($n) eq 'Math::BigInt';
23 22 100       113 $x = Math::BigInt->new("$x") unless ref($x) eq 'Math::BigInt';
24 22 100       90 $z = Math::BigInt->new("$z") unless ref($z) eq 'Math::BigInt';
25              
26 22 50       94 croak "n must be >= 2" unless $n >= 2;
27 22         2136 $c->bmod($n);
28              
29 22         1957 my $self = {
30             c => $c,
31             d => ($c + 2) >> 2,
32             n => $n,
33             x => $x,
34             z => $z,
35             f => $n-$n+1,
36             };
37              
38 22         12760 bless $self, $class;
39 22         95 return $self;
40             }
41              
42             sub _addx {
43 742     742   2599 my ($x1, $x2, $xin, $n) = @_;
44              
45 742         2151 my $u = ($x2 - 1) * ($x1 + 1);
46 742         327410 my $v = ($x2 + 1) * ($x1 - 1);
47              
48 742         305284 my $upv2 = ($u + $v) ** 2;
49 742         315910 my $umv2 = ($u - $v) ** 2;
50              
51 742         287239 return ( $upv2 % $n, ($umv2*$xin) % $n );
52             }
53              
54             sub _add3 {
55 10809     10809   22781 my ($x1, $z1, $x2, $z2, $xin, $zin, $n) = @_;
56              
57 10809         22874 my $u = ($x2 - $z2) * ($x1 + $z1);
58 10809         3287727 my $v = ($x2 + $z2) * ($x1 - $z1);
59              
60 10809         3225744 my $upv2 = $u + $v; $upv2->bmul($upv2);
  10809         906947  
61 10809         2005613 my $umv2 = $u - $v; $umv2->bmul($umv2);
  10809         1116950  
62              
63 10809         2008642 $upv2->bmul($zin)->bmod($n);
64 10809         6698395 $umv2->bmul($xin)->bmod($n);
65 10809         6708502 return ($upv2, $umv2);
66             }
67              
68             sub _double {
69 10580     10580   21412 my ($x, $z, $n, $d) = @_;
70              
71 10580         24102 my $u = $x + $z; $u->bmul($u);
  10580         745993  
72 10580         1284725 my $v = $x - $z; $v->bmul($v);
  10580         1196629  
73              
74 10580         1271754 my $w = $u - $v;
75 10580         1243352 my $t = $d * $w + $v;
76              
77 10580         2240395 $u->bmul($v)->bmod($n);
78 10580         5438924 $w->bmul($t)->bmod($n);
79 10580         6365935 return ($u, $w);
80             }
81              
82             sub mul {
83 1361     1361 1 3721 my ($self, $k) = @_;
84 1361         2834 my $x = $self->{'x'};
85 1361         2527 my $z = $self->{'z'};
86 1361         2656 my $n = $self->{'n'};
87 1361         2927 my $d = $self->{'d'};
88              
89 1361         2488 my ($x1, $x2, $z1, $z2);
90              
91 1361         2555 my $r = --$k;
92 1361         2639 my $l = -1;
93 1361         3578 while ($r != 1) { $r >>= 1; $l++ }
  10807         12322  
  10807         15981  
94 1361 100       3952 if ($k & (1 << $l)) {
95 633         1921 ($x2, $z2) = _double($x, $z, $n, $d);
96 633         2172 ($x1, $z1) = _add3($x2, $z2, $x, $z, $x, $z, $n);
97 633         1824 ($x2, $z2) = _double($x2, $z2, $n, $d);
98             } else {
99 728         2293 ($x1, $z1) = _double($x, $z, $n, $d);
100 728         2192 ($x2, $z2) = _add3($x, $z, $x1, $z1, $x, $z, $n);
101             }
102 1361         3242 $l--;
103 1361         3822 while ($l >= 1) {
104 8087 100       19990 if ($k & (1 << $l)) {
105 3957         8419 ($x1, $z1) = _add3($x1, $z1, $x2, $z2, $x, $z, $n);
106 3957         16242 ($x2, $z2) = _double($x2, $z2, $n, $d);
107             } else {
108 4130         10973 ($x2, $z2) = _add3($x2, $z2, $x1, $z1, $x, $z, $n);
109 4130         14687 ($x1, $z1) = _double($x1, $z1, $n, $d);
110             }
111 8087         32261 $l--;
112             }
113 1361 50       4317 if ($k & 1) {
114 0         0 ($x, $z) = _double($x2, $z2, $n, $d);
115             } else {
116 1361         4040 ($x, $z) = _add3($x2, $z2, $x1, $z1, $x, $z, $n);
117             }
118              
119 1361         3757 $self->{'x'} = $x;
120 1361         3915 $self->{'z'} = $z;
121 1361         7780 return $self;
122             }
123              
124             sub add {
125 0     0 1 0 my ($self, $other) = @_;
126 0 0       0 croak "add takes a EC point"
127             unless ref($other) eq 'Math::Prime::Util::ECProjectivePoint';
128             croak "second point is not on the same curve"
129             unless $self->{'c'} == $other->{'c'} &&
130 0 0 0     0 $self->{'n'} == $other->{'n'};
131              
132             ($self->{'x'}, $self->{'z'}) = _add3($self->{'x'}, $self->{'z'},
133             $other->{'x'}, $other->{'z'},
134             $self->{'x'}, $self->{'z'},
135 0         0 $self->{'n'});
136 0         0 return $self;
137             }
138              
139             sub double {
140 85     85 1 145 my ($self) = @_;
141 85         221 ($self->{'x'}, $self->{'z'}) = _double($self->{'x'}, $self->{'z'}, $self->{'n'}, $self->{'d'});
142 85         390 return $self;
143             }
144              
145             #sub _extended_gcd {
146             # my ($a, $b) = @_;
147             # my $zero = $a-$a;
148             # my ($x, $lastx, $y, $lasty) = ($zero, $zero+1, $zero+1, $zero);
149             # while ($b != 0) {
150             # my $q = int($a/$b);
151             # ($a, $b) = ($b, $a % $b);
152             # ($x, $lastx) = ($lastx - $q*$x, $x);
153             # ($y, $lasty) = ($lasty - $q*$y, $y);
154             # }
155             # return ($a, $lastx, $lasty);
156             #}
157              
158             sub normalize {
159 10     10 1 26 my ($self) = @_;
160 10         24 my $n = $self->{'n'};
161 10         23 my $z = $self->{'z'};
162             #my ($f, $u, undef) = _extended_gcd( $z, $n );
163 10         27 my $f = Math::BigInt::bgcd( $z, $n );
164 10         25794 my $u = $z->copy->bmodinv($n);
165 10         37669 $self->{'x'} = ( $self->{'x'} * $u ) % $n;
166 10         3620 $self->{'z'} = $n-$n+1;
167 10         2255 $self->{'f'} = ($f * $self->{'f'}) % $n;
168 10         1613 return $self;
169             }
170              
171 0     0 1 0 sub c { return shift->{'c'}; }
172 10     10 1 27 sub d { return shift->{'d'}; }
173 0     0 1 0 sub n { return shift->{'n'}; }
174 1371     1371 1 4955 sub x { return shift->{'x'}; }
175 0     0 1 0 sub z { return shift->{'z'}; }
176 10     10 1 31 sub f { return shift->{'f'}; }
177              
178             sub is_infinity {
179 0     0 1 0 my $self = shift;
180 0   0     0 return ($self->{'x'}->is_zero() && $self->{'z'}->is_one());
181             }
182              
183             sub copy {
184 10     10 1 24 my $self = shift;
185             return Math::Prime::Util::ECProjectivePoint->new(
186 10         56 $self->{'c'}, $self->{'n'}, $self->{'x'}, $self->{'z'});
187             }
188              
189             1;
190              
191             __END__