Code Duplication    Length = 199-215 lines in 3 locations

includes/libraries/Encryption/Crypt/aesctr.php 1 location

@@ 10-224 (lines=215) @@
7
/*    form is offered.                                                                            */
8
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
9
10
class Aes
11
{
12
    /**
13
     * AES Cipher function: encrypt 'input' with Rijndael algorithm
14
     *
15
     * @param input message as byte-array (16 bytes)
16
     * @param w     key schedule as 2D byte-array (Nr+1 x Nb bytes) -
17
     *              generated from the cipher key by keyExpansion()
18
     * @return ciphertext as byte-array (16 bytes)
19
     */
20
    public static function cipher($input, $w)
21
    {
22
        // main cipher function [é5.1]
23
        $Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
24
        $Nr = count($w) / $Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
25
26
        $state = array(); // initialise 4xNb byte-array 'state' with input [é3.4]
27
        for ($i = 0; $i < 4 * $Nb; $i++) {
28
            $state[$i % 4][floor($i / 4)] = $input[$i];
29
        }
30
31
        $state = self::addRoundKey($state, $w, 0, $Nb);
32
33
        for ($round = 1; $round < $Nr; $round++) {  // apply Nr rounds
34
            $state = self::subBytes($state, $Nb);
35
            $state = self::shiftRows($state, $Nb);
36
            $state = self::mixColumns($state, $Nb);
37
            $state = self::addRoundKey($state, $w, $round, $Nb);
38
        }
39
40
        $state = self::subBytes($state, $Nb);
41
        $state = self::shiftRows($state, $Nb);
42
        $state = self::addRoundKey($state, $w, $Nr, $Nb);
43
44
        $output = array(4 * $Nb); // convert state to 1-d array before returning [é3.4]
45
        for ($i = 0; $i < 4 * $Nb; $i++) {
46
            $output[$i] = $state[$i % 4][floor($i / 4)];
47
        }
48
49
        return $output;
50
    }
51
52
    /**
53
     * @param integer $rnd
54
     * @param integer $Nb
55
     */
56
    private static function addRoundKey($state, $w, $rnd, $Nb)
57
    {
58
        // xor Round Key into state S [é5.1.4]
59
        for ($r = 0; $r < 4; $r++) {
60
            for ($c = 0; $c < $Nb; $c++) {
61
                $state[$r][$c] ^= $w[$rnd * 4 + $c][$r];
62
            }
63
        }
64
65
        return $state;
66
    }
67
68
    /**
69
     * @param integer $Nb
70
     */
71
    private static function subBytes($s, $Nb)
72
    {
73
        // apply SBox to state S [é5.1.1]
74
        for ($r = 0; $r < 4; $r++) {
75
            for ($c = 0; $c < $Nb; $c++) {
76
                $s[$r][$c] = self::$sBox[$s[$r][$c]];
77
            }
78
        }
79
80
        return $s;
81
    }
82
83
    /**
84
     * @param integer $Nb
85
     */
86
    private static function shiftRows($s, $Nb)
87
    {
88
        // shift row r of state S left by r bytes [é5.1.2]
89
        $t = array(4);
90
        for ($r = 1; $r < 4; $r++) {
91
            for ($c = 0; $c < 4; $c++) {
92
                $t[$c] = $s[$r][($c + $r) % $Nb]; // shift into temp copy
93
            }
94
            for ($c = 0; $c < 4; $c++) {
95
                $s[$r][$c] = $t[$c]; // and copy back
96
            }
97
        }          // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
98
        return $s; // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
99
    }
100
101
    /**
102
     * @param integer $Nb
103
     */
104
    private static function mixColumns($s, $Nb)
105
    {
106
        // combine bytes of each col of state S [é5.1.3]
107
        for ($c = 0; $c < 4; $c++) {
108
            $a = array(4); // 'a' is a copy of the current column from 's'
109
            $b = array(4); // 'b' is aé{02} in GF(2^8)
110
            for ($i = 0; $i < 4; $i++) {
111
                $a[$i] = $s[$i][$c];
112
                $b[$i] = $s[$i][$c] & 0x80 ? $s[$i][$c] << 1 ^ 0x011b : $s[$i][$c] << 1;
113
            }
114
            // a[n] ^ b[n] is aé{03} in GF(2^8)
115
            $s[0][$c] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; // 2*a0 + 3*a1 + a2 + a3
116
            $s[1][$c] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; // a0 * 2*a1 + 3*a2 + a3
117
            $s[2][$c] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; // a0 + a1 + 2*a2 + 3*a3
118
            $s[3][$c] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; // 3*a0 + a1 + a2 + 2*a3
119
        }
120
121
        return $s;
122
    }
123
124
    /**
125
     * Key expansion for Rijndael cipher(): performs key expansion on cipher key
126
     * to generate a key schedule
127
     *
128
     * @param key cipher key byte-array (16 bytes)
129
     * @return key schedule as 2D byte-array (Nr+1 x Nb bytes)
130
     */
131
    public static function keyExpansion($key)
132
    {
133
        // generate Key Schedule from Cipher Key [é5.2]
134
        $Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
135
        $Nk = count($key) / 4; // key length (in words): 4/6/8 for 128/192/256-bit keys
136
        $Nr = $Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys
137
138
        $w = array();
139
        $temp = array();
140
141
        for ($i = 0; $i < $Nk; $i++) {
142
            $r = array($key[4 * $i], $key[4 * $i + 1], $key[4 * $i + 2], $key[4 * $i + 3]);
143
            $w[$i] = $r;
144
        }
145
146
        for ($i = $Nk; $i < ($Nb * ($Nr + 1)); $i++) {
147
            $w[$i] = array();
148
            for ($t = 0; $t < 4; $t++) {
149
                $temp[$t] = $w[$i - 1][$t];
150
            }
151
            if ($i % $Nk == 0) {
152
                $temp = self::subWord(self::rotWord($temp));
153
                for ($t = 0; $t < 4; $t++) {
154
                    $temp[$t] ^= self::$rCon[$i / $Nk][$t];
155
                }
156
            } elseif ($Nk > 6 && $i % $Nk == 4) {
157
                $temp = self::subWord($temp);
158
            }
159
            for ($t = 0; $t < 4; $t++) {
160
                $w[$i][$t] = $w[$i - $Nk][$t] ^ $temp[$t];
161
            }
162
        }
163
164
        return $w;
165
    }
166
167
    private static function subWord($w)
168
    {
169
        // apply SBox to 4-byte word w
170
        for ($i = 0; $i < 4; $i++) {
171
            $w[$i] = self::$sBox[$w[$i]];
172
        }
173
174
        return $w;
175
    }
176
177
    private static function rotWord($w)
178
    {
179
        // rotate 4-byte word w left by one byte
180
        $tmp = $w[0];
181
        for ($i = 0; $i < 3; $i++) {
182
            $w[$i] = $w[$i + 1];
183
        }
184
        $w[3] = $tmp;
185
186
        return $w;
187
    }
188
189
    // sBox is pre-computed multiplicative inverse in GF(2^8) used in subBytes and keyExpansion [é5.1.1]
190
    private static $sBox = array(
191
            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
192
            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
193
            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
194
            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
195
            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
196
            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
197
            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
198
            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
199
            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
200
            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
201
            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
202
            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
203
            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
204
            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
205
            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
206
            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
207
    );
208
209
    // rCon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [é5.2]
210
    private static $rCon = array(
211
            array(0x00, 0x00, 0x00, 0x00),
212
            array(0x01, 0x00, 0x00, 0x00),
213
            array(0x02, 0x00, 0x00, 0x00),
214
            array(0x04, 0x00, 0x00, 0x00),
215
            array(0x08, 0x00, 0x00, 0x00),
216
            array(0x10, 0x00, 0x00, 0x00),
217
            array(0x20, 0x00, 0x00, 0x00),
218
            array(0x40, 0x00, 0x00, 0x00),
219
            array(0x80, 0x00, 0x00, 0x00),
220
            array(0x1b, 0x00, 0x00, 0x00),
221
            array(0x36, 0x00, 0x00, 0x00)
222
    );
223
224
}
225
226
class aesctr extends Aes
227
{

install/js/crypt/aes.class.php 1 location

@@ 7-205 (lines=199) @@
4
/*    commercial or non-commercial use under CC-BY licence. No warranty of any form is offered.   */
5
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
6
7
class Aes
8
{
9
    /**
10
     * AES Cipher function: encrypt 'input' with Rijndael algorithm
11
     *
12
     * @param input message as byte-array (16 bytes)
13
     * @param w     key schedule as 2D byte-array (Nr+1 x Nb bytes) -
14
     *              generated from the cipher key by keyExpansion()
15
     * @return      ciphertext as byte-array (16 bytes)
16
     */
17
    public static function cipher($input, $w) {    // main cipher function [é5.1]
18
    $Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
19
    $Nr = count($w) / $Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
20
21
    $state = array(); // initialise 4xNb byte-array 'state' with input [é3.4]
22
    for ($i = 0; $i < 4 * $Nb; $i++) {
23
        $state[$i % 4][floor($i / 4)] = $input[$i];
24
    }
25
26
    $state = self::addRoundKey($state, $w, 0, $Nb);
27
28
    for ($round = 1; $round < $Nr; $round++) {  // apply Nr rounds
29
        $state = self::subBytes($state, $Nb);
30
        $state = self::shiftRows($state, $Nb);
31
        $state = self::mixColumns($state);
32
        $state = self::addRoundKey($state, $w, $round, $Nb);
33
    }
34
35
    $state = self::subBytes($state, $Nb);
36
    $state = self::shiftRows($state, $Nb);
37
    $state = self::addRoundKey($state, $w, $Nr, $Nb);
38
39
    $output = array(4 * $Nb); // convert state to 1-d array before returning [é3.4]
40
    for ($i = 0; $i < 4 * $Nb; $i++) {
41
        $output[$i] = $state[$i % 4][floor($i / 4)];
42
    }
43
44
    return $output;
45
    }
46
47
    /**
48
     * @param integer $rnd
49
     * @param integer $Nb
50
     */
51
    private static function addRoundKey($state, $w, $rnd, $Nb) {  // xor Round Key into state S [é5.1.4]
52
    for ($r = 0; $r < 4; $r++) {
53
        for ($c = 0; $c < $Nb; $c++) {
54
            $state[$r][$c] ^= $w[$rnd * 4 + $c][$r];
55
        }
56
    }
57
58
    return $state;
59
    }
60
61
    /**
62
     * @param integer $Nb
63
     */
64
    private static function subBytes($s, $Nb) {    // apply SBox to state S [é5.1.1]
65
    for ($r = 0; $r < 4; $r++) {
66
        for ($c = 0; $c < $Nb; $c++) {
67
            $s[$r][$c] = self::$sBox[$s[$r][$c]];
68
        }
69
    }
70
71
    return $s;
72
    }
73
74
    /**
75
     * @param integer $Nb
76
     */
77
    private static function shiftRows($s, $Nb) {    // shift row r of state S left by r bytes [é5.1.2]
78
    $t = array(4);
79
    for ($r = 1; $r < 4; $r++) {
80
        for ($c = 0; $c < 4; $c++) {
81
            $t[$c] = $s[$r][($c + $r) % $Nb];
82
        }
83
        // shift into temp copy
84
        for ($c = 0; $c < 4; $c++) {
85
            $s[$r][$c] = $t[$c];
86
        }
87
        // and copy back
88
    }          // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
89
    return $s; // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
90
    }
91
92
    /**
93
     * @param integer $Nb
94
     */
95
    private static function mixColumns($s) {   // combine bytes of each col of state S [é5.1.3]
96
    for ($c = 0; $c < 4; $c++) {
97
        $a = array(4); // 'a' is a copy of the current column from 's'
98
        $b = array(4); // 'b' is aé{02} in GF(2^8)
99
        for ($i = 0; $i < 4; $i++) {
100
        $a[$i] = $s[$i][$c];
101
        $b[$i] = $s[$i][$c] & 0x80 ? $s[$i][$c] << 1 ^ 0x011b : $s[$i][$c] << 1;
102
        }
103
        // a[n] ^ b[n] is aé{03} in GF(2^8)
104
        $s[0][$c] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; // 2*a0 + 3*a1 + a2 + a3
105
        $s[1][$c] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; // a0 * 2*a1 + 3*a2 + a3
106
        $s[2][$c] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; // a0 + a1 + 2*a2 + 3*a3
107
        $s[3][$c] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; // 3*a0 + a1 + a2 + 2*a3
108
    }
109
110
    return $s;
111
    }
112
113
    /**
114
     * Key expansion for Rijndael cipher(): performs key expansion on cipher key
115
     * to generate a key schedule
116
     *
117
     * @param key cipher key byte-array (16 bytes)
118
     * @return    key schedule as 2D byte-array (Nr+1 x Nb bytes)
119
     */
120
    public static function keyExpansion($key) {  // generate Key Schedule from Cipher Key [é5.2]
121
    $Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
122
    $Nk = count($key) / 4; // key length (in words): 4/6/8 for 128/192/256-bit keys
123
    $Nr = $Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys
124
125
    $w = array();
126
    $temp = array();
127
128
    for ($i = 0; $i < $Nk; $i++) {
129
        $r = array($key[4 * $i], $key[4 * $i + 1], $key[4 * $i + 2], $key[4 * $i + 3]);
130
        $w[$i] = $r;
131
    }
132
133
    for ($i = $Nk; $i < ($Nb * ($Nr + 1)); $i++) {
134
        $w[$i] = array();
135
        for ($t = 0; $t < 4; $t++) {
136
            $temp[$t] = $w[$i - 1][$t];
137
        }
138
        if ($i % $Nk == 0) {
139
        $temp = self::subWord(self::rotWord($temp));
140
        for ($t = 0; $t < 4; $t++) {
141
            $temp[$t] ^= self::$rCon[$i / $Nk][$t];
142
        }
143
        } elseif ($Nk > 6 && $i % $Nk == 4) {
144
        $temp = self::subWord($temp);
145
        }
146
        for ($t = 0; $t < 4; $t++) {
147
            $w[$i][$t] = $w[$i - $Nk][$t] ^ $temp[$t];
148
        }
149
    }
150
151
    return $w;
152
    }
153
154
    private static function subWord($w) {    // apply SBox to 4-byte word w
155
    for ($i = 0; $i < 4; $i++) {
156
        $w[$i] = self::$sBox[$w[$i]];
157
    }
158
159
    return $w;
160
    }
161
162
    private static function rotWord($w) {    // rotate 4-byte word w left by one byte
163
    $tmp = $w[0];
164
    for ($i = 0; $i < 3; $i++) {
165
        $w[$i] = $w[$i + 1];
166
    }
167
    $w[3] = $tmp;
168
169
    return $w;
170
    }
171
172
    // sBox is pre-computed multiplicative inverse in GF(2^8) used in subBytes and keyExpansion [é5.1.1]
173
    private static $sBox = array(
174
    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
175
    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
176
    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
177
    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
178
    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
179
    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
180
    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
181
    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
182
    0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
183
    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
184
    0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
185
    0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
186
    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
187
    0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
188
    0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
189
    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
190
191
    // rCon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [é5.2]
192
    private static $rCon = array(
193
    array(0x00, 0x00, 0x00, 0x00),
194
    array(0x01, 0x00, 0x00, 0x00),
195
    array(0x02, 0x00, 0x00, 0x00),
196
    array(0x04, 0x00, 0x00, 0x00),
197
    array(0x08, 0x00, 0x00, 0x00),
198
    array(0x10, 0x00, 0x00, 0x00),
199
    array(0x20, 0x00, 0x00, 0x00),
200
    array(0x40, 0x00, 0x00, 0x00),
201
    array(0x80, 0x00, 0x00, 0x00),
202
    array(0x1b, 0x00, 0x00, 0x00),
203
    array(0x36, 0x00, 0x00, 0x00));
204
205
}
206
207
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
208

install/libs/aesctr.php 1 location

@@ 10-224 (lines=215) @@
7
/*    form is offered.                                                                            */
8
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
9
10
class Aes
11
{
12
    /**
13
     * AES Cipher function: encrypt 'input' with Rijndael algorithm
14
     *
15
     * @param input message as byte-array (16 bytes)
16
     * @param w     key schedule as 2D byte-array (Nr+1 x Nb bytes) -
17
     *              generated from the cipher key by keyExpansion()
18
     * @return ciphertext as byte-array (16 bytes)
19
     */
20
    public static function cipher($input, $w)
21
    {
22
        // main cipher function [é5.1]
23
        $Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
24
        $Nr = count($w) / $Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
25
26
        $state = array(); // initialise 4xNb byte-array 'state' with input [é3.4]
27
        for ($i = 0; $i < 4 * $Nb; $i++) {
28
            $state[$i % 4][floor($i / 4)] = $input[$i];
29
        }
30
31
        $state = self::addRoundKey($state, $w, 0, $Nb);
32
33
        for ($round = 1; $round < $Nr; $round++) {  // apply Nr rounds
34
            $state = self::subBytes($state, $Nb);
35
            $state = self::shiftRows($state, $Nb);
36
            $state = self::mixColumns($state, $Nb);
37
            $state = self::addRoundKey($state, $w, $round, $Nb);
38
        }
39
40
        $state = self::subBytes($state, $Nb);
41
        $state = self::shiftRows($state, $Nb);
42
        $state = self::addRoundKey($state, $w, $Nr, $Nb);
43
44
        $output = array(4 * $Nb); // convert state to 1-d array before returning [é3.4]
45
        for ($i = 0; $i < 4 * $Nb; $i++) {
46
            $output[$i] = $state[$i % 4][floor($i / 4)];
47
        }
48
49
        return $output;
50
    }
51
52
    /**
53
     * @param integer $rnd
54
     * @param integer $Nb
55
     */
56
    private static function addRoundKey($state, $w, $rnd, $Nb)
57
    {
58
        // xor Round Key into state S [é5.1.4]
59
        for ($r = 0; $r < 4; $r++) {
60
            for ($c = 0; $c < $Nb; $c++) {
61
                $state[$r][$c] ^= $w[$rnd * 4 + $c][$r];
62
            }
63
        }
64
65
        return $state;
66
    }
67
68
    /**
69
     * @param integer $Nb
70
     */
71
    private static function subBytes($s, $Nb)
72
    {
73
        // apply SBox to state S [é5.1.1]
74
        for ($r = 0; $r < 4; $r++) {
75
            for ($c = 0; $c < $Nb; $c++) {
76
                $s[$r][$c] = self::$sBox[$s[$r][$c]];
77
            }
78
        }
79
80
        return $s;
81
    }
82
83
    /**
84
     * @param integer $Nb
85
     */
86
    private static function shiftRows($s, $Nb)
87
    {
88
        // shift row r of state S left by r bytes [é5.1.2]
89
        $t = array(4);
90
        for ($r = 1; $r < 4; $r++) {
91
            for ($c = 0; $c < 4; $c++) {
92
                $t[$c] = $s[$r][($c + $r) % $Nb]; // shift into temp copy
93
            }
94
            for ($c = 0; $c < 4; $c++) {
95
                $s[$r][$c] = $t[$c]; // and copy back
96
            }
97
        }          // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
98
        return $s; // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
99
    }
100
101
    /**
102
     * @param integer $Nb
103
     */
104
    private static function mixColumns($s, $Nb)
105
    {
106
        // combine bytes of each col of state S [é5.1.3]
107
        for ($c = 0; $c < 4; $c++) {
108
            $a = array(4); // 'a' is a copy of the current column from 's'
109
            $b = array(4); // 'b' is aé{02} in GF(2^8)
110
            for ($i = 0; $i < 4; $i++) {
111
                $a[$i] = $s[$i][$c];
112
                $b[$i] = $s[$i][$c] & 0x80 ? $s[$i][$c] << 1 ^ 0x011b : $s[$i][$c] << 1;
113
            }
114
            // a[n] ^ b[n] is aé{03} in GF(2^8)
115
            $s[0][$c] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; // 2*a0 + 3*a1 + a2 + a3
116
            $s[1][$c] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; // a0 * 2*a1 + 3*a2 + a3
117
            $s[2][$c] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; // a0 + a1 + 2*a2 + 3*a3
118
            $s[3][$c] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; // 3*a0 + a1 + a2 + 2*a3
119
        }
120
121
        return $s;
122
    }
123
124
    /**
125
     * Key expansion for Rijndael cipher(): performs key expansion on cipher key
126
     * to generate a key schedule
127
     *
128
     * @param key cipher key byte-array (16 bytes)
129
     * @return key schedule as 2D byte-array (Nr+1 x Nb bytes)
130
     */
131
    public static function keyExpansion($key)
132
    {
133
        // generate Key Schedule from Cipher Key [é5.2]
134
        $Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
135
        $Nk = count($key) / 4; // key length (in words): 4/6/8 for 128/192/256-bit keys
136
        $Nr = $Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys
137
138
        $w = array();
139
        $temp = array();
140
141
        for ($i = 0; $i < $Nk; $i++) {
142
            $r = array($key[4 * $i], $key[4 * $i + 1], $key[4 * $i + 2], $key[4 * $i + 3]);
143
            $w[$i] = $r;
144
        }
145
146
        for ($i = $Nk; $i < ($Nb * ($Nr + 1)); $i++) {
147
            $w[$i] = array();
148
            for ($t = 0; $t < 4; $t++) {
149
                $temp[$t] = $w[$i - 1][$t];
150
            }
151
            if ($i % $Nk == 0) {
152
                $temp = self::subWord(self::rotWord($temp));
153
                for ($t = 0; $t < 4; $t++) {
154
                    $temp[$t] ^= self::$rCon[$i / $Nk][$t];
155
                }
156
            } elseif ($Nk > 6 && $i % $Nk == 4) {
157
                $temp = self::subWord($temp);
158
            }
159
            for ($t = 0; $t < 4; $t++) {
160
                $w[$i][$t] = $w[$i - $Nk][$t] ^ $temp[$t];
161
            }
162
        }
163
164
        return $w;
165
    }
166
167
    private static function subWord($w)
168
    {
169
        // apply SBox to 4-byte word w
170
        for ($i = 0; $i < 4; $i++) {
171
            $w[$i] = self::$sBox[$w[$i]];
172
        }
173
174
        return $w;
175
    }
176
177
    private static function rotWord($w)
178
    {
179
        // rotate 4-byte word w left by one byte
180
        $tmp = $w[0];
181
        for ($i = 0; $i < 3; $i++) {
182
            $w[$i] = $w[$i + 1];
183
        }
184
        $w[3] = $tmp;
185
186
        return $w;
187
    }
188
189
    // sBox is pre-computed multiplicative inverse in GF(2^8) used in subBytes and keyExpansion [é5.1.1]
190
    private static $sBox = array(
191
            0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
192
            0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
193
            0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
194
            0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
195
            0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
196
            0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
197
            0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
198
            0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
199
            0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
200
            0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
201
            0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
202
            0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
203
            0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
204
            0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
205
            0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
206
            0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
207
    );
208
209
    // rCon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [é5.2]
210
    private static $rCon = array(
211
            array(0x00, 0x00, 0x00, 0x00),
212
            array(0x01, 0x00, 0x00, 0x00),
213
            array(0x02, 0x00, 0x00, 0x00),
214
            array(0x04, 0x00, 0x00, 0x00),
215
            array(0x08, 0x00, 0x00, 0x00),
216
            array(0x10, 0x00, 0x00, 0x00),
217
            array(0x20, 0x00, 0x00, 0x00),
218
            array(0x40, 0x00, 0x00, 0x00),
219
            array(0x80, 0x00, 0x00, 0x00),
220
            array(0x1b, 0x00, 0x00, 0x00),
221
            array(0x36, 0x00, 0x00, 0x00)
222
    );
223
224
}
225
226
class aesctr extends Aes
227
{