1 | <?php |
||
15 | * @link http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf |
||
16 | */ |
||
17 | class GCM |
||
18 | { |
||
19 | /** |
||
20 | * Block of 64 zero bits. |
||
21 | * |
||
22 | * @var string |
||
23 | */ |
||
24 | const ZB_64 = "\0\0\0\0\0\0\0\0"; |
||
25 | |||
26 | /** |
||
27 | * Block of 128 zero bits. |
||
28 | * |
||
29 | * @var string |
||
30 | */ |
||
31 | const ZB_128 = self::ZB_64 . self::ZB_64; |
||
32 | |||
33 | /** |
||
34 | * Array of supported t-values, that is, the bit length of the |
||
35 | * authentication tag. |
||
36 | * |
||
37 | * See NIST SP-800-38D section 5.2.1.2 for the details. |
||
38 | * |
||
39 | * @internal |
||
40 | * |
||
41 | * @var array |
||
42 | */ |
||
43 | const SUPPORTED_T_LEN = array(128, 120, 112, 104, 96, 64, 32); |
||
44 | |||
45 | /** |
||
46 | * Cipher. |
||
47 | * |
||
48 | * @var Cipher $_cipher |
||
49 | */ |
||
50 | protected $_cipher; |
||
51 | |||
52 | /** |
||
53 | * Authentication tag length in bytes. |
||
54 | * |
||
55 | * @var int |
||
56 | */ |
||
57 | protected $_tagLength; |
||
58 | |||
59 | /** |
||
60 | * Constructor. |
||
61 | * |
||
62 | * @param Cipher $cipher Cipher implementation |
||
63 | * @param int $tag_length Authentication tag length in bytes |
||
64 | * @throws \DomainException If tag length is not supported |
||
65 | */ |
||
66 | 46 | public function __construct(Cipher $cipher, int $tag_length = 16) |
|
75 | |||
76 | /** |
||
77 | * Encrypt plaintext. |
||
78 | * |
||
79 | * @param string $P Plaintext |
||
80 | * @param string $A Additional authenticated data |
||
81 | * @param string $K Encryption key |
||
82 | * @param string $IV Initialization vector |
||
83 | * @throws \RuntimeException For generic errors |
||
84 | * @return array Tuple of ciphertext <code>C</code> and authentication tag |
||
85 | * <code>T</code> |
||
86 | */ |
||
87 | 46 | public function encrypt(string $P, string $A, string $K, string $IV): array |
|
98 | |||
99 | /** |
||
100 | * Decrypt ciphertext. |
||
101 | * |
||
102 | * @param string $C Ciphertext |
||
103 | * @param string $T Authentication tag |
||
104 | * @param string $A Additional authenticated data |
||
105 | * @param string $K Encryption key |
||
106 | * @param string $IV Initialization vector |
||
107 | * @throws AuthenticationException If message authentication fails |
||
108 | * @throws \RuntimeException For generic errors |
||
109 | * @return string Plaintext <code>P</code> |
||
110 | */ |
||
111 | 44 | public function decrypt(string $C, string $T, string $A, string $K, |
|
126 | |||
127 | /** |
||
128 | * Generate pre-counter block. |
||
129 | * |
||
130 | * See NIST SP-300-38D section 7.1 step 2 for the details. |
||
131 | * |
||
132 | * @param string $IV Initialization vector |
||
133 | * @param GHASH $ghash GHASH functor |
||
134 | * @return string |
||
135 | */ |
||
136 | 49 | private function _generateJ0(string $IV, GHASH $ghash): string |
|
146 | |||
147 | /** |
||
148 | * Apply GCTR algorithm. |
||
149 | * |
||
150 | * See NIST SP-300-38D section 6.5 for the details. |
||
151 | * |
||
152 | * @param string $ICB Initial counter block |
||
153 | * @param string $X Input data |
||
154 | * @param string $K Encryption key |
||
155 | * @return string Output data |
||
156 | */ |
||
157 | 49 | private function _gctr(string $ICB, string $X, string $K): string |
|
181 | |||
182 | /** |
||
183 | * Compute authentication tag |
||
184 | * |
||
185 | * See NIST SP-300-38D section 7.1 steps 5-6 for the details. |
||
186 | * |
||
187 | * @param string $A Additional authenticated data |
||
188 | * @param string $C Ciphertext |
||
189 | * @param string $J0 Pre-counter block |
||
190 | * @param string $K Encryption key |
||
191 | * @param GHASH $ghash GHASH functor |
||
192 | * @return string Authentication tag <code>T</code> |
||
193 | */ |
||
194 | 49 | private function _computeAuthTag(string $A, string $C, string $J0, string $K, |
|
202 | |||
203 | /** |
||
204 | * Pad data to 128 bit block boundary. |
||
205 | * |
||
206 | * @param string $data |
||
207 | * @return string |
||
208 | */ |
||
209 | 49 | private static function _pad128($data) |
|
217 | |||
218 | /** |
||
219 | * Increment 32 rightmost bits of the counter block. |
||
220 | * |
||
221 | * See NIST SP-300-38D section 6.2 for the details. |
||
222 | * |
||
223 | * @param string $X |
||
224 | * @return string |
||
225 | */ |
||
226 | 49 | private static function _inc32(string $X): string |
|
235 | |||
236 | /** |
||
237 | * Convert integer to 64 bit big endian binary string. |
||
238 | * |
||
239 | * @param int $num |
||
240 | * @return string |
||
241 | */ |
||
242 | 49 | private static function _uint64(int $num): string |
|
250 | |||
251 | /** |
||
252 | * Convert string to GMP number. |
||
253 | * |
||
254 | * String is interpreted as an unsigned integer with big endian order and |
||
255 | * the most significant byte first. |
||
256 | * |
||
257 | * @param string $data Binary data |
||
258 | * @return \GMP |
||
259 | */ |
||
260 | 53 | public static function strToGMP(string $data): \GMP |
|
264 | |||
265 | /** |
||
266 | * Convert GMP number to string. |
||
267 | * |
||
268 | * Returned string represents an unsigned integer with big endian order and |
||
269 | * the most significant byte first. |
||
270 | * |
||
271 | * @param \GMP $num GMP number |
||
272 | * @param int $size Width of the string in bytes |
||
273 | * @return string Binary data |
||
274 | */ |
||
275 | 53 | public static function gmpToStr(\GMP $num, int $size): string |
|
276 | { |
||
277 | 53 | $data = gmp_export($num, 1, GMP_MSW_FIRST | GMP_BIG_ENDIAN); |
|
278 | 53 | $len = strlen($data); |
|
279 | 53 | if ($len < $size) { |
|
280 | 43 | $data = str_repeat("\0", $size - $len) . $data; |
|
281 | } |
||
285 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.