| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Math::Prime::Util::ECAffinePoint; | 
| 2 | 1 |  |  | 1 |  | 7 | use strict; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 30 |  | 
| 3 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 34 |  | 
| 4 | 1 |  |  | 1 |  | 6 | use Carp qw/carp croak confess/; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 175 |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | BEGIN { | 
| 7 | 1 |  |  | 1 |  | 4 | $Math::Prime::Util::ECAffinePoint::AUTHORITY = 'cpan:DANAJ'; | 
| 8 | 1 |  |  |  |  | 51 | $Math::Prime::Util::ECAffinePoint::VERSION = '0.69'; | 
| 9 |  |  |  |  |  |  | } | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | BEGIN { | 
| 12 | 1 | 50 |  | 1 |  | 994 | 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 affine coordinates.  Should be split into a point class. | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | sub new { | 
| 20 | 9 |  |  | 9 | 1 | 38 | my ($class, $a, $b, $n, $x, $y) = @_; | 
| 21 | 9 | 50 |  |  |  | 37 | $a = Math::BigInt->new("$a") unless ref($a) eq 'Math::BigInt'; | 
| 22 | 9 | 50 |  |  |  | 28 | $b = Math::BigInt->new("$b") unless ref($b) eq 'Math::BigInt'; | 
| 23 | 9 | 50 |  |  |  | 24 | $n = Math::BigInt->new("$n") unless ref($n) eq 'Math::BigInt'; | 
| 24 | 9 | 50 |  |  |  | 26 | $x = Math::BigInt->new("$x") unless ref($x) eq 'Math::BigInt'; | 
| 25 | 9 | 50 |  |  |  | 22 | $y = Math::BigInt->new("$y") unless ref($y) eq 'Math::BigInt'; | 
| 26 |  |  |  |  |  |  |  | 
| 27 | 9 | 50 |  |  |  | 25 | croak "n must be >= 2" unless $n >= 2; | 
| 28 | 9 |  |  |  |  | 996 | $a->bmod($n); | 
| 29 | 9 |  |  |  |  | 972 | $b->bmod($n); | 
| 30 |  |  |  |  |  |  |  | 
| 31 | 9 |  |  |  |  | 812 | my $self = { | 
| 32 |  |  |  |  |  |  | a => $a, | 
| 33 |  |  |  |  |  |  | b => $b, | 
| 34 |  |  |  |  |  |  | n => $n, | 
| 35 |  |  |  |  |  |  | x => $x, | 
| 36 |  |  |  |  |  |  | y => $y, | 
| 37 |  |  |  |  |  |  | f => $n->copy->bone, | 
| 38 |  |  |  |  |  |  | }; | 
| 39 |  |  |  |  |  |  |  | 
| 40 | 9 |  |  |  |  | 851 | bless $self, $class; | 
| 41 | 9 |  |  |  |  | 25 | return $self; | 
| 42 |  |  |  |  |  |  | } | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | sub _add { | 
| 45 | 0 |  |  | 0 |  | 0 | my ($self, $P1x, $P1y, $P2x, $P2y) = @_; | 
| 46 | 0 |  |  |  |  | 0 | my $n = $self->{'n'}; | 
| 47 |  |  |  |  |  |  |  | 
| 48 | 0 | 0 |  |  |  | 0 | if ($P1x == $P2x) { | 
| 49 | 0 |  |  |  |  | 0 | my $t = ($P1y + $P2y) % $n; | 
| 50 | 0 | 0 |  |  |  | 0 | return (Math::BigInt->bzero,Math::BigInt->bone) if $t == 0; | 
| 51 |  |  |  |  |  |  | } | 
| 52 | 0 |  |  |  |  | 0 | my $deltax = ($P2x - $P1x) % $n; | 
| 53 | 0 |  |  |  |  | 0 | $deltax->bmodinv($n); | 
| 54 | 0 | 0 |  |  |  | 0 | return (Math::BigInt->bzero,Math::BigInt->bone) if $deltax eq "NaN"; | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 0 |  |  |  |  | 0 | my $deltay = ($P2y - $P1y) % $n; | 
| 57 | 0 |  |  |  |  | 0 | my $m = ($deltay * $deltax) % $n;   # m = deltay / deltax | 
| 58 |  |  |  |  |  |  |  | 
| 59 | 0 |  |  |  |  | 0 | my $x = ($m*$m - $P1x - $P2x) % $n; | 
| 60 | 0 |  |  |  |  | 0 | my $y = ($m*($P1x - $x) - $P1y) % $n; | 
| 61 | 0 |  |  |  |  | 0 | return ($x,$y); | 
| 62 |  |  |  |  |  |  | } | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | sub _double { | 
| 65 | 0 |  |  | 0 |  | 0 | my ($self, $P1x, $P1y) = @_; | 
| 66 | 0 |  |  |  |  | 0 | my $n = $self->{'n'}; | 
| 67 |  |  |  |  |  |  |  | 
| 68 | 0 |  |  |  |  | 0 | my $m = 2*$P1y; | 
| 69 | 0 |  |  |  |  | 0 | $m->bmodinv($n); | 
| 70 | 0 | 0 |  |  |  | 0 | return (Math::BigInt->bzero,Math::BigInt->bone) if $m eq "NaN"; | 
| 71 |  |  |  |  |  |  |  | 
| 72 | 0 |  |  |  |  | 0 | $m = ((3*$P1x*$P1x + $self->{'a'}) * $m) % $n; | 
| 73 |  |  |  |  |  |  |  | 
| 74 | 0 |  |  |  |  | 0 | my $x = ($m*$m - 2*$P1x) % $n; | 
| 75 | 0 |  |  |  |  | 0 | my $y = ($m*($P1x - $x) - $P1y) % $n; | 
| 76 | 0 |  |  |  |  | 0 | return ($x,$y); | 
| 77 |  |  |  |  |  |  | } | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | sub _inplace_add { | 
| 80 | 147 |  |  | 147 |  | 367 | my ($P1x, $P1y, $x, $y, $n) = @_; | 
| 81 |  |  |  |  |  |  |  | 
| 82 | 147 | 100 |  |  |  | 431 | if ($P1x == $x) { | 
| 83 | 9 |  |  |  |  | 354 | my $t = ($P1y + $y) % $n; | 
| 84 | 9 | 50 |  |  |  | 1507 | if ($t == 0) { | 
| 85 | 9 |  |  |  |  | 1618 | ($_[2],$_[3]) = (Math::BigInt->bzero,Math::BigInt->bone); | 
| 86 | 9 |  |  |  |  | 500 | return; | 
| 87 |  |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  | } | 
| 89 | 138 |  |  |  |  | 5689 | my $deltax = ($x - $P1x) % $n; | 
| 90 | 138 |  |  |  |  | 31320 | $deltax->bmodinv($n); | 
| 91 | 138 | 50 |  |  |  | 413241 | if ($deltax eq 'NaN') { | 
| 92 | 0 |  |  |  |  | 0 | ($_[2],$_[3]) = (Math::BigInt->bzero,Math::BigInt->bone); | 
| 93 | 0 |  |  |  |  | 0 | return; | 
| 94 |  |  |  |  |  |  | } | 
| 95 | 138 |  |  |  |  | 3754 | my $deltay = ($y - $P1y) % $n; | 
| 96 | 138 |  |  |  |  | 33352 | my $m = ($deltay * $deltax) % $n;   # m = deltay / deltax | 
| 97 |  |  |  |  |  |  |  | 
| 98 | 138 |  |  |  |  | 41582 | $_[2] = ($m*$m - $P1x - $x) % $n; | 
| 99 | 138 |  |  |  |  | 72594 | $_[3] = ($m*($P1x - $_[2]) - $P1y) % $n; | 
| 100 |  |  |  |  |  |  | } | 
| 101 |  |  |  |  |  |  | sub _inplace_double { | 
| 102 | 331 |  |  | 331 |  | 800 | my($x, $y, $a, $n) = @_; | 
| 103 | 331 |  |  |  |  | 893 | my $m = $y+$y; | 
| 104 | 331 |  |  |  |  | 24978 | $m->bmodinv($n); | 
| 105 | 331 | 50 |  |  |  | 912188 | if ($m eq 'NaN') { | 
| 106 | 0 |  |  |  |  | 0 | ($_[0],$_[1]) = (Math::BigInt->bzero,Math::BigInt->bone); | 
| 107 | 0 |  |  |  |  | 0 | return; | 
| 108 |  |  |  |  |  |  | } | 
| 109 | 331 |  |  |  |  | 9452 | $m->bmul($x->copy->bmul($x)->bmul(3)->badd($a))->bmod($n); | 
| 110 |  |  |  |  |  |  |  | 
| 111 | 331 |  |  |  |  | 207710 | my $xin = $x->copy; | 
| 112 | 331 |  |  |  |  | 6450 | $_[0] = ($m*$m - $x - $x) % $n; | 
| 113 | 331 |  |  |  |  | 175029 | $_[1] = ($m*($xin - $_[0]) - $y) % $n; | 
| 114 |  |  |  |  |  |  | } | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | sub mul { | 
| 117 | 18 |  |  | 18 | 1 | 1618 | my ($self, $k) = @_; | 
| 118 | 18 |  |  |  |  | 48 | my $x = $self->{'x'}; | 
| 119 | 18 |  |  |  |  | 41 | my $y = $self->{'y'}; | 
| 120 | 18 |  |  |  |  | 33 | my $a = $self->{'a'}; | 
| 121 | 18 |  |  |  |  | 33 | my $n = $self->{'n'}; | 
| 122 | 18 |  |  |  |  | 28 | my $f = $self->{'f'}; | 
| 123 | 18 | 50 | 33 |  |  | 99 | if (ref($k) eq 'Math::BigInt' && $k < ''.~0) { | 
| 124 | 18 | 50 | 50 |  |  | 2389 | if ($] >= 5.008 || ~0 == 4294967295) { | 
|  |  | 0 | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 125 | 18 |  |  |  |  | 49 | $k = int($k->bstr); | 
| 126 |  |  |  |  |  |  | } elsif ($] < 5.008 && ~0 > 4294967295 && $k < 562949953421312) { | 
| 127 | 0 |  |  |  |  | 0 | $k = unpack('Q',pack('Q',$k->bstr)); | 
| 128 |  |  |  |  |  |  | } | 
| 129 |  |  |  |  |  |  | } | 
| 130 |  |  |  |  |  |  |  | 
| 131 | 18 |  |  |  |  | 337 | my $Bx = $n->copy->bzero; | 
| 132 | 18 |  |  |  |  | 674 | my $By = $n->copy->bone; | 
| 133 | 18 |  |  |  |  | 1413 | my $v = 1; | 
| 134 |  |  |  |  |  |  |  | 
| 135 | 18 |  |  |  |  | 48 | while ($k > 0) { | 
| 136 | 496 | 100 |  |  |  | 240085 | if ( ($k % 2) != 0) { | 
| 137 | 165 |  |  |  |  | 315 | $k--; | 
| 138 | 165 |  |  |  |  | 454 | $f->bmul($Bx-$x)->bmod($n); | 
| 139 | 165 | 50 | 33 |  |  | 60596 | if    ($x->is_zero && $y->is_one)   { } | 
|  |  | 100 | 66 |  |  |  |  | 
| 140 | 18 |  |  |  |  | 653 | elsif ($Bx->is_zero && $By->is_one) { ($Bx,$By) = ($x,$y); } | 
| 141 | 147 |  |  |  |  | 3352 | else                                { _inplace_add($x,$y,$Bx,$By,$n); } | 
| 142 |  |  |  |  |  |  | } else { | 
| 143 | 331 |  |  |  |  | 591 | $k >>= 1; | 
| 144 | 331 |  |  |  |  | 896 | $f->bmul(2*$y)->bmod($n); | 
| 145 | 331 |  |  |  |  | 136458 | _inplace_double($x,$y,$a,$n); | 
| 146 |  |  |  |  |  |  | } | 
| 147 |  |  |  |  |  |  | } | 
| 148 | 18 |  |  |  |  | 3355 | $f = Math::BigInt::bgcd($f, $n); | 
| 149 | 18 |  |  |  |  | 9033 | $self->{'x'} = $Bx; | 
| 150 | 18 |  |  |  |  | 58 | $self->{'y'} = $By; | 
| 151 | 18 |  |  |  |  | 54 | $self->{'f'} = $f; | 
| 152 | 18 |  |  |  |  | 109 | return $self; | 
| 153 |  |  |  |  |  |  | } | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | sub add { | 
| 156 | 0 |  |  | 0 | 1 | 0 | my ($self, $other) = @_; | 
| 157 | 0 | 0 |  |  |  | 0 | croak "add takes a EC point" | 
| 158 |  |  |  |  |  |  | unless ref($other) eq 'Math::Prime::Util::ECAffinePoint'; | 
| 159 |  |  |  |  |  |  | croak "second point is not on the same curve" | 
| 160 |  |  |  |  |  |  | unless $self->{'a'} == $other->{'a'} && | 
| 161 |  |  |  |  |  |  | $self->{'b'} == $other->{'b'} && | 
| 162 | 0 | 0 | 0 |  |  | 0 | $self->{'n'} == $other->{'n'}; | 
|  |  |  | 0 |  |  |  |  | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | ($self->{'x'}, $self->{'y'}) = $self->_add($self->{'x'}, $self->{'y'}, | 
| 165 | 0 |  |  |  |  | 0 | $other->{'x'}, $other->{'y'}); | 
| 166 | 0 |  |  |  |  | 0 | return $self; | 
| 167 |  |  |  |  |  |  | } | 
| 168 |  |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  |  | 
| 170 | 0 |  |  | 0 | 1 | 0 | sub a { return shift->{'a'}; } | 
| 171 | 0 |  |  | 0 | 1 | 0 | sub b { return shift->{'b'}; } | 
| 172 | 0 |  |  | 0 | 1 | 0 | sub n { return shift->{'n'}; } | 
| 173 | 0 |  |  | 0 | 1 | 0 | sub x { return shift->{'x'}; } | 
| 174 | 0 |  |  | 0 | 1 | 0 | sub y { return shift->{'y'}; } | 
| 175 | 0 |  |  | 0 | 1 | 0 | sub f { return shift->{'f'}; } | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | sub is_infinity { | 
| 178 | 18 |  |  | 18 | 1 | 36 | my $self = shift; | 
| 179 | 18 |  | 66 |  |  | 48 | return ($self->{'x'}->is_zero() && $self->{'y'}->is_one()); | 
| 180 |  |  |  |  |  |  | } | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | 1; | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | __END__ |