Annotation of loncom/auth/londes.js, revision 1.4
1.1 www 1: <script language="JavaScript">
2: // The LearningOnline Network with CAPA
3: // Encryption Routines according to Data Encryption Standard DES
4: // Federal Information Processing Standards Publication 46-2 (1993 Dec 30)
1.2 www 5: //
1.3 www 6: // $Id: londes.js,v 1.2 2001/11/29 19:12:44 www Exp $
1.2 www 7: //
8: // Copyright Michigan State University Board of Trustees
9: //
10: // This file is part of the LearningOnline Network with CAPA (LON-CAPA).
11: //
12: // LON-CAPA is free software; you can redistribute it and/or modify
13: // it under the terms of the GNU General Public License as published by
14: // the Free Software Foundation; either version 2 of the License, or
15: // (at your option) any later version.
16: //
17: // LON-CAPA is distributed in the hope that it will be useful,
18: // but WITHOUT ANY WARRANTY; without even the implied warranty of
19: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20: // GNU General Public License for more details.
21: //
22: // You should have received a copy of the GNU General Public License
23: // along with LON-CAPA; if not, write to the Free Software
24: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25: //
26: // /home/httpd/html/adm/gpl.txt
27: //
28: // http://www.lon-capa.org/
29: //
1.1 www 30: // JavaScript Implementation by Gerd Kortemeyer
1.3 www 31: // 1997,06/27/00,06/28,03/23/02 Gerd Kortemeyer
1.1 www 32:
33: // Global variables
34:
35: // Array of integers with i-th bit set
36: var bit=new Array(31);
37: // Initial permutation IP for right part
38: var riparr=new Array(31);
39: // Inverse permutation IP-1
40: var liiparr=new Array(31);
41: var uiiparr=new Array(31);
42: // Key vectors
43: var uk=new Array(16);
44: var lk=new Array(16);
45: // Upper- and lower 32-bit of external key
46: var uextkey=0;
47: var lextkey=0;
48: // Upper- and lower 32-bit of block
49: var ublock=0;
50: var lblock=0;
51: // Upper and lower 24 bit of expanded right vector
52: var lexpand=0;
53: var uexpand=0;
54: // S-box array
55: var sbarr=new Array(511);
56: // E expansion
57: var etarr=new Array(47);
58: // P permutation
59: var pparr=new Array(31);
60: // r- and l-vector
61: var rv=0;
62: var lv=0;
63: // Blocks of data for text
64: var b0=0;
65: var b1=0;
66: var b2=0;
67: var b3=0;
68: // Text variable
69: var text="";
70:
1.3 www 71:
72: // Function to AND with bit i
73:
74: function andbit(value,i) {
75: return value&bit[i];
76: }
77:
78: // Function to OR with bit i
79:
80: function orbit(value,i) {
81: return value|bit[i];
82: }
83:
1.1 www 84: // Initialize table arrays and perform self test
85:
86: function init() {
87: window.status="Initializing ...";
88: var rip="58504234261810 260524436282012 462544638302214 664564840322416 8";
89: var iip=" 8162432 7152331 6142230 5132129 4122028 3111927 2101826 1 91725";
90: var sb
91: sb ="14 413 1 21511 8 310 612 5 9 0 7";
92: sb+=" 015 7 414 213 110 61211 9 5 3 8";
93: sb+=" 4 114 813 6 2111512 9 7 310 5 0";
94: sb+="1512 8 2 4 9 1 7 511 31410 0 613";
95: sb+="15 1 814 611 3 4 9 7 21312 0 510";
96: sb+=" 313 4 715 2 81412 0 110 6 911 5";
97: sb+=" 014 71110 413 1 5 812 6 9 3 215";
98: sb+="13 810 1 315 4 211 6 712 0 514 9";
99: sb+="10 0 914 6 315 5 11312 711 4 2 8";
100: sb+="13 7 0 9 3 4 610 2 8 514121115 1";
101: sb+="13 6 4 9 815 3 011 1 212 51014 7";
102: sb+=" 11013 0 6 9 8 7 41514 311 5 212";
103: sb+=" 71314 3 0 6 910 1 2 8 51112 415";
104: sb+="13 811 5 615 0 3 4 7 212 11014 9";
105: sb+="10 6 9 01211 71315 1 314 5 2 8 4";
106: sb+=" 315 0 610 113 8 9 4 51112 7 214";
107: sb+=" 212 4 1 71011 6 8 5 31513 014 9";
108: sb+="1411 212 4 713 1 5 01510 3 9 8 6";
109: sb+=" 4 2 1111013 7 815 912 5 6 3 014";
110: sb+="11 812 7 114 213 615 0 910 4 5 3";
111: sb+="12 11015 9 2 6 8 013 3 414 7 511";
112: sb+="1015 4 2 712 9 5 6 11314 011 3 8";
113: sb+=" 91415 5 2 812 3 7 0 410 11311 6";
114: sb+=" 4 3 212 9 515101114 1 7 6 0 813";
115: sb+=" 411 21415 0 813 312 9 7 510 6 1";
116: sb+="13 011 7 4 9 11014 3 512 215 8 6";
117: sb+=" 1 4111312 3 7141015 6 8 0 5 9 2";
118: sb+=" 61113 8 1 410 7 9 5 01514 2 312";
119: sb+="13 2 8 4 61511 110 9 314 5 012 7";
120: sb+=" 11513 810 3 7 412 5 611 014 9 2";
121: sb+=" 711 4 1 91214 2 0 6101315 3 5 8";
122: sb+=" 2 114 7 410 8131512 9 0 3 5 611";
123: var et
124: et ="32 1 2 3 4 5 4 5 6 7 8 9 8 910111213121314151617";
125: et+="1617181920212021222324252425262728292829303132 1";
126: var pp="16 7202129122817 1152326 5183110 2 824143227 3 9191330 62211 425";
127: bit[0]=1;
128: for (var i=1; i<=31;i++) { bit[i]=bit[i-1]<<1; }
129: for (i=0; i<=31;i++) {
130: riparr[i]=parseInt(rip.substring(i*2,i*2+2));
131: pparr[i]=parseInt(pp.substring(i*2,i*2+2));
132: }
133: for (i=0;i<=15;i++) {
134: liiparr[i]=parseInt(iip.substring(i*2,i*2+2));
135: uiiparr[i]=parseInt(iip.substring(32+i*2,32+i*2+2));
136: }
137: for (i=0;i<=511;i++) {
138: sbarr[i]=parseInt(sb.substring(i*2,i*2+2));
139: }
140: for (i=0;i<=47;i++) {
141: etarr[i]=parseInt(et.substring(i*2,i*2+2));
142: }
143:
1.4 ! www 144: // Selftest
! 145: window.status="Self test";
! 146:
! 147: // Primitive test, "Cryptography: A New Dimension in Computer Security"
! 148: // C.H. Meyer, S.M. Matyas, John Wiley and Sons, 1982, pg. 160
! 149:
! 150: uextkey=0x1234567;
! 151: lextkey=bit[31]|0x9abcdef;
! 152: ublock=uextkey;
! 153: lblock=lextkey;
! 154: ip();
! 155: if (hexstring(lv)!='cc00ccff') { alert("IP failed: lv."); }
! 156: if (hexstring(rv)!='f0aaf0aa') { alert("IP failed: rv."); }
! 157: initkeys();
! 158: if (hexstring(uk[1])!='000b0267') { alert("Key generation failed: uk"); }
! 159: if (hexstring(lk[1])!='009b49a5') { alert("Key generation failed: lk"); }
! 160: stage(1);
! 161: if (hexstring(uexpand)!='007a1555') { alert("E failed: u"); }
! 162: if (hexstring(lexpand)!='007a1555') { alert("E failed: l"); }
! 163: if (hexstring(rv)!='921c209c') { alert("Stage 1 failed"); }
! 164:
! 165: // According to National Bureau of Standards, Special Publication 500-20,
! 166: // "Validating the Correctness of Hardware Implementations of the
! 167: // NBS Data Encryption Standard", Rev. Sep. 1980.
! 168:
! 169: // PC-1 and PC-2 test
! 170: ublock=0;
! 171: lblock=0;
! 172: uextkey=0x1010101;
! 173: lextkey=0x1010102;
! 174: initkeys();
! 175: encrypt();
! 176: var st=hexstring(ublock);
! 177: st+=hexstring(lblock);
! 178: if (st!="869efd7f9f265a09") {
! 179: st+=": failed PC-1 and PC-2 test!";
! 180: alert(st);
! 181: }
! 182: window.status="Self test .";
! 183:
! 184: // According to NBS 500-20 IP and E test
! 185: ublock=bit[28]|0x66b40b4;
! 186: lblock=bit[30]|0xaba4bd6;
! 187: uextkey=0x1010101;
! 188: lextkey=0x1010101;
! 189: initkeys();
! 190: encrypt();
! 191: var st=hexstring(ublock);
! 192: st+=hexstring(lblock);
! 193: if (st!="0000000000000001") {
! 194: st+=": failed IP and E test!";
! 195: alert(st);
! 196: }
! 197: window.status="Self test ..";
! 198:
! 199: // According to NBS 500-20 ptest
! 200: ublock=0;
! 201: lblock=0;
! 202: uextkey=bit[28]|0x29116;
! 203: lextkey=bit[31]|bit[28]|0x8100101;
! 204: initkeys();
! 205: encrypt();
! 206: var st=hexstring(ublock);
! 207: st+=hexstring(lblock);
! 208: if (st!="1aeac39a61f0a464") {
! 209: st+=": failed ptest!";
! 210: alert(st);
! 211: }
! 212: window.status="Self test ...";
! 213:
! 214: // According to NBS 500-20 S-box test
! 215: ublock=bit[28]|bit[29]|0x553228;
! 216: lblock=bit[29]|bit[30]|0xd6f295a;
! 217: var orgu=ublock;
! 218: var orgl=lblock;
! 219: uextkey=bit[28]|0xc587f1c;
! 220: lextkey=bit[28]|0x3924fef;
! 221: initkeys();
! 222: encrypt();
! 223: var st=hexstring(ublock);
! 224: st+=hexstring(lblock);
! 225: if (st!="63fac0d034d9f793") {
! 226: st+=": failed S-box test!";
! 227: alert(st);
! 228: }
! 229: window.status="Self test ....";
! 230:
! 231: // Decryption test
! 232: decrypt();
! 233: if (ublock!=orgu) { alert("Decryption failed for ublock."); }
! 234: if (lblock!=orgl) { alert("Decryption failed for lblock."); }
! 235: window.status="Self test .....";
! 236:
! 237: // Reset keys
! 238:
! 239: uextkey=0;
! 240: lextkey=0;
! 241:
1.1 www 242: window.status="Ready.";
243: }
244:
245: // Return a string with hex-representation of integer
246:
247: function hexstring(i) {
248: var hstr="";
249: var hchr="0123456789abcdef";
250: for (var k=28; k>=0; k=k-4) {
251: j=0;
1.3 www 252: for (var m=0; m<=3; m++) { if (andbit(i,k+m)!=0) { j=orbit(j,m); } }
1.1 www 253: hstr+=hchr.substring(j,j+1);
254: }
255: return(hstr);
256: }
257:
258: // Shift a 28-bit register one time
259:
260: function shift(sreg) {
1.3 www 261: var bit27=andbit(sreg,0)<<27;
1.1 www 262: return (sreg>>1)|bit27;
263: }
264:
265: // Initialize key-arrays according to uextkey and lextkey
266:
267: function initkeys() {
268: // Constants
269: var celements="574941332517 9 158504234261810 259514335271911 360524436";
270: var delements="63554739312315 762544638302214 661534537292113 5282012 4";
271: var lkelements="14171124 1 5 32815 62110231912 426 816 7272013 2";
272: var ukelements="415231374755304051453348444939563453464250362932";
273: var shifttimes="1122222212222221";
274: // PC-2 order
275: var ukarr=new Array(23);
276: var lkarr=new Array(23);
277: for (i=0;i<=23;i++) {
278: ukarr[i]=parseInt(ukelements.substring(i*2,i*2+2));
279: lkarr[i]=parseInt(lkelements.substring(i*2,i*2+2));
280: }
281: // Initialize c and d
282: var bt;
283: var c=0;
284: var d=0;
285: for (var i=0; i<=27;i++) {
286: bt=parseInt(celements.substring(i*2,i*2+2));
287: if (bt<=32) {
1.3 www 288: if (andbit(uextkey,31-(bt-1)) != 0) { c=orbit(c,i); }
1.1 www 289: } else {
1.3 www 290: if (andbit(lextkey,31-(bt-33)) != 0) { c=orbit(c,i); }
1.1 www 291: }
292: bt=parseInt(delements.substring(i*2,i*2+2));
293: if (bt<=32) {
1.3 www 294: if (andbit(uextkey,31-(bt-1)) != 0) { d=orbit(d,i); }
1.1 www 295: } else {
1.3 www 296: if (andbit(lextkey,31-(bt-33)) != 0) { d=orbit(d,i); }
1.1 www 297: }
298: }
299: // Initialize the k vectors
300: for (i=1;i<=16;i++) {
301: // Shift c and d
302: if (shifttimes.substring(i-1,i)=='1') {
303: c=shift(c);
304: d=shift(d);
305: } else {
306: c=shift(shift(c));
307: d=shift(shift(d));
308: }
309: uk[i]=0;
310: lk[i]=0;
311: for (j=0; j<=23;j++) {
1.3 www 312: if (andbit(d,ukarr[j]-29)!=0) { lk[i]=orbit(lk[i],23-j); }
313: if (andbit(c,lkarr[j]-1)!=0) { uk[i]=orbit(uk[i],23-j); }
1.1 www 314: }
315: }
316: }
317:
318: // Initial permutation of ublock and lblock into rv and lv
319:
320: function ip() {
321: var bt;
322: rv=0;
323: lv=0;
324: for (var i=0; i<=31;i++) {
325: bt=riparr[i];
326: if (bt<=32) {
1.3 www 327: if (andbit(lblock,bt-1) != 0) { rv=orbit(rv,i); }
1.1 www 328: } else {
1.3 www 329: if (andbit(ublock,bt-33) != 0) { rv=orbit(rv,i); }
1.1 www 330: }
331: if (bt<=33) {
1.3 www 332: if (andbit(lblock,bt-2) != 0) { lv=orbit(lv,i); }
1.1 www 333: } else {
1.3 www 334: if (andbit(ublock,bt-34) != 0) { lv=orbit(lv,i); }
1.1 www 335: }
336: }
337: }
338:
339: // Inverse Initial Permutation IP-1, input rv,lv, output lblock,ublock
340:
341: function invip() {
342: var bt;
343: ublock=0;
344: lblock=0;
345: for (var i=0; i<=15;i++) {
346: bt=liiparr[i];
1.3 www 347: if (andbit(rv,bt-1) != 0) { lblock=orbit(lblock,i*2); }
348: if (andbit(lv,bt-1) != 0) { lblock=orbit(lblock,i*2+1); }
1.1 www 349: bt=uiiparr[i];
1.3 www 350: if (andbit(rv,bt-1) != 0) { ublock=orbit(ublock,i*2); }
351: if (andbit(lv,bt-1) != 0) { ublock=orbit(ublock,i*2+1); }
1.1 www 352: }
353: }
354:
355: // Expansion of right vector according to E, input rv
356:
357: function expand() {
358: var bt;
359: uexpand=0;
360: lexpand=0;
361: for (var i=0; i<=23; i++) {
362: bt=etarr[i];
1.3 www 363: if (andbit(rv,bt-1)!=0) { lexpand=orbit(lexpand,i); }
1.1 www 364: }
365: for (i=24; i<=47; i++) {
366: bt=etarr[i];
1.3 www 367: if (andbit(rv,bt-1)!=0) { uexpand=orbit(uexpand,i-24); }
1.1 www 368: }
369: }
370:
371: // Permutes rv according to P, input/output rv
372:
373: function permute() {
374: var prv=rv;
375: rv=0;
376: for (var i=0; i<=31; i++) {
1.3 www 377: if (andbit(prv,31-(pparr[i]-1))!=0) { rv=orbit(rv,31-i); }
1.1 www 378: }
379: }
380:
381: // Performs stage si of the encryption, input/output rv
382:
383: function stage(si) {
384: expand();
385: var uadd=uexpand^uk[si];
386: var ladd=lexpand^lk[si];
387: rv=0;
388: var ks=0;
389: for (var ki=42;ki>=24;ki=ki-6) {
390: rv=rv<<4;
391: var i=0;
1.3 www 392: if (andbit(uadd,ki-24)!=0) { i=orbit(i,0); }
393: if (andbit(uadd,ki-19)!=0) { i=orbit(i,1); }
1.1 www 394: var j=0;
395: for (var kj=0; kj<=3; kj++) {
1.3 www 396: if (andbit(uadd,ki-23+kj)!=0) { j=orbit(j,kj); }
1.1 www 397: }
398: rv=rv|sbarr[ks*64+i*16+j];
399: ks++;
400: }
401: for (var ki=18;ki>=0;ki=ki-6) {
402: rv=rv<<4;
403: var i=0;
1.3 www 404: if (andbit(ladd,ki) !=0) { i=orbit(i,0); }
405: if (andbit(ladd,ki+5)!=0) { i=orbit(i,1); }
1.1 www 406: var j=0;
407: for (var kj=0; kj<=3; kj++) {
1.3 www 408: if (andbit(ladd,ki+1+kj)!=0) { j=orbit(j,kj); }
1.1 www 409: }
410: rv=rv|sbarr[ks*64+i*16+j];
411: ks++;
412: }
413: permute();
414: }
415:
416: // Encryption
417:
418: function encrypt() {
419: ip();
420: for (var i=1; i<=16; i++) {
421: var prv=rv;
422: stage(i);
423: rv=rv^lv;
424: lv=prv;
425: }
426: invip();
427: }
428:
429: // Decryption
430:
431: function decrypt() {
432: ip();
433: for (var i=16; i>=1; i--) {
434: var prv=rv;
435: stage(i);
436: rv=rv^lv;
437: lv=prv;
438: }
439: invip();
440: }
441:
442: // Put text into b0,b1,b2,b3
443:
444: function block(text) {;
445: var equiv= "*+ -./0123456789......@";
446: equiv+="ABCDEFGHIJKLMNOPQRSTUVWXYZ _ ";
447: equiv+="abcdefghijklmnopqrstuvwxyz";
448: var tl=text.length;
449: if (tl>=16) { tl=15; }
450: text+=" ";
451: text=escape(text);
452: var i;
453: var c;
454: var conv='';
455: var j=0;
456: for (i=0;i<15;i++) {
457: if (text.charAt(j)=='%') {
458: conv+=text.charAt(j+1)+text.charAt(j+2);
459: j=j+3;
460: } else {
461: c=hexstring(42+equiv.indexOf(text.charAt(j)));
462: conv+=c.substr(6,2);
463: j++;
464: }
465: }
466: b3=tl*bit[24]+parseInt("0x"+conv.substr(0,6));
467: b2=parseInt("0x"+conv.substr(6,8));
468: b1=parseInt("0x"+conv.substr(14,8));
469: b0=parseInt("0x"+conv.substr(22,8));
470:
471: }
472:
473: function crypted(text) {
474: block(text);
475: lblock=b0;
476: ublock=b1;
477: encrypt();
478: b0=lblock;
479: b1=ublock;
480: lblock=b2;
481: ublock=b3;
482: encrypt();
483: b2=lblock;
484: b3=ublock;
485: return(hexstring(b3)+hexstring(b2)+hexstring(b1)+hexstring(b0));
486: }
487:
488: </script>
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>