Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?PHP
2
/*The contents of this document are free for use by anyone for any purpose they choose.
3
no warranty is implied, nor will one be honored.  The author assumes no liability for
4
any consequences that may arise from the use of contents of this document.  Events not
5
covered include but are not limited to: system crashes, system slowdown, system failure,
6
fires, explosions, floods, earthquakes, boiling seas, intestinal inflammation, cold coffee,
7
and total protonic inversion.
8
Any questions, comments, or improvements are appreciated and can be directed to:
9
 
10
Tim Thorpe
11
blushift@netins.net
12
*/
13
 
14
/*
15
This script implements the 56-bit DES encryption algorithm,
16
created from scratch based on interpretation of the original
17
specification document.
18
 
19
des_encrypt_ecb("my key", "my text");
20
and
21
mcrypt_ecb (MCRYPT_DES, "my key", "my text", MCRYPT_ENCRYPT, str_pad("", 8, chr(0x00)));
22
are functionally identical.
23
 
24
Because PHP is lacking in bitwise operators, this set of routines
25
makes use of data that has been expanded so that a byte becomes an 8-byte string.
26
 
27
The script performs the transformations, and then condenses the data back to a usable form.
28
Apologies for a lack of comments in the bulk of the functions.
29
*/////////////////////////////////////////////////////////////////////////////
30
 
31
function des_encrypt_ecb($key, $clearText) {
32
//Function to implement Electronic Code Book encoding
33
//I haven't had occasion to add any other methods or a decoder for that matter,
34
//but all of the underlying functions were written to be universal to all encoding methods,
35
//so adding other methods should be easy if you need them.
36
 
37
    if (strlen($key) < 7)
38
        $key = str_pad(substr($key, 0, 7), 7, chr(0x00));  //We need 7 bytes for a key; no more, no less
39
 
40
    if (strlen($key) == 7) $key = des_add_parity($key);
41
 
42
	$keys = des_make_subkeys (des_bits_to_bytes ($key));  //Chew the key into the subkeys needed for DES
43
	$blockCount = (int) (strlen($clearText) / 8);  //Figure out how many blocks of 8 bytes we need to encode
44
	if (strlen ($clearText) % 8) {  //Check to see if there are any leftovers
45
		$blockCount++;  //Add another block for them
46
		$clearText = str_pad($clearText, $blockCount * 8, chr(0x00));  //Pad it out with zeroes
47
	}
48
	for ($i = 0; $i < $blockCount; $i++) {  //Cycle through the blocks
49
		$clearBlock = substr($clearText, $i * 8, 8);  //Grab a block from the input
50
		$cypherBlock = des_block_encode(des_bits_to_bytes ($clearBlock), $keys);  //Encrypt it
51
		$cypherText .= des_bytes_to_bits ($cypherBlock);  //Convert the result back to a useful form
52
	}
53
	return ($cypherText);  //Cough it up
54
}
55
 
56
function des_block_encode($clearText, $subKeys) {
57
	$ip_table = array(58, 50, 42, 34, 26, 18, 10,  2,
58
			  60, 52, 44, 36, 28, 20, 12,  4,
59
			  62, 54, 46, 38, 30, 22, 14,  6,
60
			  64, 56, 48, 40, 32, 24, 16,  8,
61
			  57, 49, 41, 33, 25, 17,  9,  1,
62
			  59, 51, 43, 35, 27, 19, 11,  3,
63
			  61, 53, 45, 37, 29, 21, 13,  5,
64
			  63, 55, 47, 39, 31, 23, 15,  7);
65
 
66
	$ip1_table = array(40,  8, 48, 16, 56, 24, 64, 32,
67
			   39,  7, 47, 15, 55, 23, 63, 31,
68
			   38,  6, 46, 14, 54, 22, 62, 30,
69
			   37,  5, 45, 13, 53, 21, 61, 29,
70
			   36,  4, 44, 12, 52, 20, 60, 28,
71
			   35,  3, 43, 11, 51, 19, 59, 27,
72
			   34,  2, 42, 10, 50, 18, 58, 26,
73
			   33,  1, 41,  9, 49, 17, 57, 25);
74
 
75
	foreach ($ip_table as $bit) {
76
		$ip .= $clearText[$bit - 1];
77
	}
78
	$l[0] = substr($ip, 0, 32);
79
	$r[0] = substr($ip, 32);
80
	for ($index = 1; $index <= 16; $index++) {
81
		$l[$index] = $r[$index - 1];
82
		$r[$index] = des_xor($l[$index - 1], des_transform($r[$index - 1], $subKeys[$index]));
83
	}
84
 
85
	foreach ($ip1_table as $bit) {
86
		$concat	= $r[16] . $l[16];
87
		$cypherBlock .= $concat[$bit - 1];
88
	}
89
	return ($cypherBlock);
90
}
91
 
