[6a3a178] | 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 | }
|
---|