Passed
Branch wip_sessions (2e0cc8)
by Nils
04:59
created

Aes::shiftRows()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 7
nc 5
nop 2
dl 0
loc 13
rs 10
c 1
b 0
f 0
1
<?php
2
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
3
/*  AES implementation in PHP (c) Chris Veness 2005-2010. Right of free use is granted for all    */
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) -
0 ignored issues
show
Bug introduced by
The type key was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
     *              generated from the cipher key by keyExpansion()
15
     * @return      ciphertext as byte-array (16 bytes)
0 ignored issues
show
Bug introduced by
The type ciphertext was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $output returns the type array<integer,integer> which is incompatible with the documented return type ciphertext.
Loading history...
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)
0 ignored issues
show
Bug introduced by
The type cipher was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $w returns the type array which is incompatible with the documented return type key.
Loading history...
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