<script language="JavaScript">
// The LearningOnline Network with CAPA
// Encryption Routines according to Data Encryption Standard DES
// Federal Information Processing Standards Publication 46-2 (1993 Dec 30)
//
// $Id: londes.js,v 1.5 2002/03/23 11:59:22 www Exp $
//
// Copyright Michigan State University Board of Trustees
//
// This file is part of the LearningOnline Network with CAPA (LON-CAPA).
//
// LON-CAPA is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// LON-CAPA 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. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with LON-CAPA; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// /home/httpd/html/adm/gpl.txt
//
// http://www.lon-capa.org/
//
// JavaScript Implementation by Gerd Kortemeyer
// 1997,06/27/00,06/28,03/23/02 Gerd Kortemeyer
// Global variables
// Array of integers with i-th bit set
var bit=new Array(31);
// Initial permutation IP for right part
var riparr=new Array(31);
// Inverse permutation IP-1
var liiparr=new Array(31);
var uiiparr=new Array(31);
// Key vectors
var uk=new Array(16);
var lk=new Array(16);
// Upper- and lower 32-bit of external key
var uextkey=0;
var lextkey=0;
// Upper- and lower 32-bit of block
var ublock=0;
var lblock=0;
// Upper and lower 24 bit of expanded right vector
var lexpand=0;
var uexpand=0;
// S-box array
var sbarr=new Array(511);
// E expansion
var etarr=new Array(47);
// P permutation
var pparr=new Array(31);
// r- and l-vector
var rv=0;
var lv=0;
// Blocks of data for text
var b0=0;
var b1=0;
var b2=0;
var b3=0;
// Text variable
var text="";
// Function to AND with bit i
function andbit(value,i) {
return value&bit[i];
}
// General OR function
function orvalue(a,b) {
return a|b;
}
// Function to OR with bit i
function orbit(value,i) {
return orvalue(value,bit[i]);
}
// Initialize table arrays and perform self test
function init() {
window.status="Initializing ...";
var rip="58504234261810 260524436282012 462544638302214 664564840322416 8";
var iip=" 8162432 7152331 6142230 5132129 4122028 3111927 2101826 1 91725";
var sb
sb ="14 413 1 21511 8 310 612 5 9 0 7";
sb+=" 015 7 414 213 110 61211 9 5 3 8";
sb+=" 4 114 813 6 2111512 9 7 310 5 0";
sb+="1512 8 2 4 9 1 7 511 31410 0 613";
sb+="15 1 814 611 3 4 9 7 21312 0 510";
sb+=" 313 4 715 2 81412 0 110 6 911 5";
sb+=" 014 71110 413 1 5 812 6 9 3 215";
sb+="13 810 1 315 4 211 6 712 0 514 9";
sb+="10 0 914 6 315 5 11312 711 4 2 8";
sb+="13 7 0 9 3 4 610 2 8 514121115 1";
sb+="13 6 4 9 815 3 011 1 212 51014 7";
sb+=" 11013 0 6 9 8 7 41514 311 5 212";
sb+=" 71314 3 0 6 910 1 2 8 51112 415";
sb+="13 811 5 615 0 3 4 7 212 11014 9";
sb+="10 6 9 01211 71315 1 314 5 2 8 4";
sb+=" 315 0 610 113 8 9 4 51112 7 214";
sb+=" 212 4 1 71011 6 8 5 31513 014 9";
sb+="1411 212 4 713 1 5 01510 3 9 8 6";
sb+=" 4 2 1111013 7 815 912 5 6 3 014";
sb+="11 812 7 114 213 615 0 910 4 5 3";
sb+="12 11015 9 2 6 8 013 3 414 7 511";
sb+="1015 4 2 712 9 5 6 11314 011 3 8";
sb+=" 91415 5 2 812 3 7 0 410 11311 6";
sb+=" 4 3 212 9 515101114 1 7 6 0 813";
sb+=" 411 21415 0 813 312 9 7 510 6 1";
sb+="13 011 7 4 9 11014 3 512 215 8 6";
sb+=" 1 4111312 3 7141015 6 8 0 5 9 2";
sb+=" 61113 8 1 410 7 9 5 01514 2 312";
sb+="13 2 8 4 61511 110 9 314 5 012 7";
sb+=" 11513 810 3 7 412 5 611 014 9 2";
sb+=" 711 4 1 91214 2 0 6101315 3 5 8";
sb+=" 2 114 7 410 8131512 9 0 3 5 611";
var et
et ="32 1 2 3 4 5 4 5 6 7 8 9 8 910111213121314151617";
et+="1617181920212021222324252425262728292829303132 1";
var pp="16 7202129122817 1152326 5183110 2 824143227 3 9191330 62211 425";
bit[0]=1;
for (var i=1; i<=31;i++) { bit[i]=bit[i-1]<<1; }
for (i=0; i<=31;i++) {
riparr[i]=parseInt(rip.substring(i*2,i*2+2));
pparr[i]=parseInt(pp.substring(i*2,i*2+2));
}
for (i=0;i<=15;i++) {
liiparr[i]=parseInt(iip.substring(i*2,i*2+2));
uiiparr[i]=parseInt(iip.substring(32+i*2,32+i*2+2));
}
for (i=0;i<=511;i++) {
sbarr[i]=parseInt(sb.substring(i*2,i*2+2));
}
for (i=0;i<=47;i++) {
etarr[i]=parseInt(et.substring(i*2,i*2+2));
}
// Selftest
window.status="Self test";
// Primitive test, "Cryptography: A New Dimension in Computer Security"
// C.H. Meyer, S.M. Matyas, John Wiley and Sons, 1982, pg. 160
uextkey=0x1234567;
lextkey=orbit(0x9abcdef,31);
ublock=uextkey;
lblock=lextkey;
ip();
if (hexstring(lv)!='cc00ccff') { alert("IP failed: lv."); }
if (hexstring(rv)!='f0aaf0aa') { alert("IP failed: rv."); }
initkeys();
if (hexstring(uk[1])!='000b0267') { alert("Key generation failed: uk"); }
if (hexstring(lk[1])!='009b49a5') { alert("Key generation failed: lk"); }
stage(1);
if (hexstring(uexpand)!='007a1555') { alert("E failed: u"); }
if (hexstring(lexpand)!='007a1555') { alert("E failed: l"); }
if (hexstring(rv)!='921c209c') { alert("Stage 1 failed"); }
// According to National Bureau of Standards, Special Publication 500-20,
// "Validating the Correctness of Hardware Implementations of the
// NBS Data Encryption Standard", Rev. Sep. 1980.
// PC-1 and PC-2 test
ublock=0;
lblock=0;
uextkey=0x1010101;
lextkey=0x1010102;
initkeys();
encrypt();
var st=hexstring(ublock);
st+=hexstring(lblock);
if (st!="869efd7f9f265a09") {
st+=": failed PC-1 and PC-2 test!";
alert(st);
}
window.status="Self test .";
// According to NBS 500-20 IP and E test
ublock=orbit(0x66b40b4,28);
lblock=orbit(0xaba4bd6,30);
uextkey=0x1010101;
lextkey=0x1010101;
initkeys();
encrypt();
var st=hexstring(ublock);
st+=hexstring(lblock);
if (st!="0000000000000001") {
st+=": failed IP and E test!";
alert(st);
}
window.status="Self test ..";
// According to NBS 500-20 ptest
ublock=0;
lblock=0;
uextkey=orbit(0x29116,28);
lextkey=orbit(orbit(0x8100101,28),31);
initkeys();
encrypt();
var st=hexstring(ublock);
st+=hexstring(lblock);
if (st!="1aeac39a61f0a464") {
st+=": failed ptest!";
alert(st);
}
window.status="Self test ...";
// According to NBS 500-20 S-box test
ublock=orbit(orbit(0x553228,28),29);
lblock=orbit(orbit(0xd6f295a,29),30);
var orgu=ublock;
var orgl=lblock;
uextkey=orbit(0xc587f1c,28);
lextkey=orbit(0x3924fef,28);
initkeys();
encrypt();
var st=hexstring(ublock);
st+=hexstring(lblock);
if (st!="63fac0d034d9f793") {
st+=": failed S-box test!";
alert(st);
}
window.status="Self test ....";
// Decryption test
decrypt();
if (ublock!=orgu) { alert("Decryption failed for ublock."); }
if (lblock!=orgl) { alert("Decryption failed for lblock."); }
window.status="Self test .....";
// Reset keys
uextkey=0;
lextkey=0;
window.status="Ready.";
}
// Return a string with hex-representation of integer
function hexstring(i) {
var hstr="";
var hchr="0123456789abcdef";
for (var k=28; k>=0; k=k-4) {
j=0;
for (var m=0; m<=3; m++) { if (andbit(i,k+m)!=0) { j=orbit(j,m); } }
hstr+=hchr.substring(j,j+1);
}
return(hstr);
}
// Shift a 28-bit register one time
function shift(sreg) {
var bit27=andbit(sreg,0)<<27;
return (sreg>>1)|bit27;
}
// Initialize key-arrays according to uextkey and lextkey
function initkeys() {
// Constants
var celements="574941332517 9 158504234261810 259514335271911 360524436";
var delements="63554739312315 762544638302214 661534537292113 5282012 4";
var lkelements="14171124 1 5 32815 62110231912 426 816 7272013 2";
var ukelements="415231374755304051453348444939563453464250362932";
var shifttimes="1122222212222221";
// PC-2 order
var ukarr=new Array(23);
var lkarr=new Array(23);
for (i=0;i<=23;i++) {
ukarr[i]=parseInt(ukelements.substring(i*2,i*2+2));
lkarr[i]=parseInt(lkelements.substring(i*2,i*2+2));
}
// Initialize c and d
var bt;
var c=0;
var d=0;
for (var i=0; i<=27;i++) {
bt=parseInt(celements.substring(i*2,i*2+2));
if (bt<=32) {
if (andbit(uextkey,31-(bt-1)) != 0) { c=orbit(c,i); }
} else {
if (andbit(lextkey,31-(bt-33)) != 0) { c=orbit(c,i); }
}
bt=parseInt(delements.substring(i*2,i*2+2));
if (bt<=32) {
if (andbit(uextkey,31-(bt-1)) != 0) { d=orbit(d,i); }
} else {
if (andbit(lextkey,31-(bt-33)) != 0) { d=orbit(d,i); }
}
}
// Initialize the k vectors
for (i=1;i<=16;i++) {
// Shift c and d
if (shifttimes.substring(i-1,i)=='1') {
c=shift(c);
d=shift(d);
} else {
c=shift(shift(c));
d=shift(shift(d));
}
uk[i]=0;
lk[i]=0;
for (j=0; j<=23;j++) {
if (andbit(d,ukarr[j]-29)!=0) { lk[i]=orbit(lk[i],23-j); }
if (andbit(c,lkarr[j]-1)!=0) { uk[i]=orbit(uk[i],23-j); }
}
}
}
// Initial permutation of ublock and lblock into rv and lv
function ip() {
var bt;
rv=0;
lv=0;
for (var i=0; i<=31;i++) {
bt=riparr[i];
if (bt<=32) {
if (andbit(lblock,bt-1) != 0) { rv=orbit(rv,i); }
} else {
if (andbit(ublock,bt-33) != 0) { rv=orbit(rv,i); }
}
if (bt<=33) {
if (andbit(lblock,bt-2) != 0) { lv=orbit(lv,i); }
} else {
if (andbit(ublock,bt-34) != 0) { lv=orbit(lv,i); }
}
}
}
// Inverse Initial Permutation IP-1, input rv,lv, output lblock,ublock
function invip() {
var bt;
ublock=0;
lblock=0;
for (var i=0; i<=15;i++) {
bt=liiparr[i];
if (andbit(rv,bt-1) != 0) { lblock=orbit(lblock,i*2); }
if (andbit(lv,bt-1) != 0) { lblock=orbit(lblock,i*2+1); }
bt=uiiparr[i];
if (andbit(rv,bt-1) != 0) { ublock=orbit(ublock,i*2); }
if (andbit(lv,bt-1) != 0) { ublock=orbit(ublock,i*2+1); }
}
}
// Expansion of right vector according to E, input rv
function expand() {
var bt;
uexpand=0;
lexpand=0;
for (var i=0; i<=23; i++) {
bt=etarr[i];
if (andbit(rv,bt-1)!=0) { lexpand=orbit(lexpand,i); }
}
for (i=24; i<=47; i++) {
bt=etarr[i];
if (andbit(rv,bt-1)!=0) { uexpand=orbit(uexpand,i-24); }
}
}
// Permutes rv according to P, input/output rv
function permute() {
var prv=rv;
rv=0;
for (var i=0; i<=31; i++) {
if (andbit(prv,31-(pparr[i]-1))!=0) { rv=orbit(rv,31-i); }
}
}
// Performs stage si of the encryption, input/output rv
function stage(si) {
expand();
var uadd=uexpand^uk[si];
var ladd=lexpand^lk[si];
rv=0;
var ks=0;
for (var ki=42;ki>=24;ki=ki-6) {
rv=rv<<4;
var i=0;
if (andbit(uadd,ki-24)!=0) { i=orbit(i,0); }
if (andbit(uadd,ki-19)!=0) { i=orbit(i,1); }
var j=0;
for (var kj=0; kj<=3; kj++) {
if (andbit(uadd,ki-23+kj)!=0) { j=orbit(j,kj); }
}
rv=orvalue(rv,sbarr[ks*64+i*16+j]);
ks++;
}
for (var ki=18;ki>=0;ki=ki-6) {
rv=rv<<4;
var i=0;
if (andbit(ladd,ki) !=0) { i=orbit(i,0); }
if (andbit(ladd,ki+5)!=0) { i=orbit(i,1); }
var j=0;
for (var kj=0; kj<=3; kj++) {
if (andbit(ladd,ki+1+kj)!=0) { j=orbit(j,kj); }
}
rv=orvalue(rv,sbarr[ks*64+i*16+j]);
ks++;
}
permute();
}
// Encryption
function encrypt() {
ip();
for (var i=1; i<=16; i++) {
var prv=rv;
stage(i);
rv=rv^lv;
lv=prv;
}
invip();
}
// Decryption
function decrypt() {
ip();
for (var i=16; i>=1; i--) {
var prv=rv;
stage(i);
rv=rv^lv;
lv=prv;
}
invip();
}
// Put text into b0,b1,b2,b3
function block(text) {;
var equiv= "*+ -./0123456789......@";
equiv+="ABCDEFGHIJKLMNOPQRSTUVWXYZ _ ";
equiv+="abcdefghijklmnopqrstuvwxyz";
var tl=text.length;
if (tl>=16) { tl=15; }
text+=" ";
text=escape(text);
var i;
var c;
var conv='';
var j=0;
for (i=0;i<15;i++) {
if (text.charAt(j)=='%') {
conv+=text.charAt(j+1)+text.charAt(j+2);
j=j+3;
} else {
c=hexstring(42+equiv.indexOf(text.charAt(j)));
conv+=c.substr(6,2);
j++;
}
}
b3=tl*bit[24]+parseInt("0x"+conv.substr(0,6));
b2=parseInt("0x"+conv.substr(6,8));
b1=parseInt("0x"+conv.substr(14,8));
b0=parseInt("0x"+conv.substr(22,8));
}
function crypted(text) {
block(text);
lblock=b0;
ublock=b1;
encrypt();
b0=lblock;
b1=ublock;
lblock=b2;
ublock=b3;
encrypt();
b2=lblock;
b3=ublock;
return(hexstring(b3)+hexstring(b2)+hexstring(b1)+hexstring(b0));
}
</script>
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>