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>