143 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| var assert = require('minimalistic-assert');
 | |
| var inherits = require('inherits');
 | |
| 
 | |
| var utils = require('./utils');
 | |
| var Cipher = require('./cipher');
 | |
| 
 | |
| function DESState() {
 | |
|   this.tmp = new Array(2);
 | |
|   this.keys = null;
 | |
| }
 | |
| 
 | |
| function DES(options) {
 | |
|   Cipher.call(this, options);
 | |
| 
 | |
|   var state = new DESState();
 | |
|   this._desState = state;
 | |
| 
 | |
|   this.deriveKeys(state, options.key);
 | |
| }
 | |
| inherits(DES, Cipher);
 | |
| module.exports = DES;
 | |
| 
 | |
| DES.create = function create(options) {
 | |
|   return new DES(options);
 | |
| };
 | |
| 
 | |
| var shiftTable = [
 | |
|   1, 1, 2, 2, 2, 2, 2, 2,
 | |
|   1, 2, 2, 2, 2, 2, 2, 1
 | |
| ];
 | |
| 
 | |
| DES.prototype.deriveKeys = function deriveKeys(state, key) {
 | |
|   state.keys = new Array(16 * 2);
 | |
| 
 | |
|   assert.equal(key.length, this.blockSize, 'Invalid key length');
 | |
| 
 | |
|   var kL = utils.readUInt32BE(key, 0);
 | |
|   var kR = utils.readUInt32BE(key, 4);
 | |
| 
 | |
|   utils.pc1(kL, kR, state.tmp, 0);
 | |
|   kL = state.tmp[0];
 | |
|   kR = state.tmp[1];
 | |
|   for (var i = 0; i < state.keys.length; i += 2) {
 | |
|     var shift = shiftTable[i >>> 1];
 | |
|     kL = utils.r28shl(kL, shift);
 | |
|     kR = utils.r28shl(kR, shift);
 | |
|     utils.pc2(kL, kR, state.keys, i);
 | |
|   }
 | |
| };
 | |
| 
 | |
| DES.prototype._update = function _update(inp, inOff, out, outOff) {
 | |
|   var state = this._desState;
 | |
| 
 | |
|   var l = utils.readUInt32BE(inp, inOff);
 | |
|   var r = utils.readUInt32BE(inp, inOff + 4);
 | |
| 
 | |
|   // Initial Permutation
 | |
|   utils.ip(l, r, state.tmp, 0);
 | |
|   l = state.tmp[0];
 | |
|   r = state.tmp[1];
 | |
| 
 | |
|   if (this.type === 'encrypt')
 | |
|     this._encrypt(state, l, r, state.tmp, 0);
 | |
|   else
 | |
|     this._decrypt(state, l, r, state.tmp, 0);
 | |
| 
 | |
|   l = state.tmp[0];
 | |
|   r = state.tmp[1];
 | |
| 
 | |
|   utils.writeUInt32BE(out, l, outOff);
 | |
|   utils.writeUInt32BE(out, r, outOff + 4);
 | |
| };
 | |
| 
 | |
| DES.prototype._pad = function _pad(buffer, off) {
 | |
|   var value = buffer.length - off;
 | |
|   for (var i = off; i < buffer.length; i++)
 | |
|     buffer[i] = value;
 | |
| 
 | |
|   return true;
 | |
| };
 | |
| 
 | |
| DES.prototype._unpad = function _unpad(buffer) {
 | |
|   var pad = buffer[buffer.length - 1];
 | |
|   for (var i = buffer.length - pad; i < buffer.length; i++)
 | |
|     assert.equal(buffer[i], pad);
 | |
| 
 | |
|   return buffer.slice(0, buffer.length - pad);
 | |
| };
 | |
| 
 | |
| DES.prototype._encrypt = function _encrypt(state, lStart, rStart, out, off) {
 | |
|   var l = lStart;
 | |
|   var r = rStart;
 | |
| 
 | |
|   // Apply f() x16 times
 | |
|   for (var i = 0; i < state.keys.length; i += 2) {
 | |
|     var keyL = state.keys[i];
 | |
|     var keyR = state.keys[i + 1];
 | |
| 
 | |
|     // f(r, k)
 | |
|     utils.expand(r, state.tmp, 0);
 | |
| 
 | |
|     keyL ^= state.tmp[0];
 | |
|     keyR ^= state.tmp[1];
 | |
|     var s = utils.substitute(keyL, keyR);
 | |
|     var f = utils.permute(s);
 | |
| 
 | |
|     var t = r;
 | |
|     r = (l ^ f) >>> 0;
 | |
|     l = t;
 | |
|   }
 | |
| 
 | |
|   // Reverse Initial Permutation
 | |
|   utils.rip(r, l, out, off);
 | |
| };
 | |
| 
 | |
| DES.prototype._decrypt = function _decrypt(state, lStart, rStart, out, off) {
 | |
|   var l = rStart;
 | |
|   var r = lStart;
 | |
| 
 | |
|   // Apply f() x16 times
 | |
|   for (var i = state.keys.length - 2; i >= 0; i -= 2) {
 | |
|     var keyL = state.keys[i];
 | |
|     var keyR = state.keys[i + 1];
 | |
| 
 | |
|     // f(r, k)
 | |
|     utils.expand(l, state.tmp, 0);
 | |
| 
 | |
|     keyL ^= state.tmp[0];
 | |
|     keyR ^= state.tmp[1];
 | |
|     var s = utils.substitute(keyL, keyR);
 | |
|     var f = utils.permute(s);
 | |
| 
 | |
|     var t = l;
 | |
|     l = (r ^ f) >>> 0;
 | |
|     r = t;
 | |
|   }
 | |
| 
 | |
|   // Reverse Initial Permutation
 | |
|   utils.rip(l, r, out, off);
 | |
| };
 |