Completed
Push — development ( fd35b5...2c05ec )
by Nils
07:23
created

Cipher_Skipjack::encrypt()   D

Complexity

Conditions 10
Paths 17

Size

Total Lines 28
Code Lines 14

Duplication

Lines 24
Ratio 85.71 %

Importance

Changes 0
Metric Value
cc 10
eloc 14
nc 17
nop 1
dl 24
loc 28
rs 4.8196
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * Author: Ryan Gilfether
4
 * URL: http://www.gilfether.com/phpCrypt
5
 * Date: April 23, 2013
6
 * Copyright (C) 2013 Ryan Gilfether
7
 *
8
 * This file is part of phpCrypt
9
 *
10
 * phpCrypt is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 3 of the License, or
13
 * (at your option) any later version
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
namespace PHP_CRYPT;
25
require_once(dirname(__FILE__)."/../Cipher.php");
26
require_once(dirname(__FILE__)."/../phpCrypt.php");
27
28
29
/**
30
 * Implements Skipjack Encryption
31
 * Resources used to implement this algorithm:
32
 * csrc.nist.gov/groups/ST/toolkit/documents/skipjack/skipjack.pdf
33
 * http://calccrypto.wikidot.com/algorithms:skipjack
34
 * http://www.quadibloc.com/crypto/co040303.htm
35
 *
36
 * @author Ryan Gilfether
37
 * @link http://www.gilfether.com/phpcrypt
38
 * @copyright 2013 Ryan Gilfether
39
 */
