Mega Code Archive

 
Categories / JavaScript DHTML / Security
 

RC4 Encryption in JavaScript

<html>   <head>     <!--       CryptoMX Tools       Copyright (C) 2004 - 2006 Derek Buitenhuis       This program 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.       This program 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 this program; if not, write to the Free Software       Found     -->     <title>RC4 Encryption</title>   </head>   <body>     <script language="JavaScript"> var dg='' function makeArray(n) {  for (var i=1; i<=n; i++) {   this[i]=0  }  return this } function rc4(key, text) {  var i, x, y, t, x2;  status("rc4")  s=makeArray(0);  for (i=0; i<256; i++) {   s[i]=i  }  y=0  for (x=0; x<256; x++) {   y=(key.charCodeAt(x % key.length) + s[x] + y) % 256   t=s[x]; s[x]=s[y]; s[y]=t  }  x=0;  y=0;  var z=""  for (x=0; x<text.length; x++) {   x2=x % 256   y=( s[x2] + y) % 256   t=s[x2]; s[x2]=s[y]; s[y]=t   z+= String.fromCharCode((text.charCodeAt(x) ^ s[(s[x2] + s[y]) % 256]))  }  return z } function badd(a,b) { // binary add  var r=''  var c=0  while(a || b) {   c=chop(a)+chop(b)+c   a=a.slice(0,-1); b=b.slice(0,-1)   if(c & 1) {    r="1"+r   } else {    r="0"+r   }   c>>=1  }  if(c) {r="1"+r}  return r } function chop(a) {  if(a.length) {   return parseInt(a.charAt(a.length-1))  } else {   return 0  } } function bsub(a,b) { // binary subtract  var r=''  var c=0  while(a) {   c=chop(a)-chop(b)-c   a=a.slice(0,-1); b=b.slice(0,-1)   if(c==0) {    r="0"+r   }   if(c == 1) {    r="1"+r    c=0   }   if(c == -1) {    r="1"+r    c=1   }   if(c==-2) {    r="0"+r    c=1   }  }  if(b || c) {return ''}  return bnorm(r) } function bnorm(r) { // trim off leading 0s  var i=r.indexOf('1')  if(i == -1) {   return '0'  } else {   return r.substr(i)  } } function bmul(a,b) { // binary multiply  var r=''; var p=''  while(a) {   if(chop(a) == '1') {    r=badd(r,b+p)   }   a=a.slice(0,-1)   p+='0'  }  return r; } function bmod(a,m) { // binary modulo  return bdiv(a,m).mod } function bdiv(a,m) { // binary divide & modulo  // this.q = quotient this.mod=remainder  var lm=m.length, al=a.length  var p='',d  this.q=''  for(n=0; n<al; n++) {   p=p+a.charAt(n);   if(p.length<lm || (d=bsub(p,m)) == '') {    this.q+='0'   } else {    if(this.q.charAt(0)=='0') {     this.q='1'    } else {     this.q+="1"    }    p=d   }  }  this.mod=bnorm(p)  return this } function bmodexp(x,y,m) { // binary modular exponentiation  var r='1'  status("bmodexp "+x+" "+y+" "+m)  while(y) {   if(chop(y) == 1) {    r=bmod(bmul(r,x),m)   }   y=y.slice(0,y.length-1)   x=bmod(bmul(x,x),m)  }  return bnorm(r) } function modexp(x,y,m) { // modular exponentiation  // convert packed bits (text) into strings of 0s and 1s  return b2t(bmodexp(t2b(x),t2b(y),t2b(m))) } function i2b(i) { // convert integer to binary  var r=''  while(i) {   if(i & 1) { r="1"+r} else {r="0"+r}   i>>=1;  }  return r? r:'0' } function t2b(s) {  var r=''  if(s=='') {return '0'}  while(s.length) {   var i=s.charCodeAt(0)   s=s.substr(1)   for(n=0; n<8; n++) {    r=((i & 1)? '1':'0') + r    i>>=1;   }  }  return bnorm(r) } function b2t(b) {  var r=''; var v=0; var m=1  while(b.length) {   v|=chop(b)*m   b=b.slice(0,-1)   m<<=1   if(m==256 || b=='') {    r+=String.fromCharCode(v)    v=0; m=1   }  }  return r } b64s='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"' function textToBase64(t) {  status("t 2 b64")  var r=''; var m=0; var a=0; var tl=t.length-1; var c  for(n=0; n<=tl; n++) {   c=t.charCodeAt(n)   r+=b64s.charAt((c << m | a) & 63)   a = c >> (6-m)   m+=2   if(m==6 || n==tl) {    r+=b64s.charAt(a)    if((n%45)==44) {r+="\n"}    m=0    a=0   }  }  return r } function base64ToText(t) {  status("b64 2 t")  var r=''; var m=0; var a=0; var c  for(n=0; n<t.length; n++) {   c=b64s.indexOf(t.charAt(n))   if(c >= 0) {    if(m) {     r+=String.fromCharCode((c << (8-m))&255 | a)    }    a = c >> m    m+=2    if(m==8) { m=0 }   }  }  return r } function rand(n) {  return Math.floor(Math.random() * n) } function rstring(s,l) {  var r=""  var sl=s.length  while(l-->0) {   r+=s.charAt(rand(sl))  }  //status("rstring "+r)  return r } function key2(k) {  var l=k.length  var kl=l  var r=''  while(l--) {   r+=k.charAt((l*3)%kl)  }  return r } function rsaEncrypt(keylen,key,mod,text) {  // I read that rc4 with keys larger than 256 bytes doesn't significantly  // increase the level of rc4 encryption because it's sbuffer is 256 bytes  // makes sense to me, but what do i know...  status("encrypt")  if(text.length >= keylen) {   var sessionkey=rc4(rstring(text,keylen),rstring(text,keylen))   // session key must be less than mod, so mod it   sessionkey=b2t(bmod(t2b(sessionkey),t2b(mod)))   alert("sessionkey="+sessionkey)   // return the rsa encoded key and the encrypted text   // i'm double encrypting because it would seem to me to   // lessen known-plaintext attacks, but what do i know   return modexp(sessionkey,key,mod) +    rc4(key2(sessionkey),rc4(sessionkey,text))  } else {   // don't need a session key   return modexp(text,key,mod)  } } function rsaDecrypt(keylen,key,mod,text) {  status("decrypt")  if(text.length <= keylen) {   return modexp(text,key,mod)  } else {   // sessionkey is first keylen bytes   var sessionkey=text.substr(0,keylen)   text=text.substr(keylen)   // un-rsa the session key   sessionkey=modexp(sessionkey,key,mod)   alert("sessionkey="+sessionkey)   // double decrypt the text   return rc4(sessionkey,rc4(key2(sessionkey,text),text))  } } function trim2(d) { return d.substr(0,d.lastIndexOf('1')+1) } function bgcd(u,v) { // return greatest common divisor  // algorythm from http://algo.inria.fr/banderier/Seminar/Vallee/index.html  var d, t  while(1) {   d=bsub(v,u)   //alert(v+" - "+u+" = "+d)   if(d=='0') {return u}   if(d) {    if(d.substr(-1)=='0') {     v=d.substr(0,d.lastIndexOf('1')+1) // v=(v-u)/2^val2(v-u)    } else v=d   } else {    t=v; v=u; u=t // swap u and v   }  } } function isPrime(p) {  var n,p1,p12,t  p1=bsub(p,'1')  t=p1.length-p1.lastIndexOf('1')  p12=trim2(p1)  for(n=0; n<2; n+=mrtest(p,p1,p12,t)) {   if(n<0) return 0  }  return 1 } function mrtest(p,p1,p12,t) {  // Miller-Rabin test from forum.swathmore.edu/dr.math/  var n,a,u   a='1'+rstring('01',Math.floor(p.length/2)) // random a   //alert("mrtest "+p+", "+p1+", "+a+"-"+p12)   u=bmodexp(a,p12,p)   if(u=='1') {return 1}   for(n=0;n<t;n++) {    u=bmod(bmul(u,u),p)    //dg+=u+" "    if(u=='1') return -100    if(u==p1) return 1   }   return -100 } pfactors='11100011001110101111000110001101'  // this number is 3*5*7*11*13*17*19*23*29*31*37 function prime(bits) {  // return a prime number of bits length  var p='1'+rstring('001',bits-2)+'1'  while( ! isPrime(p)) {   p=badd(p,'10'); // add 2  }  alert("p is "+p)  return p } function genkey(bits) {  q=prime(bits)  do {   p=q   q=prime(bits)  } while(bgcd(p,q)!='1')  p1q1=bmul(bsub(p,'1'),bsub(q,'1'))  // now we need a d, e,  and an n so that:  //  p1q1*n-1=de  -> bmod(bsub(bmul(d,e),'1'),p1q1)='0'  // or more specifically an n so that d & p1q1 are rel prime and factor e  n='1'+rstring('001',Math.floor(bits/3)+2)  alert('n is '+n)  factorMe=badd(bmul(p1q1,n),'1')  alert('factor is '+factorMe)  //e=bgcd(factorMe,p1q1)  //alert('bgcd='+e)  e='1'  // is this always 1?  //r=bdiv(factorMe,e)  //alert('r='+r.q+" "+r.mod)  //if(r.mod != '0') {alert('Mod Error!')}  //factorMe=r.q  d=bgcd(factorMe,'11100011001110101111000110001101')  alert('d='+d)  if(d == '1' && e == '1') {alert('Factoring failed '+factorMe+' p='+p+' q='+q)}  e=bmul(e,d)  r=bdiv(factorMe,d)  d=r.q  if(r.mod != '0') {alert('Mod Error 2!')}  this.mod=b2t(bmul(p,q))  this.pub=b2t(e)  this.priv=b2t(d) } function status(a) { }//alert(a)}     </script>               <script language="JavaScript">                 <!--                   function rc4encrypt() {                      document.rc4.text.value=textToBase64(rc4(document.rc4.key.value,document.rc4.text.value))                   }                   function rc4decrypt() {                      document.rc4.text.value=(rc4(document.rc4.key.value,base64ToText(document.rc4.text.value)))                   }                 -->               </script>     <h3>RC4 Encryption (input text for both field):</h3>     <form method="POST" name="rc4">       <div align="center">         <table border="0">           <tr>             <td align="right">               Key:             </td>             <td>               <input type="text" size="60" name="key" value="">             </td>           </tr>           <tr>             <td align="right">               Text:             </td>             <td>               <textarea name="text" rows="6" cols="70"></textarea>             </td>           </tr>           <tr>             <td>               <p align="center">                 <input type="button" name="B1" value="Encrypt" onclick="rc4encrypt()">                 <input type="button" name="B2" value="Decrypt" onclick="rc4decrypt()">               </p>             </td>           </tr>         </table>       </div>     </form>   </body> </html>