Skip to content

Commit

Permalink
Implement Poly1305
Browse files Browse the repository at this point in the history
  • Loading branch information
paragonie-security committed Aug 27, 2017
1 parent 14ed28c commit 581ff6d
Show file tree
Hide file tree
Showing 10 changed files with 1,290 additions and 30 deletions.
6 changes: 4 additions & 2 deletions src/Core/Poly1305/State.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ public function update($message = '')
$this->blocks($block, $want);
$message = self::substr($message, $want);
$bytes = self::strlen($message);
$block = self::substr($message, 0, $want);
}
}
}
Expand Down Expand Up @@ -184,6 +185,7 @@ public function blocks($message, $bytes)
self::mul($h3, $s2) +
self::mul($h4, $s1)
);

$d1 = (
self::mul($h0, $r1) +
self::mul($h1, $r0) +
Expand Down Expand Up @@ -217,7 +219,7 @@ public function blocks($message, $bytes)
);

/* (partial) h %= p */
$c = $d0 >> 26;
$c = $d0 >> 26;
$h0 = $d0 & 0x3ffffff;
$d1 += $c;
$c = $d1 >> 26;
Expand Down Expand Up @@ -302,7 +304,7 @@ public function finish()
$h1 += $c;

/* compute h + -p */
$g0 = $h0 + 5;
$g0 = $h0 + 5;
$c = $g0 >> 26;
$g0 &= 0x3ffffff;
$g1 = $h1 + $c;
Expand Down
215 changes: 214 additions & 1 deletion src/Core32/Int32.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@
*/
class ParagonIE_Sodium_Core32_Int32
{
/** @var array<int, int> - two 16-bit integers */
/**
* @var array<int, int> - two 16-bit integers
*
* 0 is the higher 16 bits
* 1 is the lower 16 bits
*/
public $limbs;

/**
* @var int
*/
public $overflow = 0;

public function __construct($array = array(0, 0))
{
$this->limbs = $array;
Expand All @@ -33,6 +43,7 @@ public function addInt32(ParagonIE_Sodium_Core32_Int32 $addend)

$tmp = $this->limbs[0] + $addend->limbs[0] + $carry;
$return->limbs[0] = (int) ($tmp & 0xffff);
$return->overflow = $this->overflow + $addend->overflow + ($tmp >> 16);

return $return;
}
Expand All @@ -55,6 +66,7 @@ public function addInt($int)

$tmp = $this->limbs[0] + (($int >> 16) & 0xffff) + $carry;
$return->limbs[0] = (int) ($tmp & 0xffff);
$return->overflow = $this->overflow + $tmp >> 16;
return $return;
}

Expand All @@ -79,6 +91,96 @@ public function compareInt($b = 0)
return ($gt + $gt - $eq) + 1;
}

/**
* @param int $m
* @return ParagonIE_Sodium_Core32_Int32
*/
public function mask($m = 0)
{
$hi = ($m >> 16) & 0xffff;
$lo = ($m & 0xffff);
return new ParagonIE_Sodium_Core32_Int32(
array(
$this->limbs[0] & $hi,
$this->limbs[1] & $lo
)
);
}

/**
* @param int $int
* @param int $size
* @return ParagonIE_Sodium_Core32_Int32
*/
public function mulInt($int = 0, $size = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);
ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
if (!$size) {
$size = 31;
}

$a = clone $this;
$return = new ParagonIE_Sodium_Core32_Int32();

for ($i = $size; $i >= 0; --$i) {
$return = $return->addInt32($a->mask(-($int & 1)));
$a = $a->shiftLeft(1);
$int >>= 1;
}
return $return;
}

/**
* @param ParagonIE_Sodium_Core32_Int32 $int
* @param int $size
* @return ParagonIE_Sodium_Core32_Int32
*/
public function mulInt32(ParagonIE_Sodium_Core32_Int32 $int, $size = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2);
if (!$size) {
$size = 31;
}

$a = clone $this;
$b = clone $int;
$return = new ParagonIE_Sodium_Core32_Int32();

for ($i = $size; $i >= 0; --$i) {
$return = $return->addInt32($a->mask(-($b->limbs[1] & 1)));
$a = $a->shiftLeft(1);
$b = $b->shiftRight(1);
}
return $return;
}