40
class Cipher_Skipjack extends Cipher
41
{
42
    /** @type integer BYTES_BLOCK The size of the block, in bytes */
43
    const BYTES_BLOCK = 8; // 64 bits
44
45
    /** @type integer BYTES_KEY The size of the key, in bytes */
46
    const BYTES_KEY = 10; // 80 bits
47
48
    /** @type string $expanded_key The expanded key */
49
    private $expanded_key = "";
50
51
    /** @type array $_f The Skipjack F-Table, this is a constant */
52
    private static $_f = array();
53
54
55
    /**
56
     * Constructor
57
     *
58
     * @param string $key The key used for Encryption/Decryption
59
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
60
     */
61
    public function __construct($key)
62
    {
63
        // set the Skipjack key
64
        parent::__construct(PHP_Crypt::CIPHER_SKIPJACK, $key, self::BYTES_KEY);
65
66
        // initialize variables
67
        $this->initTables();
68
69
        // set the block size used
70
        $this->blockSize(self::BYTES_BLOCK);
71
72
        // expand the key from 10 bytes to 128 bytes
73
        $this->expandKey();
74
    }
75
76
77
    /**
78
     * Destructor
79
     *
80
     * @return void
81
     */
82
    public function __destruct()
83
    {
84
        parent::__destruct();
85
    }
86
87
88
    /**
89
     * Encrypt plain text data using Skipjack
90
     *
91
     * @return boolean Returns true
92
     */
93 View Code Duplication
    public function encrypt(&$text)
0 ignored issues
show
Duplication introduced by
This method 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...
94
    {
95
        $this->operation(parent::ENCRYPT);
96
97
        for ($i = 1; $i <= 32; ++$i)
98
        {
99
            $pos = (4 * $i) - 4;
100
            $subkey = substr($this->expanded_key, $pos, 4);
101
102
            if ($i >= 1 && $i <= 8) {
103
                            $this->ruleA($text, $subkey, $i);
104
            }
105
106
            if ($i >= 9 && $i <= 16) {
107
                            $this->ruleB($text, $subkey, $i);
108
            }
109
110
            if ($i >= 17 && $i <= 24) {
111
                            $this->ruleA($text, $subkey, $i);
112
            }
113
114
            if ($i >= 25 && $i <= 32) {
115
                            $this->ruleB($text, $subkey, $i);
116
            }
117
        }
118
119
        return true;
120
    }
121
122
123
    /**
124
     * Decrypt a Skipjack encrypted string
125
     *
126
     * @return boolean Returns true
127
     */
128 View Code Duplication
    public function decrypt(&$text)
0 ignored issues
show
Duplication introduced by
This method 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...
129
    {
130
        $this->operation(parent::DECRYPT);
131
132
        for ($i = 32; $i >= 1; --$i)
133
        {
134
            $pos = ($i - 1) * 4;
135
            $subkey = substr($this->expanded_key, $pos, 4);
136
137
            if ($i <= 32 && $i >= 25) {
138
                            $this->ruleB($text, $subkey, $i);
139
            }
140
141
            if ($i <= 24 && $i >= 17) {
142
                            $this->ruleA($text, $subkey, $i);
143
            }
144
145
            if ($i <= 16 && $i >= 9) {
146
                            $this->ruleB($text, $subkey, $i);
147
            }
148
149
            if ($i <= 8 && $i >= 1) {
150
                            $this->ruleA($text, $subkey, $i);
151
            }
152
        }
153
154
        return true;
155
    }
156
157
158
    /**
159
     * For the G Permutations, the input data is 2 Bytes The first byte is
160
     * the left side and the second is the right side.The round key is 4 bytes
161
     * long (Indices 8*i-8 to 8*i), which is split as 4 pieces: K0, K1, K2, K3
162
     *
163
     * @param string $bytes A 2 byte string
164
     * @param string $key 4 bytes of $this->expanded_key
165
     * @return string A 2 byte string, the G Permutation of $bytes
166
     */
167
    private function gPermutation($bytes, $key)
168
    {
169
        $left = ord($bytes[0]);
170
        $right = ord($bytes[1]);
171
172
        if ($this->operation() == parent::ENCRYPT)
173
        {
174 View Code Duplication
            for ($i = 0; $i < 4; ++$i)
175
            {
176
                if ($i == 0 || $i == 2)
177
                {
178
                    $pos = $right ^ $this->str2Dec($key[$i]);
179
                    $left = $left ^ self::$_f[$pos];
180
                } else
181
                {
182
                    $pos = $left ^ $this->str2Dec($key[$i]);
183
                    $right = $right ^ self::$_f[$pos];
184
                }
185
            }
186
        } else // parent::DECRYPT
187
        {
188
            // we do the same as in encryption, but apply the key backwards,
189
            // from key[3] to key[0]
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% 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...
190 View Code Duplication
            for ($i = 3; $i >= 0; --$i)
191
            {
192
                if ($i == 0 || $i == 2)
193
                {
194
                    $pos = $right ^ $this->str2Dec($key[$i]);
195
                    $left = $left ^ self::$_f[$pos];
196
                } else
197
                {
198
                    $pos = $left ^ $this->str2Dec($key[$i]);
199
                    $right = $right ^ self::$_f[$pos];
200
                }
201
            }
202
        }
203
204
        return $this->dec2Str($left).$this->dec2Str($right);
205
    }
206
207
208
    /**
209
     * Perform SkipJacks RuleA function. Split the data into 4 parts,
210
     * 2 bytes each: W0, W1, W2, W3.
211
     *
212
     * @param string $bytes An 8 byte string
213
     * @param string $key 4 bytes of $this->expanded_key
214
     * @param integer $i The round number
215
     * @return void
216
     */
217 View Code Duplication
    private function ruleA(&$bytes, $key, $i)
0 ignored issues
show
Duplication introduced by
This method 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...
218
    {
219
        $w = str_split($bytes, 2);
220
221
        if ($this->operation() == parent::ENCRYPT)
222
        {
223
            /*
224
			 * Set the W3 as the old W2
225
			 * Set the W2 as the old W1
226
			 * Set the W1 as the G(W0)
227
			 * Set the W0 as the W1 xor W4 xor i
228
			 */
229
230
            $w[4] = $w[3];
231
            $w[3] = $w[2];
232
            $w[2] = $w[1];
233
            $w[1] = $this->gPermutation($w[0], $key);
234
235
            $hex1 = $this->str2Hex($w[1]);
236
            $hex4 = $this->str2Hex($w[4]);
237
            $hexi = $this->dec2Hex($i);
238
            $w[0] = $this->xorHex($hex1, $hex4, $hexi);
239
            $w[0] = $this->hex2Str($w[0]);
240
        } else // parent::DECRYPT
241
        {
242
            /*
243
			 * Set W4 as W0 xor W1 xor i
244
			 * Set W0 as Inverse G(W1)
245
			 * Set W1 as the old W2
246
			 * Set W2 as the old W3
247
			 * Set W3 as W4
248
			 */
249
250
            $hex0 = $this->str2Hex($w[0]);
251
            $hex1 = $this->str2Hex($w[1]);
252
            $hexi = $this->dec2Hex($i);
253
            $w[4] = $this->xorHex($hex0, $hex1, $hexi);
254
            $w[4] = $this->hex2Str($w[4]);
255
256
            $w[0] = $this->gPermutation($w[1], $key);
257
            $w[1] = $w[2];
258
            $w[2] = $w[3];
259
            $w[3] = $w[4];
260
        }
261
262
        // glue all the pieces back together
263
        $bytes = $w[0].$w[1].$w[2].$w[3];
264
    }
265
266
267
    /**
268
     * Perform SkipJacks RuleB function. Split the data into 4 parts,
269
     * 2 bytes each: W0, W1, W2, W3.
270
     *
271
     * @param string $bytes An 8 bytes string
272
     * @param string $key 4 bytes of $this->expanded_key
273
     * @param integer $i The round number
274
     * @return void
275
     */
276 View Code Duplication
    private function ruleB(&$bytes, $key, $i)
0 ignored issues
show
Duplication introduced by
This method 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...
277
    {
278
        $w = str_split($bytes, 2);
279
280
        if ($this->operation() == parent::ENCRYPT)
281
        {
282
            /*
283
			 * Set the new W3 as the old W2
284
			 * Set the new W2 as the old W0 xor old W1 xor i
285
			 * Set the new W1 as G(old W0)
286
			 * Set the new W0 as the old W3
287
			 */
288
289
            $w[4] = $w[3];
290
            $w[3] = $w[2];
291
292
            $hex0 = $this->str2Hex($w[0]);
293
            $hex1 = $this->str2Hex($w[1]);
294
            $hexi = $this->dec2Hex($i);
295
            $w[2] = $this->xorHex($hex0, $hex1, $hexi);
296
            $w[2] = $this->hex2Str($w[2]);
297
298
            $w[1] = $this->gPermutation($w[0], $key);
299
            $w[0] = $w[4];
300
        } else // parent::DECRYPT
301
        {
302
            /*
303
			 * Set W4 as the old W0
304
			 * Set new W0 as Inverse G(old W1)
305
			 * Set new W1 as Inverse G(old W1) xor old W2 xor i
306
			 * Set new W2 as the old W3
307
			 * Set new W0 as the old W4
308
			 */
309
310
            $w[4] = $w[0];
311
            $w[0] = $this->gPermutation($w[1], $key);
312
313
            $hex0 = $this->str2Hex($w[0]);
314
            $hex2 = $this->str2Hex($w[2]);
315
            $hexi = $this->dec2Hex($i);
316
            $w[1] = $this->xorHex($hex0, $hex2, $hexi);
317
            $w[1] = $this->hex2Str($w[1]);
318
319
            $w[2] = $w[3];
320
            $w[3] = $w[4];
321
        }
322
323
        $bytes = $w[0].$w[1].$w[2].$w[3];
324
    }
325
326
327
    /**
328
     * Expands the key from 10 bytes, to 128 bytes
329
     * This is done by copying the key 1 byte at a time and
330
     * appending it to $this->expanded_key, when we reach the
331
     * end of the key, we start over at position 0 and continue
332
     * until we reach 128 bytes
333
     *
334
     * @return void
335
     */
336
    private function expandKey()
337
    {
338
        $this->expanded_key = "";
339
        $key_bytes = $this->keySize();
340
        $key = $this->key();
341
        $pos = 0;
342
343 View Code Duplication
        for ($i = 0; $i < 128; ++$i)
344
        {
345
            if ($pos == $key_bytes) {
346
                            $pos = 0;
347
            }
348
349
            $this->expanded_key .= $key[$pos];
350
            ++$pos;
351
        }
352
    }
353
354
355
    /**
356
     * Initialize all the tables, this function is called inside the constructor
357
     *
358
     * @return void
359
     */
360
    private function initTables()
361
    {
362
        self::$_f = array(
363
            0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4, 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,
364
            0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e, 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,
365
            0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68, 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,
366
            0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19, 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,
367
            0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b, 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,
368
            0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0, 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,
369
            0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69, 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,
370
            0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20, 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,
371
            0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43, 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,
372
            0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa, 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,
373
            0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87, 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,
374
            0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b, 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,
375
            0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0, 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,
376
            0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1, 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,
377
            0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5, 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,
378
            0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3, 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46
379
        );
380
    }
381
382
383
    /**
384
     * Indicates that this is a block cipher
385
     *
386
     * @return integer Returns Cipher::BLOCK
387
     */
388
    public function type()
389
    {
390
        return parent::BLOCK;
391
    }
392
}
393
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
394