pssht  latest
SSH server library written in PHP
ChaCha20.php
1 <?php
2 
3 /*
4 * This file is part of pssht.
5 *
6 * (c) François Poirotte <clicky@erebot.net>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11 
13 
22 class ChaCha20
23 {
25  protected $key;
26 
27  public function __construct($key)
28  {
29  $len = strlen($key);
30  if ($len !== 32) {
31  throw new \InvalidArgumentException();
32  }
33 
34  $this->key = $key;
35  }
36 
37  protected static function quarterRound(&$a, &$b, &$c, &$d)
38  {
39  $a += $b;
40  $a &= 0xFFFFFFFF;
41  $d ^= $a;
42  $d = (($d & 0xFFFF) << 16) | (($d >> 16) & 0xFFFF);
43 
44  $c += $d;
45  $c &= 0xFFFFFFFF;
46  $b ^= $c;
47  $b = (($b & 0xFFFFF) << 12) | (($b >> 20) & 0xFFF);
48 
49  $a += $b;
50  $a &= 0xFFFFFFFF;
51  $d ^= $a;
52  $d = (($d & 0xFFFFFF) << 8) | (($d >> 24) & 0xFF);
53 
54  $c += $d;
55  $c &= 0xFFFFFFFF;
56  $b ^= $c;
57  $b = (($b & 0x1FFFFFF) << 7) | (($b >> 25) & 0x7F);
58  }
59 
60  protected function block($iv, $counter)
61  {
62  $block = array_values(
63  unpack('V*', 'expand 32-byte k' . $this->key . $counter . $iv)
64  );
65  $init = $block;
66 
67  for ($i = 0; $i < 10; $i++) {
68  static::quarterRound($block[ 0], $block[ 4], $block[ 8], $block[12]);
69  static::quarterRound($block[ 1], $block[ 5], $block[ 9], $block[13]);
70  static::quarterRound($block[ 2], $block[ 6], $block[10], $block[14]);
71  static::quarterRound($block[ 3], $block[ 7], $block[11], $block[15]);
72 
73  static::quarterRound($block[ 0], $block[ 5], $block[10], $block[15]);
74  static::quarterRound($block[ 1], $block[ 6], $block[11], $block[12]);
75  static::quarterRound($block[ 2], $block[ 7], $block[ 8], $block[13]);
76  static::quarterRound($block[ 3], $block[ 4], $block[ 9], $block[14]);
77  }
78 
79  $res = '';
80  for ($i = 0; $i < 16; $i++) {
81  $res .= pack('V', ($block[$i] + $init[$i]) & 0xFFFFFFFF);
82  }
83  return $res;
84  }
85 
86  public function encrypt($plain, $iv, $counter = 0)
87  {
88  if (strlen($iv) !== 8) {
89  throw new \InvalidArgumentException();
90  }
91 
92  $len = strlen($plain);
93  $m = ($len >> 6) + (($len % 64) > 0);
94  $keyStream = '';
95  for ($i = 0; $i < $m; $i++) {
96  $c = gmp_strval(gmp_add($counter, $i), 16);
97  $c = pack('H*', str_pad($c, 16, '0', STR_PAD_LEFT));
98  $keyStream .= $this->block($iv, strrev($c));
99  }
100  return $plain ^ $keyStream;
101  }
102 
103  public function decrypt($cipher, $iv, $counter = 0)
104  {
105  return $this->encrypt($cipher, $iv, $counter);
106  }
107 }
$key
Secret key used to encrypt/decrypt data.
Definition: ChaCha20.php:25