Initial Commit
This commit is contained in:
285
database/perl/vendor/lib/Math/Prime/Util/ECAffinePoint.pm
vendored
Normal file
285
database/perl/vendor/lib/Math/Prime/Util/ECAffinePoint.pm
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
package Math::Prime::Util::ECAffinePoint;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Carp qw/carp croak confess/;
|
||||
|
||||
BEGIN {
|
||||
$Math::Prime::Util::ECAffinePoint::AUTHORITY = 'cpan:DANAJ';
|
||||
$Math::Prime::Util::ECAffinePoint::VERSION = '0.73';
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
do { require Math::BigInt; Math::BigInt->import(try=>"GMP,Pari"); }
|
||||
unless defined $Math::BigInt::VERSION;
|
||||
}
|
||||
|
||||
# Pure perl (with Math::BigInt) manipulation of Elliptic Curves
|
||||
# in affine coordinates. Should be split into a point class.
|
||||
|
||||
sub new {
|
||||
my ($class, $a, $b, $n, $x, $y) = @_;
|
||||
$a = Math::BigInt->new("$a") unless ref($a) eq 'Math::BigInt';
|
||||
$b = Math::BigInt->new("$b") unless ref($b) eq 'Math::BigInt';
|
||||
$n = Math::BigInt->new("$n") unless ref($n) eq 'Math::BigInt';
|
||||
$x = Math::BigInt->new("$x") unless ref($x) eq 'Math::BigInt';
|
||||
$y = Math::BigInt->new("$y") unless ref($y) eq 'Math::BigInt';
|
||||
|
||||
croak "n must be >= 2" unless $n >= 2;
|
||||
$a->bmod($n);
|
||||
$b->bmod($n);
|
||||
|
||||
my $self = {
|
||||
a => $a,
|
||||
b => $b,
|
||||
n => $n,
|
||||
x => $x,
|
||||
y => $y,
|
||||
f => $n->copy->bone,
|
||||
};
|
||||
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub _add {
|
||||
my ($self, $P1x, $P1y, $P2x, $P2y) = @_;
|
||||
my $n = $self->{'n'};
|
||||
|
||||
if ($P1x == $P2x) {
|
||||
my $t = ($P1y + $P2y) % $n;
|
||||
return (Math::BigInt->bzero,Math::BigInt->bone) if $t == 0;
|
||||
}
|
||||
my $deltax = ($P2x - $P1x) % $n;
|
||||
$deltax->bmodinv($n);
|
||||
return (Math::BigInt->bzero,Math::BigInt->bone) if $deltax eq "NaN";
|
||||
|
||||
my $deltay = ($P2y - $P1y) % $n;
|
||||
my $m = ($deltay * $deltax) % $n; # m = deltay / deltax
|
||||
|
||||
my $x = ($m*$m - $P1x - $P2x) % $n;
|
||||
my $y = ($m*($P1x - $x) - $P1y) % $n;
|
||||
return ($x,$y);
|
||||
}
|
||||
|
||||
sub _double {
|
||||
my ($self, $P1x, $P1y) = @_;
|
||||
my $n = $self->{'n'};
|
||||
|
||||
my $m = 2*$P1y;
|
||||
$m->bmodinv($n);
|
||||
return (Math::BigInt->bzero,Math::BigInt->bone) if $m eq "NaN";
|
||||
|
||||
$m = ((3*$P1x*$P1x + $self->{'a'}) * $m) % $n;
|
||||
|
||||
my $x = ($m*$m - 2*$P1x) % $n;
|
||||
my $y = ($m*($P1x - $x) - $P1y) % $n;
|
||||
return ($x,$y);
|
||||
}
|
||||
|
||||
sub _inplace_add {
|
||||
my ($P1x, $P1y, $x, $y, $n) = @_;
|
||||
|
||||
if ($P1x == $x) {
|
||||
my $t = ($P1y + $y) % $n;
|
||||
if ($t == 0) {
|
||||
($_[2],$_[3]) = (Math::BigInt->bzero,Math::BigInt->bone);
|
||||
return;
|
||||
}
|
||||
}
|
||||
my $deltax = ($x - $P1x) % $n;
|
||||
$deltax->bmodinv($n);
|
||||
if ($deltax eq 'NaN') {
|
||||
($_[2],$_[3]) = (Math::BigInt->bzero,Math::BigInt->bone);
|
||||
return;
|
||||
}
|
||||
my $deltay = ($y - $P1y) % $n;
|
||||
my $m = ($deltay * $deltax) % $n; # m = deltay / deltax
|
||||
|
||||
$_[2] = ($m*$m - $P1x - $x) % $n;
|
||||
$_[3] = ($m*($P1x - $_[2]) - $P1y) % $n;
|
||||
}
|
||||
sub _inplace_double {
|
||||
my($x, $y, $a, $n) = @_;
|
||||
my $m = $y+$y;
|
||||
$m->bmodinv($n);
|
||||
if ($m eq 'NaN') {
|
||||
($_[0],$_[1]) = (Math::BigInt->bzero,Math::BigInt->bone);
|
||||
return;
|
||||
}
|
||||
$m->bmul($x->copy->bmul($x)->bmul(3)->badd($a))->bmod($n);
|
||||
|
||||
my $xin = $x->copy;
|
||||
$_[0] = ($m*$m - $x - $x) % $n;
|
||||
$_[1] = ($m*($xin - $_[0]) - $y) % $n;
|
||||
}
|
||||
|
||||
sub mul {
|
||||
my ($self, $k) = @_;
|
||||
my $x = $self->{'x'};
|
||||
my $y = $self->{'y'};
|
||||
my $a = $self->{'a'};
|
||||
my $n = $self->{'n'};
|
||||
my $f = $self->{'f'};
|
||||
if (ref($k) eq 'Math::BigInt' && $k < ''.~0) {
|
||||
if ($] >= 5.008 || ~0 == 4294967295) {
|
||||
$k = int($k->bstr);
|
||||
} elsif ($] < 5.008 && ~0 > 4294967295 && $k < 562949953421312) {
|
||||
$k = unpack('Q',pack('Q',$k->bstr));
|
||||
}
|
||||
}
|
||||
|
||||
my $Bx = $n->copy->bzero;
|
||||
my $By = $n->copy->bone;
|
||||
my $v = 1;
|
||||
|
||||
while ($k > 0) {
|
||||
if ( ($k % 2) != 0) {
|
||||
$k--;
|
||||
$f->bmul($Bx-$x)->bmod($n);
|
||||
if ($x->is_zero && $y->is_one) { }
|
||||
elsif ($Bx->is_zero && $By->is_one) { ($Bx,$By) = ($x,$y); }
|
||||
else { _inplace_add($x,$y,$Bx,$By,$n); }
|
||||
} else {
|
||||
$k >>= 1;
|
||||
$f->bmul(2*$y)->bmod($n);
|
||||
_inplace_double($x,$y,$a,$n);
|
||||
}
|
||||
}
|
||||
$f = Math::BigInt::bgcd($f, $n);
|
||||
$self->{'x'} = $Bx;
|
||||
$self->{'y'} = $By;
|
||||
$self->{'f'} = $f;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub add {
|
||||
my ($self, $other) = @_;
|
||||
croak "add takes a EC point"
|
||||
unless ref($other) eq 'Math::Prime::Util::ECAffinePoint';
|
||||
croak "second point is not on the same curve"
|
||||
unless $self->{'a'} == $other->{'a'} &&
|
||||
$self->{'b'} == $other->{'b'} &&
|
||||
$self->{'n'} == $other->{'n'};
|
||||
|
||||
($self->{'x'}, $self->{'y'}) = $self->_add($self->{'x'}, $self->{'y'},
|
||||
$other->{'x'}, $other->{'y'});
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
||||
sub a { return shift->{'a'}; }
|
||||
sub b { return shift->{'b'}; }
|
||||
sub n { return shift->{'n'}; }
|
||||
sub x { return shift->{'x'}; }
|
||||
sub y { return shift->{'y'}; }
|
||||
sub f { return shift->{'f'}; }
|
||||
|
||||
sub is_infinity {
|
||||
my $self = shift;
|
||||
return ($self->{'x'}->is_zero() && $self->{'y'}->is_one());
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
|
||||
# ABSTRACT: Elliptic curve operations for affine points
|
||||
|
||||
=pod
|
||||
|
||||
=encoding utf8
|
||||
|
||||
=for stopwords mul
|
||||
|
||||
=for test_synopsis use v5.14; my($a,$b,$n,$k,$ECP2);
|
||||
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Math::Prime::Util::ECAffinePoint - Elliptic curve operations for affine points
|
||||
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
Version 0.73
|
||||
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# Create a point on a curve (a,b,n) with coordinates 0,1
|
||||
my $ECP = Math::Prime::Util::ECAffinePoint->new($a, $b, $n, 0, 1);
|
||||
|
||||
# scalar multiplication by k.
|
||||
$ECP->mul($k);
|
||||
|
||||
# add two points on the same curve
|
||||
$ECP->add($ECP2);
|
||||
|
||||
say "P = O" if $ECP->is_infinity();
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This really should just be in Math::EllipticCurve.
|
||||
|
||||
To write.
|
||||
|
||||
|
||||
=head1 FUNCTIONS
|
||||
|
||||
=head2 new
|
||||
|
||||
$point = Math::Prime::Util::ECAffinePoint->new(a, b, n, x, y);
|
||||
|
||||
Returns a new point at C<(x,y,1)> on the curve C<(a,b,n)>.
|
||||
|
||||
=head2 a
|
||||
|
||||
=head2 b
|
||||
|
||||
=head2 n
|
||||
|
||||
Returns the C<a>, C<b>, or C<n> values that describe the curve.
|
||||
|
||||
=head2 x
|
||||
|
||||
=head2 y
|
||||
|
||||
Returns the C<x> or C<y> values that define the point on the curve.
|
||||
|
||||
=head2 f
|
||||
|
||||
Returns a possible factor found during EC multiplication.
|
||||
|
||||
=head2 add
|
||||
|
||||
Takes another point on the same curve as an argument and adds it this point.
|
||||
|
||||
=head2 mul
|
||||
|
||||
Takes an integer and performs scalar multiplication of the point.
|
||||
|
||||
=head2 is_infinity
|
||||
|
||||
Returns true if the point is (0,1), which is the point at infinity for
|
||||
the affine coordinates.
|
||||
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Math::EllipticCurve::Prime>
|
||||
|
||||
This really should just be in a L<Math::EllipticCurve> module.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Dana Jacobsen E<lt>dana@acm.orgE<gt>
|
||||
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2012-2013 by Dana Jacobsen E<lt>dana@acm.orgE<gt>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
||||
Reference in New Issue
Block a user