cryptal  latest
Cryptography Abstraction Layer
Poly1305.php
1 <?php
2 
4 
8 
17 class Poly1305 extends AbstractMac
18 {
20  private $r;
21 
23  private $s;
24 
25  public function __construct(MacEnum $macAlgorithm, SubAlgorithmAbstractEnum $innerAlgorithm, $key, $nonce = '')
26  {
27  if (MacEnum::MAC_POLY1305() !== $macAlgorithm) {
28  throw new \InvalidArgumentException('Unsupported algorithm');
29  }
30 
31  if (32 !== strlen($key)) {
32  throw new \InvalidArgumentException('Invalid key');
33  }
34 
35  $r = substr($key, 0, 16);
36  $s = substr($key, 16);
37  $t1 = "\x0F";
38  $t2 = "\xFC";
39  $r[ 3] = $r[ 3] & $t1;
40  $r[ 4] = $r[ 4] & $t2;
41  $r[ 7] = $r[ 7] & $t1;
42  $r[ 8] = $r[ 8] & $t2;
43  $r[11] = $r[11] & $t1;
44  $r[12] = $r[12] & $t2;
45  $r[15] = $r[15] & $t1;
46  $this->s = gmp_init(bin2hex(strrev($s)), 16);
47  $this->r = gmp_init(bin2hex(strrev($r)), 16);
48  $this->data = '';
49  }
50 
51  protected function internalUpdate($data)
52  {
53  $this->data .= $data;
54  }
55 
56  protected function internalFinalize()
57  {
58  $res = gmp_init(0);
59  if ('' !== $this->data) {
60  $chunks = str_split($this->data, 16);
61  $q = count($chunks);
62  foreach ($chunks as $i => $chunk) {
63  $t = gmp_init(bin2hex(strrev($chunk . "\x01")), 16);
64  $res = gmp_add($res, gmp_mul($t, gmp_pow($this->r, $q - $i)));
65  }
66  $res = gmp_mod($res, gmp_sub(gmp_pow(2, 130), 5));
67  }
68 
69  $res = gmp_mod(gmp_add($res, $this->s), gmp_pow(2, 128));
70  return strrev(pack('H*', str_pad(gmp_strval($res, 16), 32, '0', STR_PAD_LEFT)));
71  }
72 }
__construct(MacEnum $macAlgorithm, SubAlgorithmAbstractEnum $innerAlgorithm, $key, $nonce= '')
Definition: Poly1305.php:25
$r
First half of secret key (second half in the specs due to endianness).
Definition: Poly1305.php:20