Completed
Push — development ( c4d33f...5f74fd )
by Nils
09:26
created

Aes   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 199
Duplicated Lines 100 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
dl 199
loc 199
rs 9.8
c 0
b 0
f 0
wmc 31
lcom 1
cbo 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
B cipher() 29 29 4
A addRoundKey() 9 9 3
A subBytes() 9 9 3
A shiftRows() 14 14 4
D keyExpansion() 33 33 9
A subWord() 7 7 2
A mixColumns() 17 17 4
A rotWord() 9 9 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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 View Code Duplication
class Aes
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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):
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
89
    return $s; // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
90
    }
91
92
    /**
93
     * @param integer $Nb
0 ignored issues
show
Bug introduced by
There is no parameter named $Nb. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
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)
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
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)
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
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