47 const SIGMA1 =
"\xA0\x9E\x66\x7F\x3B\xCC\x90\x8B";
50 const SIGMA2 =
"\xB6\x7A\xE8\x58\x4C\xAA\x73\xB2";
53 const SIGMA3 =
"\xC6\xEF\x37\x2F\xE9\x4F\x82\xBE";
56 const SIGMA4 =
"\x54\xFF\x53\xA5\xF1\xD3\x6F\x1C";
59 const SIGMA5 =
"\x10\xE5\x27\xFA\xDE\x68\x2D\x1D";
62 const SIGMA6 =
"\xB0\x56\x88\xC2\xB3\xE6\xC1\xFD";
72 $tagLength = self::DEFAULT_TAG_LENGTH
74 if (null === self::$sbox1) {
77 "\x70\x82\x2C\xEC\xB3\x27\xC0\xE5\xE4\x85\x57\x35\xEA\x0C\xAE\x41" .
78 "\x23\xEF\x6B\x93\x45\x19\xA5\x21\xED\x0E\x4F\x4E\x1D\x65\x92\xBD" .
79 "\x86\xB8\xAF\x8F\x7C\xEB\x1F\xCE\x3E\x30\xDC\x5F\x5E\xC5\x0B\x1A" .
80 "\xA6\xE1\x39\xCA\xD5\x47\x5D\x3D\xD9\x01\x5A\xD6\x51\x56\x6C\x4D" .
81 "\x8B\x0D\x9A\x66\xFB\xCC\xB0\x2D\x74\x12\x2B\x20\xF0\xB1\x84\x99" .
82 "\xDF\x4C\xCB\xC2\x34\x7E\x76\x05\x6D\xB7\xA9\x31\xD1\x17\x04\xD7" .
83 "\x14\x58\x3A\x61\xDE\x1B\x11\x1C\x32\x0F\x9C\x16\x53\x18\xF2\x22" .
84 "\xFE\x44\xCF\xB2\xC3\xB5\x7A\x91\x24\x08\xE8\xA8\x60\xFC\x69\x50" .
85 "\xAA\xD0\xA0\x7D\xA1\x89\x62\x97\x54\x5B\x1E\x95\xE0\xFF\x64\xD2" .
86 "\x10\xC4\x00\x48\xA3\xF7\x75\xDB\x8A\x03\xE6\xDA\x09\x3F\xDD\x94" .
87 "\x87\x5C\x83\x02\xCD\x4A\x90\x33\x73\x67\xF6\xF3\x9D\x7F\xBF\xE2" .
88 "\x52\x9B\xD8\x26\xC8\x37\xC6\x3B\x81\x96\x6F\x4B\x13\xBE\x63\x2E" .
89 "\xE9\x79\xA7\x8C\x9F\x6E\xBC\x8E\x29\xF5\xF9\xB6\x2F\xFD\xB4\x59" .
90 "\x78\x98\x06\x6A\xE7\x46\x71\xBA\xD4\x25\xAB\x42\x88\xA2\x8D\xFA" .
91 "\x72\x07\xB9\x55\xF8\xEE\xAC\x0A\x36\x49\x2A\x68\x3C\x38\xF1\xA4" .
92 "\x40\x28\xD3\x7B\xBB\xC9\x43\xC1\x15\xE3\xAD\xF4\x77\xC7\x80\x9E";
96 CipherEnum::CIPHER_CAMELIA_128(),
97 CipherEnum::CIPHER_CAMELIA_192(),
98 CipherEnum::CIPHER_CAMELIA_256(),
101 if (!in_array($cipher, $supported)) {
102 throw new \InvalidArgumentException(
'Unsupported cipher');
105 if (ModeEnum::MODE_ECB() != $mode) {
106 throw new \InvalidArgumentException(
'Unsupported mode');
111 $this->cipher = $cipher;
128 $codes = array_map(
'ord', str_split($value));
129 $binary = vsprintf(str_repeat(
"%08b", strlen($value)), $codes);
130 $rot = substr($binary, $n) . substr($binary, 0, $n);
131 $codes = array_map(
'bindec', str_split($rot, 8));
132 return implode(
'', array_map(
'chr', $codes));
150 $KL = substr($key, 0, 16);
151 $this->keyLength = strlen($key) << 3;
152 switch ($this->keyLength) {
154 $KR = str_repeat(
"\x00", 16);
157 $KR = substr($key, -8) . (substr($key, -8) ^
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF");
160 $KR = substr($key, -16);
163 throw new \InvalidArgumentException(
'Invalid key length');
167 $D1 = substr($KL ^ $KR, 0, 8);
168 $D2 = substr($KL ^ $KR, 8);
169 $D2 ^= self::f($D1, self::SIGMA1);
170 $D1 ^= self::f($D2, self::SIGMA2);
171 $D1 ^= substr($KL, 0, 8);
172 $D2 ^= substr($KL, 8);
173 $D2 ^= self::f($D1, self::SIGMA3);
174 $D1 ^= self::f($D2, self::SIGMA4);
176 $D1 = substr($KA ^ $KR, 0, 8);
177 $D2 = substr($KA ^ $KR, 8);
178 $D2 ^= self::f($D1, self::SIGMA5);
179 $D1 ^= self::f($D2, self::SIGMA6);
184 if (128 === $this->keyLength) {
191 $kw[] = substr(self::rotateLeft($KL, 0), 0, 8);
192 $kw[] = substr(self::rotateLeft($KL, 0), 8);
193 $k[] = substr(self::rotateLeft($KB, 0), 0, 8);
194 $k[] = substr(self::rotateLeft($KB, 0), 8);
195 $k[] = substr(self::rotateLeft($KR, 15), 0, 8);
196 $k[] = substr(self::rotateLeft($KR, 15), 8);
197 $k[] = substr(self::rotateLeft($KA, 15), 0, 8);
198 $k[] = substr(self::rotateLeft($KA, 15), 8);
200 if (128 === $this->keyLength) {
201 $ke[] = substr(self::rotateLeft($KA, 30), 0, 8);
202 $ke[] = substr(self::rotateLeft($KA, 30), 8);
204 $ke[] = substr(self::rotateLeft($KR, 30), 0, 8);
205 $ke[] = substr(self::rotateLeft($KR, 30), 8);
206 $k[] = substr(self::rotateLeft($KB, 30), 0, 8);
207 $k[] = substr(self::rotateLeft($KB, 30), 8);
211 $k[] = substr(self::rotateLeft($KL, 45), 0, 8);
212 $k[] = substr(self::rotateLeft($KL, 45), 8);
213 $k[] = substr(self::rotateLeft($KA, 45), 0, 8);
215 if (128 === $this->keyLength) {
216 $k[] = substr(self::rotateLeft($KL, 60), 8);
218 $k[] = substr(self::rotateLeft($KA, 45), 8);
219 $ke[] = substr(self::rotateLeft($KL, 60), 0, 8);
220 $ke[] = substr(self::rotateLeft($KL, 60), 8);
221 $k[] = substr(self::rotateLeft($KR, 60), 0, 8);
222 $k[] = substr(self::rotateLeft($KR, 60), 8);
226 $k[] = substr(self::rotateLeft($KB, 60), 0, 8);
227 $k[] = substr(self::rotateLeft($KB, 60), 8);
229 if (128 === $this->keyLength) {
230 $ke[] = substr(self::rotateLeft($KL, 77), 0, 8);
231 $ke[] = substr(self::rotateLeft($KL, 77), 8);
233 $k[] = substr(self::rotateLeft($KL, 77), 0, 8);
234 $k[] = substr(self::rotateLeft($KL, 77), 8);
235 $ke[] = substr(self::rotateLeft($KA, 77), 0, 8);
236 $ke[] = substr(self::rotateLeft($KA, 77), 8);
240 $k[] = substr(self::rotateLeft($KR, 94), 0, 8);
241 $k[] = substr(self::rotateLeft($KR, 94), 8);
242 $k[] = substr(self::rotateLeft($KA, 94), 0, 8);
243 $k[] = substr(self::rotateLeft($KA, 94), 8);
244 $k[] = substr(self::rotateLeft($KL, 111), 0, 8);
245 $k[] = substr(self::rotateLeft($KL, 111), 8);
246 $kw[] = substr(self::rotateLeft($KB, 111), 0, 8);
247 $kw[] = substr(self::rotateLeft($KB, 111), 8);
256 for ($i = 1, $n = count(
$k); $i <= $n; $i++) {
257 $k2[$i] =
$k[$n - $i + 1];
259 for ($i = 1, $n = count(
$ke); $i <= $n; $i++) {
286 protected static function sbox($n, $x)
290 $x = self::rotateLeft($x, 1);
292 $x = self::rotateLeft($x, 0);
295 $rotation = array(1 => 0, 1, 7, 0);
296 return self::rotateLeft(self::$sbox1[ord($x)], $rotation[$n]);
311 protected function f($F_IN, $KE)
315 $t1 = self::sbox(1, $t[0]);
316 $t2 = self::sbox(2, $t[1]);
317 $t3 = self::sbox(3, $t[2]);
318 $t4 = self::sbox(4, $t[3]);
319 $t5 = self::sbox(2, $t[4]);
320 $t6 = self::sbox(3, $t[5]);
321 $t7 = self::sbox(4, $t[6]);
322 $t8 = self::sbox(1, $t[7]);
323 $y1 = $t1 ^ $t3 ^ $t4 ^ $t6 ^ $t7 ^ $t8;
324 $y2 = $t1 ^ $t2 ^ $t4 ^ $t5 ^ $t7 ^ $t8;
325 $y3 = $t1 ^ $t2 ^ $t3 ^ $t5 ^ $t6 ^ $t8;
326 $y4 = $t2 ^ $t3 ^ $t4 ^ $t5 ^ $t6 ^ $t7;
327 $y5 = $t1 ^ $t2 ^ $t6 ^ $t7 ^ $t8;
328 $y6 = $t2 ^ $t3 ^ $t5 ^ $t7 ^ $t8;
329 $y7 = $t3 ^ $t4 ^ $t5 ^ $t6 ^ $t8;
330 $y8 = $t1 ^ $t4 ^ $t5 ^ $t6 ^ $t7;
331 $res = $y1 . $y2 . $y3 . $y4 . $y5 . $y6 . $y7 . $y8;
350 protected static function fl($FL_IN, $KE)
352 $x1 = substr($FL_IN, 0, 4);
353 $x2 = substr($FL_IN, 4);
354 $k1 = substr($KE, 0, 4);
355 $k2 = substr($KE, 4);
356 $x2 ^= self::rotateLeft($x1 & $k1, 1);
377 protected static function flinv($FLINV_IN, $KE)
379 $y1 = substr($FLINV_IN, 0, 4);
380 $y2 = substr($FLINV_IN, 4);
381 $k1 = substr($KE, 0, 4);
382 $k2 = substr($KE, 4);
384 $y2 ^= self::rotateLeft($y1 & $k1, 1);
413 $D1 = substr($m, 0, 8);
420 $nbBlocks = count($k) / 6;
421 for ($i = 0; $i < $nbBlocks; $i++) {
423 $D1 = self::fl($D1, $ke[$i * 2 - 1]);
424 $D2 = self::flinv($D2, $ke[$i * 2]);
427 $D2 ^= self::f($D1, $k[$i * 6 + 1]);
428 $D1 ^= self::f($D2, $k[$i * 6 + 2]);
429 $D2 ^= self::f($D1, $k[$i * 6 + 3]);
430 $D1 ^= self::f($D2, $k[$i * 6 + 4]);
431 $D2 ^= self::f($D1, $k[$i * 6 + 5]);
432 $D1 ^= self::f($D2, $k[$i * 6 + 6]);
442 public function encrypt($iv, $data, &$tag = null, $aad =
'')
445 if (strlen($data) % $blockSize) {
446 throw new \InvalidArgumentException(
'Invalid block');
450 foreach (str_split($data, $blockSize) as $block) {
451 $res .= $this->
xcrypt($block, $this->k, $this->ke, $this->kw);
456 public function decrypt($iv, $data, $tag = null, $aad =
'')
459 if (strlen($data) % $blockSize) {
460 throw new \InvalidArgumentException(
'Invalid block');
464 foreach (str_split($data, $blockSize) as $block) {
465 $res .= $this->
xcrypt($block, $this->k2, $this->ke2, $this->kw2);
482 return $this->cipher;
const SIGMA5
Sigma5 constant (from the RFC)
__construct(CipherEnum $cipher, ModeEnum $mode, PaddingInterface $padding, $key, $tagLength=self::DEFAULT_TAG_LENGTH)
$kw
Subkeys used for whitening during encryption.
$ke
Subkeys used by the Feistel structure during encryption.
encrypt($iv, $data, &$tag=null, $aad= '')
$k
Subkeys used for encryption.
static rotateLeft($value, $n)
$keyLength
Original key length in bits (128, 192 or 256)
static flinv($FLINV_IN, $KE)
const SIGMA2
Sigma2 constant (from the RFC)
static $sbox1
Character string containing the whole sbox1 crypto-box.
$k2
Subkeys used for decryption.
$kw2
Subkeys used for whitening during decryption.
const SIGMA3
Sigma3 constant (from the RFC)
$ke2
Subkeys used by the Feistel structure during decryption.
const SIGMA1
Sigma1 constant (from the RFC)
const SIGMA4
Sigma4 constant (from the RFC)
decrypt($iv, $data, $tag=null, $aad= '')
xcrypt($m, array $k, array $ke, array $kw)
const SIGMA6
Sigma6 constant (from the RFC)