diff --git a/include/des.js b/include/des.js index 0075f7dc..2bab3092 100644 --- a/include/des.js +++ b/include/des.js @@ -1,13 +1,67 @@ /* - * From: http://www.tero.co.uk/des/ - * Paul Tero, July 2001 + * Ported from Flashlight VNC ActionScript implementation: + * http://www.wizhelp.com/flashlight-vnc/ * - * Derived from Eric Young's OpenSSL C implementation (BSD-style license) + * Full attribution follows: + * + * ------------------------------------------------------------------------- + * + * This DES class has been extracted from package Acme.Crypto for use in VNC. + * The bytebit[] array has been reversed so that the most significant bit + * in each byte of the key is ignored, not the least significant. Also the + * unnecessary odd parity code has been removed. + * + * These changes are: + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + + * DesCipher - the DES encryption method + * + * The meat of this code is by Dave Zimmerman , and is: + * + * Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and + * without fee is hereby granted, provided that this copyright notice is kept + * intact. * - * Optimised for performance with large blocks by Michael Hayworth, November 2001 - * http://www.netdealing.com + * WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY + * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE + * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. * - * THIS SOFTWARE IS PROVIDED "AS IS" AND + * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE + * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE + * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT + * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE + * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE + * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE + * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET WORKSHOP + * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR + * HIGH RISK ACTIVITIES. + * + * + * The rest is: + * + * Copyright (C) 1996 by Jef Poskanzer . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE @@ -18,210 +72,361 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * Visit the ACME Labs Java page for up-to-date versions of this and other + * fine Java utilities: http://www.acme.com/java/ */ +DES = { -//des -//this takes the key (byte array), the message (byte array), and whether to encrypt or decrypt -function des (key, message, encrypt, mode, iv, padding) { - //declaring this locally speeds things up a bit - var spfunction1 = new Array (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); - var spfunction2 = new Array (-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); - var spfunction3 = new Array (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); - var spfunction4 = new Array (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); - var spfunction5 = new Array (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); - var spfunction6 = new Array (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); - var spfunction7 = new Array (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); - var spfunction8 = new Array (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); + // Tables, permutations, S-boxes, etc. - //create the 16 or 48 subkeys we will need - var keys = des_createKeys (key); - var m=0, i, j, temp, temp2, right1, right2, left, right, looping; - var cbcleft, cbcleft2, cbcright, cbcright2 - var endloop, loopinc; - var len = message.length; - var chunk = 0; - //set up the loops for single and triple des - var iterations = keys.length == 32 ? 3 : 9; //single or triple des - if (iterations == 3) {looping = encrypt ? new Array (0, 32, 2) : new Array (30, -2, -2);} - else {looping = encrypt ? new Array (0, 32, 2, 62, 30, -2, 64, 96, 2) : new Array (94, 62, -2, 32, 64, 2, 30, -2, -2);} + bytebit : [0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80], + bigbyte : [ 0x800000, 0x400000, 0x200000, 0x100000, + 0x080000, 0x040000, 0x020000, 0x010000, 0x008000, 0x004000, + 0x002000, 0x001000, 0x000800, 0x000400, 0x000200, 0x000100, + 0x000080, 0x000040, 0x000020, 0x000010, 0x000008, 0x000004, + 0x000002, 0x000001], + pc1 : [ 56, 48, 40, 32, + 24, 16, 8, 0, 57, 49, + 41, 33, 25, 17, 9, 1, + 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, + 29, 21, 13, 5, 60, 52, + 44, 36, 28, 20, 12, 4, + 27, 19, 11, 3 ], + totrot : [ 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, + 23, 25, 27, 28], + pc2 : [ 13, 16, 10, 23, + 0, 4, 2, 27, 14, 5, + 20, 9, 22, 18, 11, 3, + 25, 7, 15, 6, 26, 19, + 12, 1, 40, 51, 30, 36, + 46, 54, 29, 39, 50, 44, + 32, 47, 43, 48, 38, 55, + 33, 52, 45, 41, 49, 35, + 28, 31, ], + SP1 : [ 0x01010400, 0x00000000, 0x00010000, + 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, + 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, + 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, + 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, + 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, + 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, + 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, + 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, + 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, + 0x01010004], + SP2 : [ 0x80108020, 0x80008000, 0x00008000, + 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, + 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, + 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, + 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, + 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, + 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, + 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, + 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, + 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, + 0x00108000], + SP3 : [ 0x00000208, 0x08020200, 0x00000000, + 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, + 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, + 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, + 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, + 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, + 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, + 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, + 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, + 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, + 0x00020200], + SP4 : [ 0x00802001, 0x00002081, 0x00002081, + 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, + 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, + 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, + 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, + 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, + 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, + 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, + 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, + 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, + 0x00802080], + SP5 : [ 0x00000100, 0x02080100, 0x02080000, + 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, + 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, + 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, + 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, + 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, + 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, + 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, + 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, + 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, + 0x40000100], + SP6 : [ 0x20000010, 0x20400000, 0x00004000, + 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, + 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, + 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, + 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, + 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, + 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, + 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, + 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, + 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, + 0x20004010], + SP7 : [ 0x00200000, 0x04200002, 0x04000802, + 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, + 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, + 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, + 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, + 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, + 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, + 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, + 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, + 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, + 0x00200002], + SP8 : [ 0x10001040, 0x00001000, 0x00040000, + 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, + 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, + 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, + 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, + 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, + 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, + 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, + 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, + 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, + 0x10041000], - //pad the message depending on the padding parameter - if (padding == 2) { - for (var i=0; i<8; i++) { message.push(" "); } //pad the message with spaces - } else if (padding == 1) { - temp = 8-(len%8); - for (var i=0; i<8; i++) { message.push(temp); }; - if (temp==8) len+=8; //PKCS7 padding - } else if (!padding) { - for (var i=0; i<8; i++) { message.push(0); } //pad the message out with null bytes - } + // Key routines. - //store the result here - result = []; - tempresult = []; + encryptKeys : [], + decryptKeys : [], - if (mode == 1) { //CBC mode - cbcleft = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++); - cbcright = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++); - m=0; - } + // / Set the key. + setKeys : function(key) { + DES.encryptKeys = new Array(32); + DES.decryptKeys = new Array(32); + + DES.deskey(key, true, DES.encryptKeys); + DES.deskey(key, false, DES.decryptKeys); + console.log("DES.encryptKeys: " + DES.encryptKeys); + }, - //loop through each 64 bit chunk of the message - while (m < len) { - left = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; - right = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; + // Turn an 8-byte key into internal keys. + deskey : function(keyBlock, encrypting, KnL) { + var i, j, l, m, n; + var pc1m = new Array(56); + var pcr = new Array(56); + var kn = new Array(32); - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode == 1) {if (encrypt) {left ^= cbcleft; right ^= cbcright;} else {cbcleft2 = cbcleft; cbcright2 = cbcright; cbcleft = left; cbcright = right;}} + for (j = 0; j < 56; ++j) { + l = DES.pc1[j]; + m = l & 07; + pc1m[j] = ((keyBlock[l >>> 3] & DES.bytebit[m]) != 0) ? 1: 0; + } - //first each 64 but chunk of the message must be permuted according to IP - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4); - temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16); - temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8); - temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1); + for (i = 0; i < 16; ++i) { + if (encrypting) + m = i << 1; + else + m = (15- i) << 1; + n = m + 1; + kn[m] = kn[n] = 0; + for (j = 0; j < 28; ++j) { + l = j + DES.totrot[i]; + if (l < 28) + pcr[j] = pc1m[l]; + else + pcr[j] = pc1m[l - 28]; + } + for (j = 28; j < 56; ++j) { + l = j + DES.totrot[i]; + if (l < 56) + pcr[j] = pc1m[l]; + else + pcr[j] = pc1m[l - 28]; + } + for (j = 0; j < 24; ++j) { + if (pcr[DES.pc2[j]] != 0) + kn[m] |= DES.bigbyte[j]; + if (pcr[DES.pc2[j + 24]] != 0) + kn[n] |= DES.bigbyte[j]; + } + } + DES.cookey(kn, KnL); + }, - left = ((left << 1) | (left >>> 31)); - right = ((right << 1) | (right >>> 31)); + cookey: function(raw, KnL) { + var raw0, raw1; + var rawi, KnLi; + var i; - //do this either 1 or 3 times for each chunk of the message - for (j=0; j>> 4) | (right << 28)) ^ keys[i+1]; - //the result is attained by passing these bytes through the S selection functions - temp = left; - left = right; - right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f] - | spfunction6[(right1 >>> 8) & 0x3f] | spfunction8[right1 & 0x3f] - | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & 0x3f] - | spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]); - } - temp = left; left = right; right = temp; //unreverse left and right - } //for either 1 or 3 iterations + for (i = 0, rawi = 0, KnLi = 0; i < 16; ++i) { + raw0 = raw[rawi++]; + raw1 = raw[rawi++]; + KnL[KnLi] = (raw0 & 0x00fc0000) << 6; + KnL[KnLi] |= (raw0 & 0x00000fc0) << 10; + KnL[KnLi] |= (raw1 & 0x00fc0000) >>> 10; + KnL[KnLi] |= (raw1 & 0x00000fc0) >>> 6; + ++KnLi; + KnL[KnLi] = (raw0 & 0x0003f000) << 12; + KnL[KnLi] |= (raw0 & 0x0000003f) << 16; + KnL[KnLi] |= (raw1 & 0x0003f000) >>> 4; + KnL[KnLi] |= (raw1 & 0x0000003f); + ++KnLi; + } + }, - //move then each one bit to the right - left = ((left >>> 1) | (left << 31)); - right = ((right >>> 1) | (right << 31)); + // Block encryption routines. - //now perform IP-1, which is IP in the opposite direction - temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8); - temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2); - temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16); - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4); + // / Encrypt a block of eight bytes. + encrypt: function(clearText, clearOff, cipherText, cipherOff) { + var tempInts = new Array(12); + DES.squashBytesToInts(clearText, clearOff, tempInts, 0, 2); + DES.des(tempInts, tempInts, DES.encryptKeys); + DES.spreadIntsToBytes(tempInts, 0, cipherText, cipherOff, 2); + }, - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode == 1) {if (encrypt) {cbcleft = left; cbcright = right;} else {left ^= cbcleft2; right ^= cbcright2;}} - tempresult = tempresult.concat([(left>>>24), ((left>>>16) & 0xff), ((left>>>8) & 0xff), (left & 0xff), (right>>>24), ((right>>>16) & 0xff), ((right>>>8) & 0xff), (right & 0xff)]); + // / Decrypt a block of eight bytes. + decrypt: function(cipherText, cipherOff, clearText, clearOff) { + var tempInts = new Array(12); + DES.squashBytesToInts(cipherText, cipherOff, tempInts, 0, 2); + DES.des(tempInts, tempInts, DES.decryptKeys); + DES.spreadIntsToBytes(tempInts, 0, clearText, clearOff, 2); + }, - chunk += 8; - if (chunk == 512) {result = result.concat(tempresult); tempresult = []; chunk = 0;} - } //for every 8 characters, or 64 bits in the message + // The DES function. + des: function(inInts, outInts, keys) { + var fval, work, right, leftt; + var round; + var keysi = 0; - //return the result as an array - return result.concat(tempresult); -} //end of des + leftt = inInts[0]; + right = inInts[1]; + work = ((leftt >>> 4) ^ right) & 0x0f0f0f0f; + right ^= work; + leftt ^= (work << 4); + work = ((leftt >>> 16) ^ right) & 0x0000ffff; + right ^= work; + leftt ^= (work << 16); -//des_createKeys -//this takes as input a 64 bit key (even though only 56 bits are used) -//as an array of 2 integers, and returns 16 48 bit keys -function des_createKeys (key) { - //declaring this locally speeds things up a bit - pc2bytes0 = new Array (0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x200,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204); - pc2bytes1 = new Array (0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101); - pc2bytes2 = new Array (0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808); - pc2bytes3 = new Array (0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000); - pc2bytes4 = new Array (0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010); - pc2bytes5 = new Array (0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420); - pc2bytes6 = new Array (0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002); - pc2bytes7 = new Array (0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800); - pc2bytes8 = new Array (0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002); - pc2bytes9 = new Array (0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408); - pc2bytes10 = new Array (0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020); - pc2bytes11 = new Array (0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200); - pc2bytes12 = new Array (0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010); - pc2bytes13 = new Array (0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105); + work = ((right >>> 2) ^ leftt) & 0x33333333; + leftt ^= work; + right ^= (work << 2); - //how many iterations (1 for des, 3 for triple des) - var iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys - //stores the return keys - var keys = new Array (32 * iterations); - //now define the left shifts which need to be done - var shifts = new Array (0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0); - //other variables - var lefttemp, righttemp, m=0, n=0, temp; + work = ((right >>> 8) ^ leftt) & 0x00ff00ff; + leftt ^= work; + right ^= (work << 8); + right = (right << 1) | ((right >>> 31) & 1); - for (var j=0; j>> 31) & 1); - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4); - temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16); - temp = ((left >>> 2) ^ right) & 0x33333333; right ^= temp; left ^= (temp << 2); - temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16); - temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8); - temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1); + for (round = 0; round < 8; ++round) { + work = (right << 28) | (right >>> 4); + work ^= keys[keysi++]; + fval = DES.SP7[work & 0x0000003f]; + fval |= DES.SP5[(work >>> 8) & 0x0000003f]; + fval |= DES.SP3[(work >>> 16) & 0x0000003f]; + fval |= DES.SP1[(work >>> 24) & 0x0000003f]; + work = right ^ keys[keysi++]; + fval |= DES.SP8[work & 0x0000003f]; + fval |= DES.SP6[(work >>> 8) & 0x0000003f]; + fval |= DES.SP4[(work >>> 16) & 0x0000003f]; + fval |= DES.SP2[(work >>> 24) & 0x0000003f]; + leftt ^= fval; + work = (leftt << 28) | (leftt >>> 4); + work ^= keys[keysi++]; + fval = DES.SP7[work & 0x0000003f]; + fval |= DES.SP5[(work >>> 8) & 0x0000003f]; + fval |= DES.SP3[(work >>> 16) & 0x0000003f]; + fval |= DES.SP1[(work >>> 24) & 0x0000003f]; + work = leftt ^ keys[keysi++]; + fval |= DES.SP8[work & 0x0000003f]; + fval |= DES.SP6[(work >>> 8) & 0x0000003f]; + fval |= DES.SP4[(work >>> 16) & 0x0000003f]; + fval |= DES.SP2[(work >>> 24) & 0x0000003f]; + right ^= fval; + } - //the right side needs to be shifted and to get the last four bits of the left side - temp = (left << 8) | ((right >>> 20) & 0x000000f0); - //left needs to be put upside down - left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0); - right = temp; + right = (right << 31) | (right >>> 1); + work = (leftt ^ right) & 0xaaaaaaaa; + leftt ^= work; + right ^= work; + leftt = (leftt << 31) | (leftt >>> 1); + work = ((leftt >>> 8) ^ right) & 0x00ff00ff; + right ^= work; + leftt ^= (work << 8); + work = ((leftt >>> 2) ^ right) & 0x33333333; + right ^= work; + leftt ^= (work << 2); + work = ((right >>> 16) ^ leftt) & 0x0000ffff; + leftt ^= work; + right ^= (work << 16); + work = ((right >>> 4) ^ leftt) & 0x0f0f0f0f; + leftt ^= work; + right ^= (work << 4); + outInts[0] = right; + outInts[1] = leftt; + }, - //now go through and perform these shifts on the left and right keys - for (var i=0; i < shifts.length; i++) { - //shift the keys either one or two bits to the left - if (shifts[i]) {left = (left << 2) | (left >>> 26); right = (right << 2) | (right >>> 26);} - else {left = (left << 1) | (left >>> 27); right = (right << 1) | (right >>> 27);} - left &= -0xf; right &= -0xf; + // Routines taken from other parts of the Acme utilities. - //now apply PC-2, in such a way that E is easier when encrypting or decrypting - //this conversion will look like PC-2 except only the last 6 bits of each byte are used - //rather than 48 consecutive bits and the order of lines will be according to - //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 - lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] - | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf] - | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] - | pc2bytes6[(left >>> 4) & 0xf]; - righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] - | pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf] - | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] - | pc2bytes13[(right >>> 4) & 0xf]; - temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff; - keys[n++] = lefttemp ^ temp; keys[n++] = righttemp ^ (temp << 16); + // / Squash bytes down to ints. + squashBytesToInts: function (inBytes, inOff, outInts, outOff, intLen) { + for (var i = 0; i < intLen; ++i) + outInts[outOff + i] = ((inBytes[inOff + i * 4] & 0xff) << 24) + | ((inBytes[inOff + i * 4+ 1] & 0xff) << 16) + | ((inBytes[inOff + i * 4+ 2] & 0xff) << 8) + | (inBytes[inOff + i * 4+ 3] & 0xff); + }, + + // / Spread ints into unsigned bytes. + spreadIntsToBytes: function (inInts, inOff, outBytes, outOff, intLen) { + for (var i = 0; i < intLen; ++i) { + outBytes[outOff + i * 4] = (inInts[inOff + i] >>> 24) % 256; + outBytes[outOff + i * 4+ 1] = (inInts[inOff + i] >>> 16) % 256; + outBytes[outOff + i * 4+ 2] = (inInts[inOff + i] >>> 8) % 256; + outBytes[outOff + i * 4+ 3] = (inInts[inOff + i]) % 256; + } + /* Make unsigned */ + var idx; + for (var i = 0; i < intLen; ++i) { + for (var j = 0; j < 4; j++) { + idx = outOff + i * 4 + j; + if (outBytes[idx] < 0) { + outBytes[idx] += 256; + } + } + } } - } //for each iterations - //return the keys we've created - return keys; -} //end of des_createKeys - - -////////////////////////////// TEST ////////////////////////////// -function stringToHex (s) { - var r = "0x"; - var hexes = new Array ("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"); - for (var i=0; i> 4] + hexes [s.charCodeAt(i) & 0xf];} - return r; } - -function hexToString (h) { - var r = ""; - for (var i= (h.substr(0, 2)=="0x")?2:0; i> init_msg"); - //console.log("RQ (" + RQ.length + ") " + RQ); + console.log("RQ (" + RQ.length + ") " + RQ); switch (RFB.state) { @@ -151,14 +151,7 @@ init_msg: function () { break; case 'Security' : - if (RFB.version == 3.3) { - if (RQ.length < 4) { - RFB.updateState('reset', "Invalid security frame"); - return; - } - RFB.auth_scheme = RQ.shift32(); - console.log("auth_scheme: " + RFB.auth_scheme); - } else if (RFB.version == 3.8) { + if (RFB.version == 3.8) { var num_types = RQ.shift8(); if (num_types == 0) { var strlen = RQ.shift32(); @@ -168,11 +161,17 @@ init_msg: function () { } var types = RQ.shiftBytes(num_types); if ((types[0] != 1) && (types[0] != 2)) { - RFB.updateState('failed', "Disconnected: invalid security type list: " + types); + RFB.updateState('failed', "Disconnected: invalid security types list: " + types); return; } RFB.auth_scheme = types[0]; RFB.send_array([RFB.auth_scheme]); + } else if (RFB.version == 3.3) { + if (RQ.length < 4) { + RFB.updateState('failed', "Invalid security frame"); + return; + } + RFB.auth_scheme = RQ.shift32(); } RFB.updateState('Authentication', "Authenticating using scheme: " + RFB.auth_scheme); // Fall through @@ -201,8 +200,7 @@ init_msg: function () { var challenge = RQ.shiftBytes(16); console.log("Password: " + RFB.password); console.log("Challenge: " + challenge + " (" + challenge.length + ")"); - passwd = RFB.passwdTwiddle(RFB.password); - response = des(passwd, challenge, 1); + var response = RFB.DES(RFB.password, challenge); console.log("Response: " + response + " (" + response.length + ")"); RFB.send_array(response); @@ -215,8 +213,8 @@ init_msg: function () { break; case 'SecurityResult' : - if (RQ.length != 4) { - RFB.updateState('reset', "Invalid VNC auth response"); + if (RQ.length < 4) { + RFB.updateState('failed', "Invalid VNC auth response"); return; } var resp = RQ.shift32(); @@ -225,7 +223,13 @@ init_msg: function () { RFB.updateState('ServerInitialisation', "Authentication OK"); break; case 1: // failed - RFB.updateState('reset', "Authentication failed"); + if (RFB.version == 3.8) { + var reason_len = RQ.shift32(); + var reason = RQ.shiftStr(reason_len); + RFB.updateState('failed', reason); + } else if (RFB.version == 3.3) { + RFB.updateState('failed', "Authentication failed"); + } return; case 2: // too-many RFB.updateState('failed', "Disconnected: too many auth attempts"); @@ -236,7 +240,7 @@ init_msg: function () { case 'ServerInitialisation' : if (RQ.length < 24) { - RFB.updateState('reset', "Invalid server initialisation"); + RFB.updateState('failed', "Invalid server initialisation"); return; } @@ -796,22 +800,17 @@ send_array: function (arr) { } }, -/* Mirror bits of each character and return as array */ -passwdTwiddle: function (passwd) { - var arr; - arr = []; - for (var i=0; i< passwd.length; i++) { - var c = passwd.charCodeAt(i); - arr.push( ((c & 0x80) >> 7) + - ((c & 0x40) >> 5) + - ((c & 0x20) >> 3) + - ((c & 0x10) >> 1) + - ((c & 0x08) << 1) + - ((c & 0x04) << 3) + - ((c & 0x02) << 5) + - ((c & 0x01) << 7) ); +DES: function (password, challenge) { + var passwd = []; + var response = challenge.slice(); + for (var i=0; i < password.length; i++) { + passwd.push(password.charCodeAt(i)); } - return arr; + + DES.setKeys(passwd); + DES.encrypt(response, 0, response, 0); + DES.encrypt(response, 8, response, 8); + return response; }, flushClient: function () {