92
function des_make_subkeys($key) {
93
	$pc1 = array(57, 49, 41, 33, 25, 17,  9,
94
		      1, 58, 50, 42, 34, 26, 18,
95
		     10,  2, 59, 51, 43, 35, 27,
96
		     19, 11,  3, 60, 52, 44, 36,
97
		     63, 55, 47, 39, 31, 23, 15,
98
		      7, 62, 54, 46, 38, 30, 22,
99
		     14,  6, 61, 53, 45, 37, 29,
100
		     21, 13,  5, 28, 20, 12,  4);
101
 
102
	$pc2 = array(14, 17, 11, 24,  1,  5,
103
		      3, 28, 15,  6, 21, 10,
104
		     23, 19, 12,  4, 26,  8,
105
		     16,  7, 27, 20, 13,  2,
106
		     41, 52, 31, 37, 47, 55,
107
		     30, 40, 51, 45, 33, 48,
108
		     44, 49, 39, 56, 34, 53,
109
		     46, 42, 50, 36, 29, 32);
110
 
111
	$shifts = array(1, 1, 2, 2,
112
			2, 2, 2, 2,
113
			1, 2, 2, 2,
114
			2, 2, 2, 1);
115
	foreach ($pc1 as $bit) {
116
		$k .= $key[$bit - 1];
117
	}
118
	$index = 0;
119
	$c[$index] = substr($k, 0, 28);
120
	$d[$index] = substr($k, 28);
121
	unset ($k);
122
	foreach ($shifts as $positions) {
123
		$index++;
124
		$c[$index] = des_rotate_left ($c[$index - 1], $positions);
125
		$d[$index] = des_rotate_left ($d[$index - 1], $positions);
126
	}
127
	for ($i = 1; $i <= 16; $i++) {
128
		foreach ($pc2 as $bit) {
129
			$concat = $c[$i] . $d[$i];
130
			$k[$i] .= $concat[$bit - 1];
131
		}
132
	}
133
	return ($k);
134
}
135
 
136
function des_transform($data, $key) {
137
	$e_table = array(32,  1,  2,  3,  4,  5,
138
			  4,  5,  6,  7,  8,  9,
139
			  8,  9, 10, 11, 12, 13,
140
			 12, 13, 14, 15, 16, 17,
141
			 16, 17, 18, 19, 20, 21,
142
			 20, 21, 22, 23, 24, 25,
143
			 24, 25, 26, 27, 28, 29,
144
			 28, 29, 30, 31, 32,  1);
145
 
146
	$s = array(array(14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
147
			  0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
148
			  4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
149
			 15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13),
150
		   array(15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
151
			  3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
152
			  0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
153
			 13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9),
154
		   array(10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
155
			 13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
156
			 13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
157
			  1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12),
158
		   array( 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
159
			 13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
160
			 10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
161
			  3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14),
162
		   array( 2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
163
			 14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
164
			  4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
165
			 11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3),
166
		   array(12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
167
			 10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
168
			  9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
169
			  4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13),
170
		   array( 4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
171
			 13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
172
			  1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
173
			  6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12),
174
		   array(13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0,  12,  7,
175
			  1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
176
			  7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13,  15, 3,  5,  8,
177
			  2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11));
178
 
179
	$p_table = array(16,  7, 20, 21,
180
                         29, 12, 28, 17,
181
                          1, 15, 23, 26,
182
                          5, 18, 31, 10,
183
                          2,  8, 24, 14,
184
                         32, 27,  3,  9,
185
                         19, 13, 30,  6,
186
                         22, 11,  4, 25);
187
 
188
	$nybbles = array(chr(0x00).chr(0x00).chr(0x00).chr(0x00), chr(0x00).chr(0x00).chr(0x00).chr(0x01),
189
			 chr(0x00).chr(0x00).chr(0x01).chr(0x00), chr(0x00).chr(0x00).chr(0x01).chr(0x01),
190
			 chr(0x00).chr(0x01).chr(0x00).chr(0x00), chr(0x00).chr(0x01).chr(0x00).chr(0x01),
191
			 chr(0x00).chr(0x01).chr(0x01).chr(0x00), chr(0x00).chr(0x01).chr(0x01).chr(0x01),
192
			 chr(0x01).chr(0x00).chr(0x00).chr(0x00), chr(0x01).chr(0x00).chr(0x00).chr(0x01),
193
			 chr(0x01).chr(0x00).chr(0x01).chr(0x00), chr(0x01).chr(0x00).chr(0x01).chr(0x01),
194
			 chr(0x01).chr(0x01).chr(0x00).chr(0x00), chr(0x01).chr(0x01).chr(0x00).chr(0x01),
195
			 chr(0x01).chr(0x01).chr(0x01).chr(0x00), chr(0x01).chr(0x01).chr(0x01).chr(0x01));
196
 
197
 
198
	foreach ($e_table as $bit) {
199
		$e .= $data[$bit - 1];
200
	}
201
	$ek = des_xor($e, $key);
202
	for ($i = 0; $i < 8; $i++) {
203
		$offset = $i * 6;
204
		$sAddress = ord($ek[$offset]) * 0x20 +
205
			    ord($ek[$offset + 1]) * 0x08 +
206
			    ord($ek[$offset + 2]) * 0x04 +
207
			    ord($ek[$offset + 3]) * 0x02 +
208
			    ord($ek[$offset + 4]) +
209
			    ord($ek[$offset + 5]) * 0x10;
210
		$sResult .= $nybbles[$s[$i][$sAddress]];
211
	}
212
	foreach ($p_table as $bit) {
213
		$p .= $sResult[$bit - 1];
214
	}
215
	return ($p);
216
}
217
 
