UNPKG

@aleen42/idea

Version:

The IDEA cypher implementation in JavaScript

372 lines (312 loc) 9.78 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else { var a = factory(); for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; } })(typeof window !== 'undefined' ? window : this, function() { return /******/ (function() { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ 5241: /***/ (function(module) { /* * Copyright (c) 1999-2003 AppGate Network Security AB. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code as * defined in and that are subject to the MindTerm Public Source License, * Version 2.0, (the 'License'). You may not use this file except in compliance * with the License. * * You should have received a copy of the MindTerm Public Source License * along with this software; see the file LICENSE. If not, write to * AppGate Network Security AB, Stora Badhusgatan 18-20, 41121 Goteborg, SWEDEN * *****************************************************************************/ /* * Author's comment: The contents of this file is heavily based upon Bruce * Schneier's c-code found in his book: Bruce Schneier: Applied Cryptography 2nd * ed., John Wiley & Sons, 1996 * * The IDEA mathematical formula may be covered by one or more of the following * patents: PCT/CH91/00117, EP 0 482 154 B1, US Pat. 5,214,703. * Hence it might be subject to licensing for commercial use. */ var DEFAULT_XOR_KEY = 197; // default xor key using by ENC3 var BLOCK_SIZE = 8; // bytes in a data-block /** * @param {Int8Array} key * @param {number} xorKey * @returns {exports} */ module.exports = function IDEA(key, xorKey) { if (xorKey === void 0) { xorKey = DEFAULT_XOR_KEY; } this.encryptor = new Engine(); this.decryptor = new Engine(); function Engine() { var _this = this; this.keySchedule = []; this.getBlockSize = function () { return BLOCK_SIZE; }; this.processBlock = function (src, inOff, out, outOff) { ideaCipher(src, inOff, out, outOff, _this.keySchedule); return BLOCK_SIZE; }; } /** * @param {Int8Array} key * @param {number} xorKey */ this.setKey = function (key, xorKey) { ideaExpandKey(key, this.encryptor.keySchedule); ideaInvertKey(this.encryptor.keySchedule, this.decryptor.keySchedule); xorKey && (this.xorKey = xorKey); }; /** * the method to encrypt * @param {Int8Array | Uint8Array} src * @returns {Int8Array} */ this.encrypt = function (src) { var len = src.length, out = new Int8Array(len), srcOff = 0, outOff = 0; if (this.xorKey === -1) { Padding.noPaddingFinal(this.encryptor, src, srcOff, out, outOff, len); } else { Padding.xorPaddingFinal(this.encryptor, this.xorKey, src, srcOff, out, outOff, len); } return out; }; /** * the method to decrypt * @param {Int8Array | Uint8Array} src * @returns {Int8Array} */ this.decrypt = function (src) { var len = src.length, out = new Int8Array(len), srcOff = 0, outOff = 0; if (this.xorKey === -1) { Padding.noPaddingFinal(this.decryptor, src, srcOff, out, outOff, len); } else { Padding.xorPaddingFinal(this.decryptor, this.xorKey, src, srcOff, out, outOff, len); } return out; }; /** * @param {Int8Array} key * @param {int[]} keySchedule */ function ideaExpandKey(key, keySchedule) { var i, ki = 0, j; for (i = 0; i < 8; i++) { keySchedule[i] = (key[2 * i] & 0xff) << 8 | key[2 * i + 1] & 0xff; } for (i = 8, j = 0; i < 52; i++) { j++; keySchedule[ki + j + 7] = (keySchedule[ki + (j & 7)] << 9 | keySchedule[ki + (j + 1 & 7)] >>> 7) & 0xffff; ki += j & 8; j &= 7; } } /** * @param {int[]} key * @param {int[]} keySchedule */ function ideaInvertKey(key, keySchedule) { var i, j, k, t1, t2, t3; j = 0; k = 51; t1 = mulInv(key[j++]); t2 = -key[j++] & 0xffff; t3 = -key[j++] & 0xffff; keySchedule[k--] = mulInv(key[j++]); keySchedule[k--] = t3; keySchedule[k--] = t2; keySchedule[k--] = t1; for (i = 1; i < 8; i++) { t1 = key[j++]; keySchedule[k--] = key[j++]; keySchedule[k--] = t1; t1 = mulInv(key[j++]); t2 = -key[j++] & 0xffff; t3 = -key[j++] & 0xffff; keySchedule[k--] = mulInv(key[j++]); keySchedule[k--] = t2; keySchedule[k--] = t3; keySchedule[k--] = t1; } t1 = key[j++]; keySchedule[k--] = key[j++]; keySchedule[k--] = t1; t1 = mulInv(key[j++]); t2 = -key[j++] & 0xffff; t3 = -key[j++] & 0xffff; // noinspection UnusedAssignment keySchedule[k--] = mulInv(key[j++]); keySchedule[k--] = t3; keySchedule[k--] = t2; // noinspection UnusedAssignment keySchedule[k--] = t1; } function ideaCipher(src, srcOffset, out, outOffset, keySchedule) { var t1 = 0, t2, x1, x2, x3, x4, ki = 0; var l = getIntMSBO(src, srcOffset); var r = getIntMSBO(src, srcOffset + 4); x1 = l >>> 16; x2 = l & 0xffff; x3 = r >>> 16; x4 = r & 0xffff; for (var round = 0; round < 8; round++) { x1 = mul(x1 & 0xffff, keySchedule[ki++]); x2 = x2 + keySchedule[ki++]; x3 = x3 + keySchedule[ki++]; x4 = mul(x4 & 0xffff, keySchedule[ki++]); t1 = x1 ^ x3; t2 = x2 ^ x4; t1 = mul(t1 & 0xffff, keySchedule[ki++]); t2 = t1 + t2; t2 = mul(t2 & 0xffff, keySchedule[ki++]); t1 = t1 + t2; x1 = x1 ^ t2; x4 = x4 ^ t1; t1 = t1 ^ x2; x2 = t2 ^ x3; x3 = t1; } t2 = x2; x1 = mul(x1 & 0xffff, keySchedule[ki++]); x2 = t1 + keySchedule[ki++]; x3 = t2 + keySchedule[ki++] & 0xffff; x4 = mul(x4 & 0xffff, keySchedule[ki]); putIntMSBO(x1 << 16 | x2 & 0xffff, out, outOffset); putIntMSBO(x3 << 16 | x4 & 0xffff, out, outOffset + 4); } function mul(a, b) { var ab = a * b; if (ab !== 0) { var lo = ab & 0xffff; var hi = ab >>> 16 & 0xffff; return lo - hi + (lo < hi ? 1 : 0); } if (a === 0) { return 1 - b; } return 1 - a; } function mulInv(x) { var t0, t1, q, y; if (x <= 1) { return x; } t1 = Math.floor(0x10001 / x); y = 0x10001 % x; if (y === 1) { return 1 - t1 & 0xffff; } t0 = 1; do { q = Math.floor(x / y); x = x % y; t0 += q * t1; if (x === 1) { return t0; } q = Math.floor(y / x); y = y % x; t1 += q * t0; } while (y !== 1); return 1 - t1 & 0xffff; } function getIntMSBO(src, srcOffset) { return (src[srcOffset] & 0xff) << 24 | (src[srcOffset + 1] & 0xff) << 16 | (src[srcOffset + 2] & 0xff) << 8 | src[srcOffset + 3] & 0xff; } function putIntMSBO(val, dest, destOffset) { dest[destOffset] = val >>> 24 & 0xff; dest[destOffset + 1] = val >>> 16 & 0xff; dest[destOffset + 2] = val >>> 8 & 0xff; dest[destOffset + 3] = val & 0xff; } this.setKey(key, xorKey); return this; }; /** * @see org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher#engineSetPadding * BaseBlockCipher.engineSetPadding("NOPADDING") */ var Padding = { noPaddingFinal: function (cipher, src, inOff, out, outOff, len) { doFinal(cipher, false, 0, src, inOff, out, outOff, len); }, xorPaddingFinal: function (cipher, xorKey, src, inOff, out, outOff, len) { doFinal(cipher, true, xorKey, src, inOff, out, outOff, len); } }; function doFinal(cipher, xorPadding, xorKey, src, inOff, out, outOff, len) { var blockSize = cipher.getBlockSize(); // assert Integer.bitCount(blockSize) == 1; var nBlocks = Math.floor(len / blockSize); // use the cipher algorithm for parts divided by the block size. for (var i = 0; i < nBlocks; i++) { cipher.processBlock(src, inOff, out, outOff); inOff += blockSize; outOff += blockSize; len -= blockSize; } if (!xorPadding && len > 0) { throw new Error('no padding, expecting more inputs'); } // use xor encryption for remain parts for (var _i = 0; _i < len; _i++) { out[outOff + _i] = src[inOff + _i] ^ xorKey; } } /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module is referenced by other modules so it can't be inlined /******/ var __webpack_exports__ = __webpack_require__(5241); /******/ /******/ return __webpack_exports__; /******/ })() ; });