File:  [LON-CAPA] / loncom / auth / londes.js
Revision 1.5: download - view: text, annotated - select for diffs
Sat Mar 23 11:59:22 2002 UTC (22 years, 3 months ago) by www
Branches: MAIN
CVS tags: HEAD
All bitwise functions except '^' already separated out, has self test.

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>