218
function des_bits_to_bytes($bitStream) {
219
	for ($i = 0; $i < strlen($bitStream); $i++) {
220
		$val = ord($bitStream[$i]);
221
		if ($val & 0x80) {$byteStream .= chr(0x01);} else {$byteStream .= chr(0x00);}
222
		if ($val & 0x40) {$byteStream .= chr(0x01);} else {$byteStream .= chr(0x00);}
223
		if ($val & 0x20) {$byteStream .= chr(0x01);} else {$byteStream .= chr(0x00);}
224
		if ($val & 0x10) {$byteStream .= chr(0x01);} else {$byteStream .= chr(0x00);}
225
		if ($val & 0x08) {$byteStream .= chr(0x01);} else {$byteStream .= chr(0x00);}
226
		if ($val & 0x04) {$byteStream .= chr(0x01);} else {$byteStream .= chr(0x00);}
227
		if ($val & 0x02) {$byteStream .= chr(0x01);} else {$byteStream .= chr(0x00);}
228
		if ($val & 0x01) {$byteStream .= chr(0x01);} else {$byteStream .= chr(0x00);}
229
	}
230
	return ($byteStream);
231
}
232
 
233
function des_bytes_to_bits($byteStream) {
234
	for ($i = 0; $i < (strlen($byteStream) / 8); $i++) {
235
		$offset	= $i * 8;
236
		$value = ord($byteStream[$offset]) * 0x80 +
237
			 ord($byteStream[$offset + 1]) * 0x40 +
238
			 ord($byteStream[$offset + 2]) * 0x20 +
239
			 ord($byteStream[$offset + 3]) * 0x10 +
240
			 ord($byteStream[$offset + 4]) * 0x08 +
241
			 ord($byteStream[$offset + 5]) * 0x04 +
242
			 ord($byteStream[$offset + 6]) * 0x02 +
243
			 ord($byteStream[$offset + 7]);
244
		$bitStream .= chr($value);
245
 
246
	}
247
	return ($bitStream);
248
}
249
 
250
function des_rotate_left($input, $positions) {
251
	return substr($input, $positions) . substr($input, 0, $positions);
252
}
253
 
254
function des_xor($a, $b) {
255
	for ($i = 0; $i < strlen($a); $i++) {
256
		$xor .= $a[$i] ^ $b[$i];
257
	}
258
	return $xor;
259
}
260
 
261
// DES helper function
262
// input: 7-Bytes Key without parity
263
// ouput: 8-Bytes Key with parity
264
function des_add_parity($key)
265
{
266
    static $odd_parity = array(
267
        1,  1,  2,  2,  4,  4,  7,  7,  8,  8, 11, 11, 13, 13, 14, 14,
268
        16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
269
        32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
270
        49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
271
        64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
272
        81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
273
        97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
274
        112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
275
        128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
276
        145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
277
        161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
278
        176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
279
        193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
280
        208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
281
        224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
282
        241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254);
283
 
284
    for ($i = 0; $i < strlen($key); $i++) {
285
        $bin .= sprintf('%08s', decbin(ord($key{$i})));
286
    }
287
 
288
    $str1 = explode('-', substr(chunk_split($bin, 7, '-'), 0, -1));
289
    foreach($str1 as $s) {
290
        $x .= sprintf('%02s', dechex($odd_parity[bindec($s . '0')]));
291
    }
292
 
293
    return pack('H*', $x);
294
 
295
}