Viewing File: /usr/local/cpanel/3rdparty/perl/536/cpanel-lib/Crypt/Perl/Ed25519/Math.pm
package Crypt::Perl::Ed25519::Math;
use strict;
use warnings;
sub reduce {
my ($r) = @_;
my @x;
for my $i ( 0 .. 63 ) {
$x[$i] = $r->[$i];
$r->[$i] = 0;
}
modL( $r, \@x );
return;
}
# p and q are arrays of arrays; s is an array of numbers
sub scalarmult {
my ($p, $q, $s) = @_;
@{$p}[0 .. 3] = ( [ gf0() ], [ gf1() ], [ gf1() ], [ gf0() ] );
my $b;
for my $i ( reverse( 0 .. 255 ) ) {
$b = ( $s->[ ( $i >> 3 ) | 0 ] >> ($i & 7) ) & 1;
_cswap( $p, $q, $b );
add( $q, $p );
add( $p, $p );
_cswap( $p, $q, $b );
}
return;
}
# p is an array of arrays; s is an array of numbers
sub scalarbase {
my ($p, $s) = @_;
my @q = ( [ X() ], [ Y() ], [ gf1() ], [ gf0() ] );
_M( $q[3], [X()], [Y()] );
scalarmult($p, \@q, $s);
}
# p is an array of arrays
sub pack {
my ($p) = @_;
my $tx = [ gf0() ];
my $ty = [ gf0() ];
my $zi = [ gf0() ];
_inv25519( $zi, $p->[2] );
_M( $tx, $p->[0], $zi );
_M( $ty, $p->[1], $zi );
my $r = _pack25519($ty);
$r->[31] ^= (_par25519($tx) << 7);
return $r;
}
sub add {
my ($p, $q) = @_;
my $a = [ gf0() ];
my $b = [ gf0() ];
my $c = [ gf0() ];
my $d = [ gf0() ];
my $e = [ gf0() ];
my $f = [ gf0() ];
my $g = [ gf0() ];
my $h = [ gf0() ];
my $t = [ gf0() ];
_Z($a, $p->[1], $p->[0]);
_Z($t, $q->[1], $q->[0]);
_M($a, $a, $t);
_A($b, $p->[0], $p->[1]);
_A($t, $q->[0], $q->[1]);
_M($b, $b, $t);
_M($c, $p->[3], $q->[3]);
_M($c, $c, [ D2() ]);
_M($d, $p->[2], $q->[2]);
_A($d, $d, $d);
_Z($e, $b, $a);
_Z($f, $d, $c);
_A($g, $d, $c);
_A($h, $b, $a);
_M($p->[0], $e, $f);
_M($p->[1], $h, $g);
_M($p->[2], $g, $f);
_M($p->[3], $e, $h);
}
sub modL {
my ($r, $x) = @_;
my ($k);
for my $i ( reverse( 32 .. 63 ) ) {
my $carry = 0;
my ($j, $k);
for (
($j = $i - 32), ($k = $i - 12);
$j < $k;
++$j
) {
$x->[$j] += $carry - 16 * $x->[$i] * (L())[$j - ($i - 32)];
# originally “>> 8” rather than “/ 256”;
$carry = _floor( ($x->[$j] + 128) / 256 );
$x->[$j] -= $carry * 256;
}
$x->[$j] += $carry;
$x->[$i] = 0;
}
my $carry = 0;
# In Perl, -98 >> 4 = 1152921504606846969. :-<
my $x31_rshift_4 = _floor( $x->[31] / 16 );
for my $j ( 0 .. 31 ) {
$x->[$j] += $carry - $x31_rshift_4 * (L())[$j];
# originally “>> 8” rather than “/ 256”; we also need floor
$carry = _floor( $x->[$j] / 256 );
$x->[$j] &= 255;
}
$x->[$_] -= $carry * (L())[$_] for 0 .. 31;
for my $i ( 0 .. 31 ) {
$x->[$i + 1] += $x->[$i] >> 8;
$r->[$i] = $x->[$i] & 255;
}
return;
}
use constant gf0 => (0) x 16;
#----------------------------------------------------------------------
use constant gf1 => ( 1, (0) x 15 );
use constant L => (
0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
(0) x 15, 0x10,
);
use constant D2 => (
0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0,
0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406,
);
use constant X => (
0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c,
0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169,
);
use constant Y => (
0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666,
0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666,
);
sub _S { _M( $_[0], $_[1], $_[1] ) }
sub _inv25519 {
my ($o, $i) = @_;
my $c = [ @{$i}[0 .. 15] ];
for my $a ( reverse( 0 .. 253 ) ) {
_S($c, $c);
next if $a == 2;
next if $a == 4;
_M( $c, $c, $i );
}
@{$o}[0 .. 15] = @{$c}[0 .. 15];
return;
}
sub _pack25519 {
my ($n) = @_;
my $b;
my $o = [];
my $t = [ @{$n}[0 .. 15] ];
my $m = [ gf0() ];
_car25519($t) for 1 .. 3;
for my $j (0, 1) {
$m->[0] = $t->[0] - 0xffed;
for my $i ( 1 .. 14 ) {
$m->[$i] = $t->[$i] - 0xffff - (($m->[$i - 1] >> 16) & 1);
$m->[$i - 1] &= 0xffff;
}
$m->[15] = $t->[15] - 0x7fff - (($m->[14] >> 16) & 1);
$b = ($m->[15] >> 16) & 1;
$m->[14] &= 0xffff;
_sel25519( $t, $m, 1 - $b );
}
for my $i ( 0 .. 15 ) {
$o->[2 * $i] = $t->[$i] & 0xff;
$o->[2 * $i + 1] = $t->[$i] >> 8;
}
return $o;
}
sub _par25519 {
my ($a) = @_;
my $d = _pack25519($a);
return $d->[0] & 1;
}
# o, a, and b are arrays of numbers
sub _A {
my ($o, $a, $b) = @_;
$o->[$_] = $a->[$_] + $b->[$_] for 0 .. 15;
return;
}
# o, a, and b are arrays of numbers
sub _Z {
my ($o, $a, $b) = @_;
$o->[$_] = $a->[$_] - $b->[$_] for 0 .. 15;
return;
}
# o, a, and b are arrays of numbers
sub _M {
my ($o, $a, $b) = @_;
my @t = (0) x 31;
for my $a_idx ( 0 .. 15 ) {
$t[$a_idx + $_] += $a->[$a_idx] * $b->[$_] for 0 .. 15;
}
# $t->[15] left as-is
for my $t_idx ( 0 .. 14 ) {
$t[$t_idx] += 38 * $t[16 + $t_idx];
}
my ($c, $v);
_car25519(\@t);
_car25519(\@t);
@{$o}[0 .. 15] = @t[0 .. 15];
return;
}
sub _car25519 {
my ($o) = @_;
my $c = 1;
my $v;
for my $o_item ( @{$o}[0 .. 15] ) {
$v = $o_item + $c + 65535;
# c = Math.floor(v / 65536)
$c = int( $v / 65536 );
$c-- if $v < 0;
# t0 = v - c * 65536
$o_item = $v - ($c * 65536);
}
$o->[0] += $c - 1 + 37 * ($c - 1);
return;
}
# p and q are arrays of numbers
sub _sel25519 {
my ($p, $q, $b) = @_;
# $b is either 0 or 1.
my $c = $b && -1;
for my $i ( 0 .. 15 ) {
my $t = $c && ($c & signed_xor($p->[$i], $q->[$i]));
$p->[$i] = signed_xor($p->[$i], $t) if $t;
$q->[$i] = signed_xor($q->[$i], $t) if $t;
}
}
# p and q are arrays of arrays
sub _cswap {
my ($p, $q, $b) = @_;
for my $i ( 0 .. 3 ) {
_sel25519( $p->[$i], $q->[$i], $b );
}
}
# Perl’s ^ operator isn’t signed-savvy,
# so (-60116 ^ 0) = 18446744073709491500.
#
# TODO: add tests
sub signed_xor {
if ( ($_[0] < 0) xor ($_[1] < 0) ) {
return ($_[0] ^ $_[1]) - ~0 - 1;
}
# signs are same -> can use native xor
return $_[0] ^ $_[1];
}
sub signed_or {
# signs are same -> can use native xor
if ( ($_[0] < 0) eq ($_[1] < 0) ) {
return $_[0] | $_[1];
}
return ($_[0] | $_[1]) - ~0 - 1;
}
#----------------------------------------------------------------------
# Verify logic
sub unpackneg {
my ($r, $p) = @_;
$_ = [ gf0() ] for my (
$t,
$chk,
$num,
$den,
$den2,
$den4,
$den6,
);
_set25519( $r->[2], [ gf1() ]);
_unpack25519($r->[1], $p);
_S($num, $r->[1]);
_M($den, $num, [ D() ]);
_Z($num, $num, $r->[2]);
_A($den, $r->[2], $den);
_S($den2, $den);
_S($den4, $den2);
_M($den6, $den4, $den2);
_M($t, $den6, $num);
_M($t, $t, $den);
_pow2523($t, $t);
_M($t, $t, $num);
_M($t, $t, $den);
_M($t, $t, $den);
_M($r->[0], $t, $den);
_S($chk, $r->[0]);
_M($chk, $chk, $den);
if (_neq25519($chk, $num)) {
_M($r->[0], $r->[0], [ I() ]);
}
_S($chk, $r->[0]);
_M($chk, $chk, $den);
if (_neq25519($chk, $num)) {
die "-1??";
}
# “>>” appears to be safe here.
if (_par25519($r->[0]) == ($p->[31] >> 7)) {
_Z($r->[0], [ gf0() ], $r->[0]);
}
_M( $r->[3], $r->[0], $r->[1] );
return 0;
}
sub crypto_verify_32 {
my ($x, $xi, $y, $yi) = @_;
return _vn($x, $xi, $y, $yi, 32);
}
use constant D => (
0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070,
0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203,
);
use constant I => (
0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43,
0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83,
);
sub _set25519 {
my ($r, $a) = @_;
$r->[$_] = $a->[$_] | 0 for 0 .. 15;
}
sub _unpack25519 {
my ($o, $n) = @_;
for my $i (0 .. 15) {
# originally “<< 8” rather than “256 *”
$o->[$i] = $n->[ 2 * $i ] + (256 * $n->[ 2 * $i + 1 ])
}
$o->[15] &= 0x7fff;
}
sub _pow2523 {
my ($o, $i) = @_;
my $c = [ @{$i}[0 .. 15] ];
for my $a ( reverse( 0 .. 250 ) ) {
_S( $c, $c );
if ($a != 1) {
_M( $c, $c, $i );
}
}
@{$o}[0 .. 15] = @{$c}[0 .. 15];
}
sub _neq25519 {
my ($a, $b) = @_;
my $c = _pack25519($a);
my $d = _pack25519($b);
return crypto_verify_32($c, 0, $d, 0);
}
sub _vn {
my ($x, $xi, $y, $yi, $n) = @_;
my $d = 0;
for my $i ( 0 .. ($n - 1) ) {
$d = signed_or( $d, signed_xor($x->[ $xi + $i ], $y->[ $yi + $i ]) );
}
# Originally “>>> 8”, which appears to be JS’s equivalent
# operator to Perl’s >>.
return (1 & (($d - 1) >> 8)) - 1;
}
sub _floor {
my $int = int $_[0];
$int -= 1 if ($_[0] < 0) && ($int != $_[0]);
return $int;
}
1;
Back to Directory
File Manager