JavaScript DHTML/Security/RC4 Encryption
RC4 Encryption in JavaScript
<source lang="html4strict">
<html>
<head> <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"> </script>
RC4 Encryption (input text for both field):
<form method="POST" name="rc4">
Key: |
<input type="text" size="60" name="key" value=""> |
Text: |
<textarea name="text" rows="6" cols="70"></textarea> |
<input type="button" name="B1" value="Encrypt" onclick="rc4encrypt()"> <input type="button" name="B2" value="Decrypt" onclick="rc4decrypt()"> |
</form> </body>
</html>
</source>