34 $logging = \Plop\Plop::getInstance();
36 $this->cipher = mcrypt_module_open(
$cipher, null,
'ecb', null);
37 mcrypt_generic_init($this->cipher, $key, str_repeat(
"\x00", 16));
40 $logging->debug(
'Pre-computing GCM table');
42 bin2hex(mcrypt_generic($this->cipher, str_repeat(
"\x00", 16))),
45 $H = str_pad(gmp_strval(
$H, 2), 128,
'0', STR_PAD_LEFT);
46 $R = gmp_init(
'E1000000000000000000000000000000', 16);
48 $this->table = array();
49 for ($i = 0; $i < 16; $i++) {
50 $this->table[$i] = array();
51 for ($j = 0; $j < 256; $j++) {
52 $V = gmp_init(dechex($j) . str_repeat(
"00", $i), 16);
54 for ($k = 0; $k < 128; $k++) {
61 $odd = gmp_testbit($V, 0);
62 $V = gmp_div_q($V, 2);
67 $this->table[$i][$j] = pack(
'H*', str_pad(gmp_strval($Z, 16), 32, 0, STR_PAD_LEFT));
70 $logging->debug(
'Done pre-computing GCM table');
73 public function __destruct()
75 mcrypt_generic_deinit($this->cipher);
78 public static function inc($X, $n)
80 $s = gmp_strval($X, 2);
81 $s1 = (string) substr($s, 0, -$n);
82 $s = gmp_add(gmp_init(substr($s, -$n), 2), 1);
83 $s = gmp_mod($s, gmp_pow(2, $n));
84 $s2 = str_pad(gmp_strval($s, 2), $n,
'0', STR_PAD_LEFT);
85 return gmp_init($s1 . $s2, 2);
88 protected function ghash($X)
90 $Xn = str_split($X, 16);
92 if (strlen($Xn[$m - 1]) != 16) {
93 throw new \InvalidArgumentException();
97 $Y =
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
99 for ($i = 0; $i < $m; $i++) {
102 for ($j = 0; $j < 16; $j++) {
103 $res = $res ^ $this->table[$j][ord($val[15 - $j])];
110 protected function gctr($ICB, $X)
116 $Xn = str_split($X, 16);
118 $CB = array(1 => $ICB);
120 for ($i = 1; $i < $n; $i++) {
121 $CB[$i + 1] = static::inc($CB[$i], 32);
126 pack(
'H*', str_pad(gmp_strval($CB[$i], 16), 32,
'0', STR_PAD_LEFT))
129 gmp_init(bin2hex($Xn[$i - 1]), 16),
130 gmp_init(bin2hex($t), 16)
132 $Yn[$i] = pack(
'H*', str_pad(gmp_strval($t, 16), 32,
'0', STR_PAD_LEFT));
139 pack(
'H*', str_pad(gmp_strval($CB[$n], 16), 32,
'0', STR_PAD_LEFT))
142 $t = str_pad(gmp_strval(gmp_init(bin2hex($t), 16), 16), 32,
'0', STR_PAD_LEFT);
143 $nn = strlen($Xn[$n - 1]) << 1;
144 $t = substr($t, 0, $nn);
146 $t = gmp_xor(gmp_init(bin2hex($Xn[$n - 1]), 16), gmp_init($t, 16));
147 $Yn[$n] = pack(
'H*', str_pad(gmp_strval($t, 16), $nn,
'0', STR_PAD_LEFT));
148 return implode(
'', $Yn);
151 public function ae($IV, $P, $A)
154 $ivlen = strlen($IV);
156 $J0 = $IV .
"\x00\x00\x00\x01";
158 $s = (16 - ($ivlen % 16)) % 16;
159 $t = gmp_strval(gmp_init($ivlen << 3, 10), 16);
162 str_repeat(
"\x00", $s) .
163 pack(
'H*', str_pad($t, 32,
'0', STR_PAD_LEFT))
167 $J0 = gmp_init(bin2hex($J0), 16);
168 $C = $this->gctr(static::inc($J0, 32), $P);
170 $u = (16 - ($Cl % 16)) % 16;
172 $v = (16 - ($Al % 16)) % 16;
175 str_repeat(
"\x00", $v) .
177 str_repeat(
"\x00", $u) .
178 pack(
'H*', str_pad(gmp_strval(gmp_init($Al << 3, 10), 16), 16,
'0', STR_PAD_LEFT)) .
179 pack(
'H*', str_pad(gmp_strval(gmp_init($Cl << 3, 10), 16), 16,
'0', STR_PAD_LEFT))
181 $T = substr($this->gctr($J0, $S), 0, $this->taglen >> 3);
182 return array($C, $T);
185 public function ad($IV, $C, $A, $T)
188 if (strlen($T) !== $this->taglen >> 3) {
192 $ivlen = strlen($IV);
194 $J0 = $IV .
"\x00\x00\x00\x01";
196 $s = (16 - ($ivlen % 16)) % 16;
197 $t = gmp_strval(gmp_init($ivlen << 3, 10), 16);
200 str_repeat(
"\x00", $s) .
201 pack(
'H*', str_pad($t, 32,
'0', STR_PAD_LEFT))
205 $J0 = gmp_init(bin2hex($J0), 16);
206 $P = $this->gctr(static::inc($J0, 32), $C);
208 $u = (16 - ($Cl % 16)) % 16;
210 $v = (16 - ($Al % 16)) % 16;
213 str_repeat(
"\x00", $v) .
215 str_repeat(
"\x00", $u) .
216 pack(
'H*', str_pad(gmp_strval(gmp_init($Al << 3, 10), 16), 16,
'0', STR_PAD_LEFT)) .
217 pack(
'H*', str_pad(gmp_strval(gmp_init($Cl << 3, 10), 16), 16,
'0', STR_PAD_LEFT))
219 $T2 = substr($this->gctr($J0, $S), 0, $this->taglen >> 3);
$table
Pre-computation table for GF(2**128)
$H
Block H, the hash subkey.
$taglen
Output tag length.
$cipher
Approved block cipher with a 128-bit block size.