/**
* OR this 32-bit integer with another.
*
* @param ParagonIE_Sodium_Core32_Int32 $b
* @return ParagonIE_Sodium_Core32_Int32
*/
public function orInt32(ParagonIE_Sodium_Core32_Int32 $b)
{
$return = new ParagonIE_Sodium_Core32_Int32();
$return->limbs = array(
(int) ($this->limbs[0] | $b->limbs[0]),
(int) ($this->limbs[1] | $b->limbs[1])
);
$return->overflow = $this->overflow | $b->overflow;
return $return;
}

/**
* @param int $b
* @return bool
*/
public function isGreaterThan($b = 0)
{
return $this->compareInt($b) > 0;
}

/**
* @param int $b
* @return bool
Expand Down Expand Up @@ -154,6 +256,81 @@ public function rotateRight($c = 0)
return $return;
}

/**
* @param int $c
* @return ParagonIE_Sodium_Core32_Int32
*/
public function shiftLeft($c = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
$return = new ParagonIE_Sodium_Core32_Int32();
$c &= 63;
if ($c === 0) {
$return->limbs = $this->limbs;
} elseif ($c < 0) {
return $this->shiftRight(-$c);
} else {
$tmp = $this->limbs[1] << $c;
$return->limbs[1] = (int)($tmp & 0xffff);
$carry = $tmp >> 16;

$tmp = ($this->limbs[0] << $c) | ($carry & 0xffff);
$return->limbs[0] = (int) ($tmp & 0xffff);
}
return $return;
}

/**
* @param int $c
* @return ParagonIE_Sodium_Core32_Int32
*/
public function shiftRight($c = 0)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1);
$return = new ParagonIE_Sodium_Core32_Int32();
$c &= 63;
if ($c >= 16) {
$return->limbs = array(
0,
$this->limbs[0]
);
return $return->shiftRight($c & 15);
}
if ($c === 0) {
$return->limbs = $this->limbs;
} elseif ($c < 0) {
return $this->shiftLeft(-$c);
} else {
$carryRight = (int) ($this->limbs[0] & ((1 << ($c + 1)) - 1));
$return->limbs[0] = (int) (($this->limbs[0] >> $c) & 0xffff);
$return->limbs[1] = (int) ((($this->limbs[1] >> $c) | ($carryRight << (16 - $c))) & 0xffff);
$return->overflow >>= $c;
}
return $return;
}


/**
* Adds a normal integer to an int32 object
*
* @param int $int
* @return ParagonIE_Sodium_Core32_Int32
*/
public function subInt($int)
{
ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1);

$return = new ParagonIE_Sodium_Core32_Int32();

$tmp = $this->limbs[1] - ($int & 0xffff);
$carry = $tmp >> 16;
$return->limbs[1] = (int) ($tmp & 0xffff);

$tmp = $this->limbs[0] - (($int >> 16) & 0xffff) + $carry;
$return->limbs[0] = (int) ($tmp & 0xffff);
return $return;
}

/**
* XOR this 32-bit integer with another.
*
Expand Down Expand Up @@ -250,6 +427,42 @@ public function toString()
ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] & 0xff);
}

/**
* @return int
*/
public function toInt()
{
return (int) (
(($this->limbs[0] & 0xffff) << 16)
|
($this->limbs[1] & 0xffff)
);
}

/**
* @return ParagonIE_Sodium_Core32_Int32
*/
public function toInt32()
{
$return = new ParagonIE_Sodium_Core32_Int32();
$return->limbs[0] = (int) ($this->limbs[0]);
$return->limbs[1] = (int) ($this->limbs[1]);
return $return;
}

/**
* @return ParagonIE_Sodium_Core32_Int64
*/
public function toInt64()
{
$return = new ParagonIE_Sodium_Core32_Int64();
$return->limbs[0] = (int) (($this->overflow >> 16) & 0xffff);
$return->limbs[1] = (int) ($this->overflow & 0xffff);
$return->limbs[2] = (int) ($this->limbs[0]);
$return->limbs[3] = (int) ($this->limbs[1]);
return $return;
}

/**
* @return string
*/
Expand Down
Loading

0 comments on commit 581ff6d

Please sign in to comment.