1 | /**
|
---|
2 | * DES (Data Encryption Standard) implementation.
|
---|
3 | *
|
---|
4 | * This implementation supports DES as well as 3DES-EDE in ECB and CBC mode.
|
---|
5 | * It is based on the BSD-licensed implementation by Paul Tero:
|
---|
6 | *
|
---|
7 | * Paul Tero, July 2001
|
---|
8 | * http://www.tero.co.uk/des/
|
---|
9 | *
|
---|
10 | * Optimised for performance with large blocks by
|
---|
11 | * Michael Hayworth, November 2001
|
---|
12 | * http://www.netdealing.com
|
---|
13 | *
|
---|
14 | * THIS SOFTWARE IS PROVIDED "AS IS" AND
|
---|
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
---|
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
---|
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
---|
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
---|
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
---|
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
---|
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
---|
22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
---|
23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
---|
24 | * SUCH DAMAGE.
|
---|
25 | *
|
---|
26 | * @author Stefan Siegl
|
---|
27 | * @author Dave Longley
|
---|
28 | *
|
---|
29 | * Copyright (c) 2012 Stefan Siegl <stesie@brokenpipe.de>
|
---|
30 | * Copyright (c) 2012-2014 Digital Bazaar, Inc.
|
---|
31 | */
|
---|
32 | var forge = require('./forge');
|
---|
33 | require('./cipher');
|
---|
34 | require('./cipherModes');
|
---|
35 | require('./util');
|
---|
36 |
|
---|
37 | /* DES API */
|
---|
38 | module.exports = forge.des = forge.des || {};
|
---|
39 |
|
---|
40 | /**
|
---|
41 | * Deprecated. Instead, use:
|
---|
42 | *
|
---|
43 | * var cipher = forge.cipher.createCipher('DES-<mode>', key);
|
---|
44 | * cipher.start({iv: iv});
|
---|
45 | *
|
---|
46 | * Creates an DES cipher object to encrypt data using the given symmetric key.
|
---|
47 | * The output will be stored in the 'output' member of the returned cipher.
|
---|
48 | *
|
---|
49 | * The key and iv may be given as binary-encoded strings of bytes or
|
---|
50 | * byte buffers.
|
---|
51 | *
|
---|
52 | * @param key the symmetric key to use (64 or 192 bits).
|
---|
53 | * @param iv the initialization vector to use.
|
---|
54 | * @param output the buffer to write to, null to create one.
|
---|
55 | * @param mode the cipher mode to use (default: 'CBC' if IV is
|
---|
56 | * given, 'ECB' if null).
|
---|
57 | *
|
---|
58 | * @return the cipher.
|
---|
59 | */
|
---|
60 | forge.des.startEncrypting = function(key, iv, output, mode) {
|
---|
61 | var cipher = _createCipher({
|
---|
62 | key: key,
|
---|
63 | output: output,
|
---|
64 | decrypt: false,
|
---|
65 | mode: mode || (iv === null ? 'ECB' : 'CBC')
|
---|
66 | });
|
---|
67 | cipher.start(iv);
|
---|
68 | return cipher;
|
---|
69 | };
|
---|
70 |
|
---|
71 | /**
|
---|
72 | * Deprecated. Instead, use:
|
---|
73 | *
|
---|
74 | * var cipher = forge.cipher.createCipher('DES-<mode>', key);
|
---|
75 | *
|
---|
76 | * Creates an DES cipher object to encrypt data using the given symmetric key.
|
---|
77 | *
|
---|
78 | * The key may be given as a binary-encoded string of bytes or a byte buffer.
|
---|
79 | *
|
---|
80 | * @param key the symmetric key to use (64 or 192 bits).
|
---|
81 | * @param mode the cipher mode to use (default: 'CBC').
|
---|
82 | *
|
---|
83 | * @return the cipher.
|
---|
84 | */
|
---|
85 | forge.des.createEncryptionCipher = function(key, mode) {
|
---|
86 | return _createCipher({
|
---|
87 | key: key,
|
---|
88 | output: null,
|
---|
89 | decrypt: false,
|
---|
90 | mode: mode
|
---|
91 | });
|
---|
92 | };
|
---|
93 |
|
---|
94 | /**
|
---|
95 | * Deprecated. Instead, use:
|
---|
96 | *
|
---|
97 | * var decipher = forge.cipher.createDecipher('DES-<mode>', key);
|
---|
98 | * decipher.start({iv: iv});
|
---|
99 | *
|
---|
100 | * Creates an DES cipher object to decrypt data using the given symmetric key.
|
---|
101 | * The output will be stored in the 'output' member of the returned cipher.
|
---|
102 | *
|
---|
103 | * The key and iv may be given as binary-encoded strings of bytes or
|
---|
104 | * byte buffers.
|
---|
105 | *
|
---|
106 | * @param key the symmetric key to use (64 or 192 bits).
|
---|
107 | * @param iv the initialization vector to use.
|
---|
108 | * @param output the buffer to write to, null to create one.
|
---|
109 | * @param mode the cipher mode to use (default: 'CBC' if IV is
|
---|
110 | * given, 'ECB' if null).
|
---|
111 | *
|
---|
112 | * @return the cipher.
|
---|
113 | */
|
---|
114 | forge.des.startDecrypting = function(key, iv, output, mode) {
|
---|
115 | var cipher = _createCipher({
|
---|
116 | key: key,
|
---|
117 | output: output,
|
---|
118 | decrypt: true,
|
---|
119 | mode: mode || (iv === null ? 'ECB' : 'CBC')
|
---|
120 | });
|
---|
121 | cipher.start(iv);
|
---|
122 | return cipher;
|
---|
123 | };
|
---|
124 |
|
---|
125 | /**
|
---|
126 | * Deprecated. Instead, use:
|
---|
127 | *
|
---|
128 | * var decipher = forge.cipher.createDecipher('DES-<mode>', key);
|
---|
129 | *
|
---|
130 | * Creates an DES cipher object to decrypt data using the given symmetric key.
|
---|
131 | *
|
---|
132 | * The key may be given as a binary-encoded string of bytes or a byte buffer.
|
---|
133 | *
|
---|
134 | * @param key the symmetric key to use (64 or 192 bits).
|
---|
135 | * @param mode the cipher mode to use (default: 'CBC').
|
---|
136 | *
|
---|
137 | * @return the cipher.
|
---|
138 | */
|
---|
139 | forge.des.createDecryptionCipher = function(key, mode) {
|
---|
140 | return _createCipher({
|
---|
141 | key: key,
|
---|
142 | output: null,
|
---|
143 | decrypt: true,
|
---|
144 | mode: mode
|
---|
145 | });
|
---|
146 | };
|
---|
147 |
|
---|
148 | /**
|
---|
149 | * Creates a new DES cipher algorithm object.
|
---|
150 | *
|
---|
151 | * @param name the name of the algorithm.
|
---|
152 | * @param mode the mode factory function.
|
---|
153 | *
|
---|
154 | * @return the DES algorithm object.
|
---|
155 | */
|
---|
156 | forge.des.Algorithm = function(name, mode) {
|
---|
157 | var self = this;
|
---|
158 | self.name = name;
|
---|
159 | self.mode = new mode({
|
---|
160 | blockSize: 8,
|
---|
161 | cipher: {
|
---|
162 | encrypt: function(inBlock, outBlock) {
|
---|
163 | return _updateBlock(self._keys, inBlock, outBlock, false);
|
---|
164 | },
|
---|
165 | decrypt: function(inBlock, outBlock) {
|
---|
166 | return _updateBlock(self._keys, inBlock, outBlock, true);
|
---|
167 | }
|
---|
168 | }
|
---|
169 | });
|
---|
170 | self._init = false;
|
---|
171 | };
|
---|
172 |
|
---|
173 | /**
|
---|
174 | * Initializes this DES algorithm by expanding its key.
|
---|
175 | *
|
---|
176 | * @param options the options to use.
|
---|
177 | * key the key to use with this algorithm.
|
---|
178 | * decrypt true if the algorithm should be initialized for decryption,
|
---|
179 | * false for encryption.
|
---|
180 | */
|
---|
181 | forge.des.Algorithm.prototype.initialize = function(options) {
|
---|
182 | if(this._init) {
|
---|
183 | return;
|
---|
184 | }
|
---|
185 |
|
---|
186 | var key = forge.util.createBuffer(options.key);
|
---|
187 | if(this.name.indexOf('3DES') === 0) {
|
---|
188 | if(key.length() !== 24) {
|
---|
189 | throw new Error('Invalid Triple-DES key size: ' + key.length() * 8);
|
---|
190 | }
|
---|
191 | }
|
---|
192 |
|
---|
193 | // do key expansion to 16 or 48 subkeys (single or triple DES)
|
---|
194 | this._keys = _createKeys(key);
|
---|
195 | this._init = true;
|
---|
196 | };
|
---|
197 |
|
---|
198 | /** Register DES algorithms **/
|
---|
199 |
|
---|
200 | registerAlgorithm('DES-ECB', forge.cipher.modes.ecb);
|
---|
201 | registerAlgorithm('DES-CBC', forge.cipher.modes.cbc);
|
---|
202 | registerAlgorithm('DES-CFB', forge.cipher.modes.cfb);
|
---|
203 | registerAlgorithm('DES-OFB', forge.cipher.modes.ofb);
|
---|
204 | registerAlgorithm('DES-CTR', forge.cipher.modes.ctr);
|
---|
205 |
|
---|
206 | registerAlgorithm('3DES-ECB', forge.cipher.modes.ecb);
|
---|
207 | registerAlgorithm('3DES-CBC', forge.cipher.modes.cbc);
|
---|
208 | registerAlgorithm('3DES-CFB', forge.cipher.modes.cfb);
|
---|
209 | registerAlgorithm('3DES-OFB', forge.cipher.modes.ofb);
|
---|
210 | registerAlgorithm('3DES-CTR', forge.cipher.modes.ctr);
|
---|
211 |
|
---|
212 | function registerAlgorithm(name, mode) {
|
---|
213 | var factory = function() {
|
---|
214 | return new forge.des.Algorithm(name, mode);
|
---|
215 | };
|
---|
216 | forge.cipher.registerAlgorithm(name, factory);
|
---|
217 | }
|
---|
218 |
|
---|
219 | /** DES implementation **/
|
---|
220 |
|
---|
221 | var spfunction1 = [0x1010400,0,0x10000,0x1010404,0x1010004,0x10404,0x4,0x10000,0x400,0x1010400,0x1010404,0x400,0x1000404,0x1010004,0x1000000,0x4,0x404,0x1000400,0x1000400,0x10400,0x10400,0x1010000,0x1010000,0x1000404,0x10004,0x1000004,0x1000004,0x10004,0,0x404,0x10404,0x1000000,0x10000,0x1010404,0x4,0x1010000,0x1010400,0x1000000,0x1000000,0x400,0x1010004,0x10000,0x10400,0x1000004,0x400,0x4,0x1000404,0x10404,0x1010404,0x10004,0x1010000,0x1000404,0x1000004,0x404,0x10404,0x1010400,0x404,0x1000400,0x1000400,0,0x10004,0x10400,0,0x1010004];
|
---|
222 | var spfunction2 = [-0x7fef7fe0,-0x7fff8000,0x8000,0x108020,0x100000,0x20,-0x7fefffe0,-0x7fff7fe0,-0x7fffffe0,-0x7fef7fe0,-0x7fef8000,-0x80000000,-0x7fff8000,0x100000,0x20,-0x7fefffe0,0x108000,0x100020,-0x7fff7fe0,0,-0x80000000,0x8000,0x108020,-0x7ff00000,0x100020,-0x7fffffe0,0,0x108000,0x8020,-0x7fef8000,-0x7ff00000,0x8020,0,0x108020,-0x7fefffe0,0x100000,-0x7fff7fe0,-0x7ff00000,-0x7fef8000,0x8000,-0x7ff00000,-0x7fff8000,0x20,-0x7fef7fe0,0x108020,0x20,0x8000,-0x80000000,0x8020,-0x7fef8000,0x100000,-0x7fffffe0,0x100020,-0x7fff7fe0,-0x7fffffe0,0x100020,0x108000,0,-0x7fff8000,0x8020,-0x80000000,-0x7fefffe0,-0x7fef7fe0,0x108000];
|
---|
223 | var spfunction3 = [0x208,0x8020200,0,0x8020008,0x8000200,0,0x20208,0x8000200,0x20008,0x8000008,0x8000008,0x20000,0x8020208,0x20008,0x8020000,0x208,0x8000000,0x8,0x8020200,0x200,0x20200,0x8020000,0x8020008,0x20208,0x8000208,0x20200,0x20000,0x8000208,0x8,0x8020208,0x200,0x8000000,0x8020200,0x8000000,0x20008,0x208,0x20000,0x8020200,0x8000200,0,0x200,0x20008,0x8020208,0x8000200,0x8000008,0x200,0,0x8020008,0x8000208,0x20000,0x8000000,0x8020208,0x8,0x20208,0x20200,0x8000008,0x8020000,0x8000208,0x208,0x8020000,0x20208,0x8,0x8020008,0x20200];
|
---|
224 | var spfunction4 = [0x802001,0x2081,0x2081,0x80,0x802080,0x800081,0x800001,0x2001,0,0x802000,0x802000,0x802081,0x81,0,0x800080,0x800001,0x1,0x2000,0x800000,0x802001,0x80,0x800000,0x2001,0x2080,0x800081,0x1,0x2080,0x800080,0x2000,0x802080,0x802081,0x81,0x800080,0x800001,0x802000,0x802081,0x81,0,0,0x802000,0x2080,0x800080,0x800081,0x1,0x802001,0x2081,0x2081,0x80,0x802081,0x81,0x1,0x2000,0x800001,0x2001,0x802080,0x800081,0x2001,0x2080,0x800000,0x802001,0x80,0x800000,0x2000,0x802080];
|
---|
225 | var spfunction5 = [0x100,0x2080100,0x2080000,0x42000100,0x80000,0x100,0x40000000,0x2080000,0x40080100,0x80000,0x2000100,0x40080100,0x42000100,0x42080000,0x80100,0x40000000,0x2000000,0x40080000,0x40080000,0,0x40000100,0x42080100,0x42080100,0x2000100,0x42080000,0x40000100,0,0x42000000,0x2080100,0x2000000,0x42000000,0x80100,0x80000,0x42000100,0x100,0x2000000,0x40000000,0x2080000,0x42000100,0x40080100,0x2000100,0x40000000,0x42080000,0x2080100,0x40080100,0x100,0x2000000,0x42080000,0x42080100,0x80100,0x42000000,0x42080100,0x2080000,0,0x40080000,0x42000000,0x80100,0x2000100,0x40000100,0x80000,0,0x40080000,0x2080100,0x40000100];
|
---|
226 | var spfunction6 = [0x20000010,0x20400000,0x4000,0x20404010,0x20400000,0x10,0x20404010,0x400000,0x20004000,0x404010,0x400000,0x20000010,0x400010,0x20004000,0x20000000,0x4010,0,0x400010,0x20004010,0x4000,0x404000,0x20004010,0x10,0x20400010,0x20400010,0,0x404010,0x20404000,0x4010,0x404000,0x20404000,0x20000000,0x20004000,0x10,0x20400010,0x404000,0x20404010,0x400000,0x4010,0x20000010,0x400000,0x20004000,0x20000000,0x4010,0x20000010,0x20404010,0x404000,0x20400000,0x404010,0x20404000,0,0x20400010,0x10,0x4000,0x20400000,0x404010,0x4000,0x400010,0x20004010,0,0x20404000,0x20000000,0x400010,0x20004010];
|
---|
227 | var spfunction7 = [0x200000,0x4200002,0x4000802,0,0x800,0x4000802,0x200802,0x4200800,0x4200802,0x200000,0,0x4000002,0x2,0x4000000,0x4200002,0x802,0x4000800,0x200802,0x200002,0x4000800,0x4000002,0x4200000,0x4200800,0x200002,0x4200000,0x800,0x802,0x4200802,0x200800,0x2,0x4000000,0x200800,0x4000000,0x200800,0x200000,0x4000802,0x4000802,0x4200002,0x4200002,0x2,0x200002,0x4000000,0x4000800,0x200000,0x4200800,0x802,0x200802,0x4200800,0x802,0x4000002,0x4200802,0x4200000,0x200800,0,0x2,0x4200802,0,0x200802,0x4200000,0x800,0x4000002,0x4000800,0x800,0x200002];
|
---|
228 | var spfunction8 = [0x10001040,0x1000,0x40000,0x10041040,0x10000000,0x10001040,0x40,0x10000000,0x40040,0x10040000,0x10041040,0x41000,0x10041000,0x41040,0x1000,0x40,0x10040000,0x10000040,0x10001000,0x1040,0x41000,0x40040,0x10040040,0x10041000,0x1040,0,0,0x10040040,0x10000040,0x10001000,0x41040,0x40000,0x41040,0x40000,0x10041000,0x1000,0x40,0x10040040,0x1000,0x41040,0x10001000,0x40,0x10000040,0x10040000,0x10040040,0x10000000,0x40000,0x10001040,0,0x10041040,0x40040,0x10000040,0x10040000,0x10001000,0x10001040,0,0x10041040,0x41000,0x41000,0x1040,0x1040,0x40040,0x10000000,0x10041000];
|
---|
229 |
|
---|
230 | /**
|
---|
231 | * Create necessary sub keys.
|
---|
232 | *
|
---|
233 | * @param key the 64-bit or 192-bit key.
|
---|
234 | *
|
---|
235 | * @return the expanded keys.
|
---|
236 | */
|
---|
237 | function _createKeys(key) {
|
---|
238 | var pc2bytes0 = [0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x200,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204],
|
---|
239 | pc2bytes1 = [0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101],
|
---|
240 | pc2bytes2 = [0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808],
|
---|
241 | pc2bytes3 = [0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000],
|
---|
242 | pc2bytes4 = [0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010],
|
---|
243 | pc2bytes5 = [0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420],
|
---|
244 | pc2bytes6 = [0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002],
|
---|
245 | pc2bytes7 = [0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800],
|
---|
246 | pc2bytes8 = [0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002],
|
---|
247 | pc2bytes9 = [0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408],
|
---|
248 | pc2bytes10 = [0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020],
|
---|
249 | pc2bytes11 = [0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200],
|
---|
250 | pc2bytes12 = [0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010],
|
---|
251 | pc2bytes13 = [0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105];
|
---|
252 |
|
---|
253 | // how many iterations (1 for des, 3 for triple des)
|
---|
254 | // changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys
|
---|
255 | var iterations = key.length() > 8 ? 3 : 1;
|
---|
256 |
|
---|
257 | // stores the return keys
|
---|
258 | var keys = [];
|
---|
259 |
|
---|
260 | // now define the left shifts which need to be done
|
---|
261 | var shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0];
|
---|
262 |
|
---|
263 | var n = 0, tmp;
|
---|
264 | for(var j = 0; j < iterations; j++) {
|
---|
265 | var left = key.getInt32();
|
---|
266 | var right = key.getInt32();
|
---|
267 |
|
---|
268 | tmp = ((left >>> 4) ^ right) & 0x0f0f0f0f;
|
---|
269 | right ^= tmp;
|
---|
270 | left ^= (tmp << 4);
|
---|
271 |
|
---|
272 | tmp = ((right >>> -16) ^ left) & 0x0000ffff;
|
---|
273 | left ^= tmp;
|
---|
274 | right ^= (tmp << -16);
|
---|
275 |
|
---|
276 | tmp = ((left >>> 2) ^ right) & 0x33333333;
|
---|
277 | right ^= tmp;
|
---|
278 | left ^= (tmp << 2);
|
---|
279 |
|
---|
280 | tmp = ((right >>> -16) ^ left) & 0x0000ffff;
|
---|
281 | left ^= tmp;
|
---|
282 | right ^= (tmp << -16);
|
---|
283 |
|
---|
284 | tmp = ((left >>> 1) ^ right) & 0x55555555;
|
---|
285 | right ^= tmp;
|
---|
286 | left ^= (tmp << 1);
|
---|
287 |
|
---|
288 | tmp = ((right >>> 8) ^ left) & 0x00ff00ff;
|
---|
289 | left ^= tmp;
|
---|
290 | right ^= (tmp << 8);
|
---|
291 |
|
---|
292 | tmp = ((left >>> 1) ^ right) & 0x55555555;
|
---|
293 | right ^= tmp;
|
---|
294 | left ^= (tmp << 1);
|
---|
295 |
|
---|
296 | // right needs to be shifted and OR'd with last four bits of left
|
---|
297 | tmp = (left << 8) | ((right >>> 20) & 0x000000f0);
|
---|
298 |
|
---|
299 | // left needs to be put upside down
|
---|
300 | left = ((right << 24) | ((right << 8) & 0xff0000) |
|
---|
301 | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0));
|
---|
302 | right = tmp;
|
---|
303 |
|
---|
304 | // now go through and perform these shifts on the left and right keys
|
---|
305 | for(var i = 0; i < shifts.length; ++i) {
|
---|
306 | //shift the keys either one or two bits to the left
|
---|
307 | if(shifts[i]) {
|
---|
308 | left = (left << 2) | (left >>> 26);
|
---|
309 | right = (right << 2) | (right >>> 26);
|
---|
310 | } else {
|
---|
311 | left = (left << 1) | (left >>> 27);
|
---|
312 | right = (right << 1) | (right >>> 27);
|
---|
313 | }
|
---|
314 | left &= -0xf;
|
---|
315 | right &= -0xf;
|
---|
316 |
|
---|
317 | // now apply PC-2, in such a way that E is easier when encrypting or
|
---|
318 | // decrypting this conversion will look like PC-2 except only the last 6
|
---|
319 | // bits of each byte are used rather than 48 consecutive bits and the
|
---|
320 | // order of lines will be according to how the S selection functions will
|
---|
321 | // be applied: S2, S4, S6, S8, S1, S3, S5, S7
|
---|
322 | var lefttmp = (
|
---|
323 | pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] |
|
---|
324 | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf] |
|
---|
325 | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] |
|
---|
326 | pc2bytes6[(left >>> 4) & 0xf]);
|
---|
327 | var righttmp = (
|
---|
328 | pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] |
|
---|
329 | pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf] |
|
---|
330 | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] |
|
---|
331 | pc2bytes13[(right >>> 4) & 0xf]);
|
---|
332 | tmp = ((righttmp >>> 16) ^ lefttmp) & 0x0000ffff;
|
---|
333 | keys[n++] = lefttmp ^ tmp;
|
---|
334 | keys[n++] = righttmp ^ (tmp << 16);
|
---|
335 | }
|
---|
336 | }
|
---|
337 |
|
---|
338 | return keys;
|
---|
339 | }
|
---|
340 |
|
---|
341 | /**
|
---|
342 | * Updates a single block (1 byte) using DES. The update will either
|
---|
343 | * encrypt or decrypt the block.
|
---|
344 | *
|
---|
345 | * @param keys the expanded keys.
|
---|
346 | * @param input the input block (an array of 32-bit words).
|
---|
347 | * @param output the updated output block.
|
---|
348 | * @param decrypt true to decrypt the block, false to encrypt it.
|
---|
349 | */
|
---|
350 | function _updateBlock(keys, input, output, decrypt) {
|
---|
351 | // set up loops for single or triple DES
|
---|
352 | var iterations = keys.length === 32 ? 3 : 9;
|
---|
353 | var looping;
|
---|
354 | if(iterations === 3) {
|
---|
355 | looping = decrypt ? [30, -2, -2] : [0, 32, 2];
|
---|
356 | } else {
|
---|
357 | looping = (decrypt ?
|
---|
358 | [94, 62, -2, 32, 64, 2, 30, -2, -2] :
|
---|
359 | [0, 32, 2, 62, 30, -2, 64, 96, 2]);
|
---|
360 | }
|
---|
361 |
|
---|
362 | var tmp;
|
---|
363 |
|
---|
364 | var left = input[0];
|
---|
365 | var right = input[1];
|
---|
366 |
|
---|
367 | // first each 64 bit chunk of the message must be permuted according to IP
|
---|
368 | tmp = ((left >>> 4) ^ right) & 0x0f0f0f0f;
|
---|
369 | right ^= tmp;
|
---|
370 | left ^= (tmp << 4);
|
---|
371 |
|
---|
372 | tmp = ((left >>> 16) ^ right) & 0x0000ffff;
|
---|
373 | right ^= tmp;
|
---|
374 | left ^= (tmp << 16);
|
---|
375 |
|
---|
376 | tmp = ((right >>> 2) ^ left) & 0x33333333;
|
---|
377 | left ^= tmp;
|
---|
378 | right ^= (tmp << 2);
|
---|
379 |
|
---|
380 | tmp = ((right >>> 8) ^ left) & 0x00ff00ff;
|
---|
381 | left ^= tmp;
|
---|
382 | right ^= (tmp << 8);
|
---|
383 |
|
---|
384 | tmp = ((left >>> 1) ^ right) & 0x55555555;
|
---|
385 | right ^= tmp;
|
---|
386 | left ^= (tmp << 1);
|
---|
387 |
|
---|
388 | // rotate left 1 bit
|
---|
389 | left = ((left << 1) | (left >>> 31));
|
---|
390 | right = ((right << 1) | (right >>> 31));
|
---|
391 |
|
---|
392 | for(var j = 0; j < iterations; j += 3) {
|
---|
393 | var endloop = looping[j + 1];
|
---|
394 | var loopinc = looping[j + 2];
|
---|
395 |
|
---|
396 | // now go through and perform the encryption or decryption
|
---|
397 | for(var i = looping[j]; i != endloop; i += loopinc) {
|
---|
398 | var right1 = right ^ keys[i];
|
---|
399 | var right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1];
|
---|
400 |
|
---|
401 | // passing these bytes through the S selection functions
|
---|
402 | tmp = left;
|
---|
403 | left = right;
|
---|
404 | right = tmp ^ (
|
---|
405 | spfunction2[(right1 >>> 24) & 0x3f] |
|
---|
406 | spfunction4[(right1 >>> 16) & 0x3f] |
|
---|
407 | spfunction6[(right1 >>> 8) & 0x3f] |
|
---|
408 | spfunction8[right1 & 0x3f] |
|
---|
409 | spfunction1[(right2 >>> 24) & 0x3f] |
|
---|
410 | spfunction3[(right2 >>> 16) & 0x3f] |
|
---|
411 | spfunction5[(right2 >>> 8) & 0x3f] |
|
---|
412 | spfunction7[right2 & 0x3f]);
|
---|
413 | }
|
---|
414 | // unreverse left and right
|
---|
415 | tmp = left;
|
---|
416 | left = right;
|
---|
417 | right = tmp;
|
---|
418 | }
|
---|
419 |
|
---|
420 | // rotate right 1 bit
|
---|
421 | left = ((left >>> 1) | (left << 31));
|
---|
422 | right = ((right >>> 1) | (right << 31));
|
---|
423 |
|
---|
424 | // now perform IP-1, which is IP in the opposite direction
|
---|
425 | tmp = ((left >>> 1) ^ right) & 0x55555555;
|
---|
426 | right ^= tmp;
|
---|
427 | left ^= (tmp << 1);
|
---|
428 |
|
---|
429 | tmp = ((right >>> 8) ^ left) & 0x00ff00ff;
|
---|
430 | left ^= tmp;
|
---|
431 | right ^= (tmp << 8);
|
---|
432 |
|
---|
433 | tmp = ((right >>> 2) ^ left) & 0x33333333;
|
---|
434 | left ^= tmp;
|
---|
435 | right ^= (tmp << 2);
|
---|
436 |
|
---|
437 | tmp = ((left >>> 16) ^ right) & 0x0000ffff;
|
---|
438 | right ^= tmp;
|
---|
439 | left ^= (tmp << 16);
|
---|
440 |
|
---|
441 | tmp = ((left >>> 4) ^ right) & 0x0f0f0f0f;
|
---|
442 | right ^= tmp;
|
---|
443 | left ^= (tmp << 4);
|
---|
444 |
|
---|
445 | output[0] = left;
|
---|
446 | output[1] = right;
|
---|
447 | }
|
---|
448 |
|
---|
449 | /**
|
---|
450 | * Deprecated. Instead, use:
|
---|
451 | *
|
---|
452 | * forge.cipher.createCipher('DES-<mode>', key);
|
---|
453 | * forge.cipher.createDecipher('DES-<mode>', key);
|
---|
454 | *
|
---|
455 | * Creates a deprecated DES cipher object. This object's mode will default to
|
---|
456 | * CBC (cipher-block-chaining).
|
---|
457 | *
|
---|
458 | * The key may be given as a binary-encoded string of bytes or a byte buffer.
|
---|
459 | *
|
---|
460 | * @param options the options to use.
|
---|
461 | * key the symmetric key to use (64 or 192 bits).
|
---|
462 | * output the buffer to write to.
|
---|
463 | * decrypt true for decryption, false for encryption.
|
---|
464 | * mode the cipher mode to use (default: 'CBC').
|
---|
465 | *
|
---|
466 | * @return the cipher.
|
---|
467 | */
|
---|
468 | function _createCipher(options) {
|
---|
469 | options = options || {};
|
---|
470 | var mode = (options.mode || 'CBC').toUpperCase();
|
---|
471 | var algorithm = 'DES-' + mode;
|
---|
472 |
|
---|
473 | var cipher;
|
---|
474 | if(options.decrypt) {
|
---|
475 | cipher = forge.cipher.createDecipher(algorithm, options.key);
|
---|
476 | } else {
|
---|
477 | cipher = forge.cipher.createCipher(algorithm, options.key);
|
---|
478 | }
|
---|
479 |
|
---|
480 | // backwards compatible start API
|
---|
481 | var start = cipher.start;
|
---|
482 | cipher.start = function(iv, options) {
|
---|
483 | // backwards compatibility: support second arg as output buffer
|
---|
484 | var output = null;
|
---|
485 | if(options instanceof forge.util.ByteBuffer) {
|
---|
486 | output = options;
|
---|
487 | options = {};
|
---|
488 | }
|
---|
489 | options = options || {};
|
---|
490 | options.output = output;
|
---|
491 | options.iv = iv;
|
---|
492 | start.call(cipher, options);
|
---|
493 | };
|
---|
494 |
|
---|
495 | return cipher;
|
---|
496 | }
|
---|