31 throw new \InvalidArgumentException(
'Incompatible cipher (block size != 16)');
34 $this->taglen = $tagLength;
38 $H = gmp_init(bin2hex($cipher->
encrypt(
'', str_repeat(
"\x00", 16))), 16);
39 $H = str_pad(gmp_strval($H, 2), 128,
'0', STR_PAD_LEFT);
40 $R = gmp_init(
'E1000000000000000000000000000000', 16);
42 $this->table = array();
43 for ($i = 0; $i < 16; $i++) {
44 $this->table[$i] = array();
45 for ($j = 0; $j < 256; $j++) {
46 $V = gmp_init(dechex($j) . str_repeat(
"00", $i), 16);
48 for ($k = 0; $k < 128; $k++) {
55 $odd = gmp_testbit($V, 0);
56 $V = gmp_div_q($V, 2);
61 $this->table[$i][$j] = pack(
'H*', str_pad(gmp_strval($Z, 16), 32, 0, STR_PAD_LEFT));
66 protected static function inc($X, $n)
68 $s = gmp_strval($X, 2);
69 $s1 = (string) substr($s, 0, -$n);
70 $s = gmp_add(gmp_init(substr($s, -$n), 2), 1);
71 $s = gmp_mod($s, gmp_pow(2, $n));
72 $s2 = str_pad(gmp_strval($s, 2), $n,
'0', STR_PAD_LEFT);
73 return gmp_init($s1 . $s2, 2);
76 protected function ghash($X)
78 $Xn = str_split($X, 16);
80 if (strlen($Xn[$m - 1]) != 16) {
81 throw new \InvalidArgumentException();
85 $Y =
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
87 for ($i = 0; $i < $m; $i++) {
90 for ($j = 0; $j < 16; $j++) {
91 $res = $res ^ $this->table[$j][ord($val[15 - $j])];
98 protected function gctr($ICB, $X)
104 $Xn = str_split($X, 16);
106 $CB = array(1 => $ICB);
108 for ($i = 1; $i < $n; $i++) {
109 $CB[$i + 1] = static::inc($CB[$i], 32);
111 $t = $this->cipher->encrypt(
114 pack(
'H*', str_pad(gmp_strval($CB[$i], 16), 32,
'0', STR_PAD_LEFT))
117 gmp_init(bin2hex($Xn[$i - 1]), 16),
118 gmp_init(bin2hex($t), 16)
120 $Yn[$i] = pack(
'H*', str_pad(gmp_strval($t, 16), 32,
'0', STR_PAD_LEFT));
124 $t = $this->cipher->encrypt(
127 pack(
'H*', str_pad(gmp_strval($CB[$n], 16), 32,
'0', STR_PAD_LEFT))
130 $t = str_pad(gmp_strval(gmp_init(bin2hex($t), 16), 16), 32,
'0', STR_PAD_LEFT);
131 $nn = strlen($Xn[$n - 1]) << 1;
132 $t = substr($t, 0, $nn);
134 $t = gmp_xor(gmp_init(bin2hex($Xn[$n - 1]), 16), gmp_init($t, 16));
135 $Yn[$n] = pack(
'H*', str_pad(gmp_strval($t, 16), $nn,
'0', STR_PAD_LEFT));
136 return implode(
'', $Yn);
139 protected function padIv()
142 $ivlen = strlen($this->iv);
144 $J0 = $this->iv .
"\x00\x00\x00\x01";
146 $s = (16 - ($ivlen % 16)) % 16;
147 $t = gmp_strval(gmp_init($ivlen << 3, 10), 16);
150 str_repeat(
"\x00", $s) .
151 pack(
'H*', str_pad($t, 32,
'0', STR_PAD_LEFT))
159 $options = stream_context_get_options($context);
160 $A = isset($options[
'cryptal'][
'data']) ? (string) $options[
'cryptal'][
'data'] :
'';
162 $J0 = gmp_init(bin2hex($this->padIv()), 16);
163 $C = $this->gctr(static::inc($J0, 32), $data);
165 $u = (16 - ($Cl % 16)) % 16;
167 $v = (16 - ($Al % 16)) % 16;
170 str_repeat(
"\x00", $v) .
172 str_repeat(
"\x00", $u) .
173 pack(
'H*', str_pad(gmp_strval(gmp_init($Al << 3, 10), 16), 16,
'0', STR_PAD_LEFT)) .
174 pack(
'H*', str_pad(gmp_strval(gmp_init($Cl << 3, 10), 16), 16,
'0', STR_PAD_LEFT))
176 $T = substr($this->gctr($J0, $S), 0, $this->taglen);
177 stream_context_set_option($context,
'cryptal',
'tag', $T);
183 $options = stream_context_get_options($context);
184 $A = isset($options[
'cryptal'][
'data']) ? (string) $options[
'cryptal'][
'data'] :
'';
185 $T = isset($options[
'cryptal'][
'tag']) ? (string) $options[
'cryptal'][
'tag'] :
'';
187 $J0 = gmp_init(bin2hex($this->padIv()), 16);
188 $P = $this->gctr(static::inc($J0, 32), $data);
190 $u = (16 - ($Cl % 16)) % 16;
192 $v = (16 - ($Al % 16)) % 16;
195 str_repeat(
"\x00", $v) .
197 str_repeat(
"\x00", $u) .
198 pack(
'H*', str_pad(gmp_strval(gmp_init($Al << 3, 10), 16), 16,
'0', STR_PAD_LEFT)) .
199 pack(
'H*', str_pad(gmp_strval(gmp_init($Cl << 3, 10), 16), 16,
'0', STR_PAD_LEFT))
201 $T2 = substr($this->gctr($J0, $S), 0, $this->taglen);
203 throw new \InvalidArgumentException(
'Tag does not match expected value');
encrypt($iv, $data, &$tag=null, $aad= '')
$table
Pre-computation table for GF(2**128)
__construct(CryptoInterface $cipher, $iv, $tagLength)
$taglen
Output tag length (in bytes)
$cipher
Approved block cipher with a 128-bit block size.
$iv
Initialization Vector.