28 throw new \InvalidArgumentException(
'Incompatible cipher (block size != 16)');
31 $nonceSize = strlen($iv);
32 if ($nonceSize < 7 || $nonceSize > 13) {
33 throw new \Exception(
"Invalid nonce (should be between 7 and 13 bytes long)");
36 if (($tagLength & 0x1) || $tagLength < 4 || $tagLength > 16) {
37 throw new \Exception(
"Invalid tag length (valid values: 4, 6, 8, 10, 12, 14 & 16)");
42 $this->L = 15 - $nonceSize;
43 $this->M = ($tagLength - 2) >> 1;
46 protected function checkum(
$M, $A)
53 throw new \InvalidArgumentException(
'Invalid length for input data (greater than 2**8L)');
59 $lenM = str_pad(ltrim(pack(
'N', strlen(
$M)),
"\x00"), $this->L,
"\x00", STR_PAD_LEFT);
60 $b = chr((($lenA > 0) << 6) | ($this->M << 3) | ($this->L - 1)) . $this->nonce . $lenM;
63 if ($lenA < ((1 << 16) - (1 << 8))) {
65 $b .= pack(
"n", $lenA);
66 } elseif (($lenA >> 32) === 0) {
68 $b .= pack(
"nN", 0xFEFF, $lenA);
71 throw new \RuntimeException(
'Not implemented yet');
76 $b .= str_repeat(
"\x00", (16 - (strlen($b) % 16)) % 16);
80 $b .= str_repeat(
"\x00", (16 - (strlen($b) % 16)) % 16);
83 $X = str_repeat(
"\x00", 16);
84 foreach (str_split($b, 16) as $block) {
85 $X = $this->cipher->encrypt(
'', $X ^ $block);
87 $T = substr($X, 0, ($this->M << 1) + 2);
95 for ($i = $this->L - 1; $i >= 0; $i--) {
97 $c[$i] = chr(ord($c[$i]) + $carry);
98 $carry &= (
"\x00" === $c[$i]);
106 $options = stream_context_get_options($context);
107 $Adata = isset($options[
'cryptal'][
'data']) ? (string) $options[
'cryptal'][
'data'] :
'';
108 $counter = str_repeat(
"\x00", $this->L);
110 $S0 = $this->cipher->encrypt(
'', $a . $counter);
113 foreach (str_split($data, 16) as $block) {
115 $res .= $block ^ $this->cipher->encrypt(
'', $a . $counter);
118 stream_context_set_option($context,
'cryptal',
'tag', $this->checkum($data, $Adata) ^ $S0);
124 $options = stream_context_get_options($context);
125 $Adata = isset($options[
'cryptal'][
'data']) ? (string) $options[
'cryptal'][
'data'] :
'';
126 $T = isset($options[
'cryptal'][
'tag']) ? (string) $options[
'cryptal'][
'tag'] :
'';
127 $counter = str_repeat(
"\x00", $this->L);
129 $S0 = $this->cipher->encrypt(
'', $a . $counter);
132 foreach (str_split($data, 16) as $block) {
134 $res .= $block ^ $this->cipher->encrypt(
'', $a . $counter);
137 $T2 = $this->checkum($res, $Adata) ^ $S0;
139 throw new \InvalidArgumentException(
'Tag does not match expected value');
__construct(CryptoInterface $cipher, $iv, $tagLength)
incrementCounter($c)
Increment the value of the counter by one.