http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/js/RSA.js ---------------------------------------------------------------------- diff --git a/version22/js/RSA.js b/version22/js/RSA.js new file mode 100644 index 0000000..ff27ac6 --- /dev/null +++ b/version22/js/RSA.js @@ -0,0 +1,392 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +/* RSA API Functions */ + +var rsa_private_key=function(n) +{ + this.p=new FF(n); + this.q=new FF(n); + this.dp=new FF(n); + this.dq=new FF(n); + this.c=new FF(n); +}; + +var rsa_public_key=function(m) +{ + this.e=0; + this.n=new FF(m); +}; + +RSA= { + RFS: ROM.MODBYTES*ROM.FFLEN, + SHA256 : 32, + SHA384 : 48, + SHA512 : 64, + + HASH_TYPE:32, + +/* SHAXXX identifier strings */ + SHA256ID : [0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20], + SHA384ID : [0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30], + SHA512ID : [0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40], + + bytestohex: function(b) + { + var s=""; + var len=b.length; + var ch; + + for (var i=0;i<len;i++) + { + ch=b[i]; + s+=((ch>>>4)&15).toString(16); + s+=(ch&15).toString(16); + + } + return s; + }, + + bytestostring: function(b) + { + var s=""; + for (var i=0;i<b.length;i++) + { + s+=String.fromCharCode(b[i]); + } + return s; + }, + + stringtobytes: function(s) + { + var b=[]; + for (var i=0;i<s.length;i++) + b.push(s.charCodeAt(i)); + return b; + }, + + hashit: function(sha,A,n) + { + var R=[]; + if (sha==this.SHA256) + { + var H=new HASH256(); + if (A!=null) H.process_array(A); + if (n>=0) H.process_num(n); + R=H.hash(); + } + if (sha==this.SHA384) + { + H=new HASH384(); + if (A!=null) H.process_array(A); + if (n>=0) H.process_num(n); + R=H.hash(); + } + if (sha==this.SHA512) + { + H=new HASH512(); + if (A!=null) H.process_array(A); + if (n>=0) H.process_num(n); + R=H.hash(); + } + return R; + }, + + KEY_PAIR: function(rng,e,PRIV,PUB) + { /* IEEE1363 A16.11/A16.12 more or less */ + + // var m,r,bytes,hbytes,words,err,res=0; + var n=PUB.n.length>>1; + var t = new FF(n); + var p1=new FF(n); + var q1=new FF(n); + + for (;;) + { + + PRIV.p.random(rng); + while (PRIV.p.lastbits(2)!=3) PRIV.p.inc(1); + while (!FF.prime(PRIV.p,rng)) PRIV.p.inc(4); + + p1.copy(PRIV.p); + p1.dec(1); + + if (p1.cfactor(e)) continue; + break; + } + + for (;;) + { + PRIV.q.random(rng); + while (PRIV.q.lastbits(2)!=3) PRIV.q.inc(1); + while (!FF.prime(PRIV.q,rng)) PRIV.q.inc(4); + + q1.copy(PRIV.q); + q1.dec(1); + + if (q1.cfactor(e)) continue; + break; + } + + PUB.n=FF.mul(PRIV.p,PRIV.q); + PUB.e=e; + + t.copy(p1); + t.shr(); + PRIV.dp.set(e); + PRIV.dp.invmodp(t); + if (PRIV.dp.parity()===0) PRIV.dp.add(t); + PRIV.dp.norm(); + + t.copy(q1); + t.shr(); + PRIV.dq.set(e); + PRIV.dq.invmodp(t); + if (PRIV.dq.parity()===0) PRIV.dq.add(t); + PRIV.dq.norm(); + + PRIV.c.copy(PRIV.p); + PRIV.c.invmodp(PRIV.q); + + return; + }, + +/* Mask Generation Function */ + MGF1: function(sha,Z,olen,K) + { + var i,hlen=sha; + var B=[]; + + var counter,cthreshold,k=0; + for (i=0;i<K.length;i++) K[i]=0; + + cthreshold=Math.floor(olen/hlen); if (olen%hlen!==0) cthreshold++; + for (counter=0;counter<cthreshold;counter++) + { + B=this.hashit(sha,Z,counter); + if (k+hlen>olen) for (i=0;i<olen%hlen;i++) K[k++]=B[i]; + else for (i=0;i<hlen;i++) K[k++]=B[i]; + } + }, + + PKCS15: function(sha,m,w) + { + var olen=ROM.FF_BITS/8; + var i,hlen=sha; + var idlen=19; + + if (olen<idlen+hlen+10) return false; + var H=this.hashit(sha,m,-1); + + for (i=0;i<w.length;i++) w[i]=0; + i=0; + w[i++]=0; + w[i++]=1; + for (var j=0;j<olen-idlen-hlen-3;j++) + w[i++]=0xff; + w[i++]=0; + + + if (hlen==this.SHA256) for (var j=0;j<idlen;j++) w[i++]=this.SHA256ID[j]; + if (hlen==this.SHA384) for (var j=0;j<idlen;j++) w[i++]=this.SHA384ID[j]; + if (hlen==this.SHA512) for (var j=0;j<idlen;j++) w[i++]=this.SHA512ID[j]; + + for (var j=0;j<hlen;j++) + w[i++]=H[j]; + + return true; + }, + + /* OAEP Message Encoding for Encryption */ + OAEP_ENCODE: function(sha,m,rng,p) + { + var i,slen,olen=RSA.RFS-1; + var mlen=m.length; + var hlen,seedlen; + var f=[]; + + hlen=sha; + var SEED=[]; + seedlen=hlen; + + if (mlen>olen-hlen-seedlen-1) return null; + + var DBMASK=[]; + + var h=this.hashit(sha,p,-1); + for (i=0;i<hlen;i++) f[i]=h[i]; + + slen=olen-mlen-hlen-seedlen-1; + + for (i=0;i<slen;i++) f[hlen+i]=0; + f[hlen+slen]=1; + for (i=0;i<mlen;i++) f[hlen+slen+1+i]=m[i]; + + for (i=0;i<seedlen;i++) SEED[i]=rng.getByte(); + this.MGF1(sha,SEED,olen-seedlen,DBMASK); + + for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i]; + this.MGF1(sha,DBMASK,seedlen,f); + + for (i=0;i<seedlen;i++) f[i]^=SEED[i]; + + for (i=0;i<olen-seedlen;i++) f[i+seedlen]=DBMASK[i]; + + /* pad to length RFS */ + var d=1; + for (i=RSA.RFS-1;i>=d;i--) + f[i]=f[i-d]; + for (i=d-1;i>=0;i--) + f[i]=0; + + return f; + }, + + /* OAEP Message Decoding for Decryption */ + OAEP_DECODE: function(sha,p,f) + { + var x,t; + var comp; + var i,k,olen=RSA.RFS-1; + var hlen,seedlen; + + hlen=sha; + var SEED=[]; + seedlen=hlen; + var CHASH=[]; + seedlen=hlen=sha; + + if (olen<seedlen+hlen+1) return null; + + var DBMASK=[]; + for (i=0;i<olen-seedlen;i++) DBMASK[i]=0; + + if (f.length<RSA.RFS) + { + var d=RSA.RFS-f.length; + for (i=RFS-1;i>=d;i--) + f[i]=f[i-d]; + for (i=d-1;i>=0;i--) + f[i]=0; + + } + + var h=this.hashit(sha,p,-1); + for (i=0;i<hlen;i++) CHASH[i]=h[i]; + + x=f[0]; + + for (i=seedlen;i<olen;i++) + DBMASK[i-seedlen]=f[i+1]; + + this.MGF1(sha,DBMASK,seedlen,SEED); + for (i=0;i<seedlen;i++) SEED[i]^=f[i+1]; + this.MGF1(sha,SEED,olen-seedlen,f); + for (i=0;i<olen-seedlen;i++) DBMASK[i]^=f[i]; + + comp=true; + for (i=0;i<hlen;i++) + { + if (CHASH[i]!=DBMASK[i]) comp=false; + } + + for (i=0;i<olen-seedlen-hlen;i++) + DBMASK[i]=DBMASK[i+hlen]; + + for (i=0;i<hlen;i++) + SEED[i]=CHASH[i]=0; + + for (k=0;;k++) + { + if (k>=olen-seedlen-hlen) return null; + if (DBMASK[k]!==0) break; + } + + t=DBMASK[k]; + + if (!comp || x!==0 || t!=0x01) + { + for (i=0;i<olen-seedlen;i++) DBMASK[i]=0; + return null; + } + + var r=[]; + + for (i=0;i<olen-seedlen-hlen-k-1;i++) + r[i]=DBMASK[i+k+1]; + + for (i=0;i<olen-seedlen;i++) DBMASK[i]=0; + + return r; + }, + + /* destroy the Private Key structure */ + PRIVATE_KEY_KILL: function(PRIV) + { + PRIV.p.zero(); + PRIV.q.zero(); + PRIV.dp.zero(); + PRIV.dq.zero(); + PRIV.c.zero(); + }, + + /* RSA encryption with the public key */ + ENCRYPT: function(PUB,F,G) + { + var n=PUB.n.getlen(); + var f=new FF(n); + + FF.fromBytes(f,F); + + f.power(PUB.e,PUB.n); + + f.toBytes(G); + }, + + /* RSA decryption with the private key */ + DECRYPT: function(PRIV,G,F) + { + var n=PRIV.p.getlen(); + var g=new FF(2*n); + + FF.fromBytes(g,G); + var jp=g.dmod(PRIV.p); + var jq=g.dmod(PRIV.q); + + jp.skpow(PRIV.dp,PRIV.p); + jq.skpow(PRIV.dq,PRIV.q); + + g.zero(); + g.dscopy(jp); + jp.mod(PRIV.q); + if (FF.comp(jp,jq)>0) jq.add(PRIV.q); + jq.sub(jp); + jq.norm(); + + var t=FF.mul(PRIV.c,jq); + jq=t.dmod(PRIV.q); + + t=FF.mul(jq,PRIV.p); + g.add(t); + g.norm(); + + g.toBytes(F); + } + +}; \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/js/TestECDH.html ---------------------------------------------------------------------- diff --git a/version22/js/TestECDH.html b/version22/js/TestECDH.html new file mode 100644 index 0000000..1ddf0c2 --- /dev/null +++ b/version22/js/TestECDH.html @@ -0,0 +1,143 @@ +<!DOCTYPE HTML> +<html> +<head> +<title>JavaScript Test ECC</title> +</head> +<body> +<h1>JavaScript Test ECC Example</h1> +<script type="text/javascript" src="DBIG.js"></script> +<script type="text/javascript" src="BIG.js"></script> +<script type="text/javascript" src="FP.js"></script> +<script type="text/javascript" src="ROM.js"></script> +<script type="text/javascript" src="UInt64.js"></script> +<script type="text/javascript" src="HASH256.js"></script> +<script type="text/javascript" src="HASH384.js"></script> +<script type="text/javascript" src="HASH512.js"></script> +<script type="text/javascript" src="RAND.js"></script> +<script type="text/javascript" src="AES.js"></script> +<script type="text/javascript" src="GCM.js"></script> +<script type="text/javascript" src="ECP.js"></script> +<script type="text/javascript" src="ECDH.js"></script> + +<script> +/* test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */ + var i,j=0,res; + var result; + var pp="M0ng00se"; + + var EGS=ECDH.EGS; + var EFS=ECDH.EFS; + var EAS=16; + var sha=ECDH.HASH_TYPE; + + var S1=[]; + var W0=[]; + var W1=[]; + var Z0=[]; + var Z1=[]; + var RAW=[]; + var SALT=[]; + var P1=[]; + var P2=[]; + var V=[]; + var M=[]; + var T=new Array(12); // must specify required length + var CS=[]; + var DS=[]; + + var rng=new RAND(); + + rng.clean(); + for (i=0;i<100;i++) RAW[i]=i; + + rng.seed(100,RAW); +//for (j=0;j<100;j++) +//{ + + for (i=0;i<8;i++) SALT[i]=(i+1); // set Salt + + window.document.write("Alice's Passphrase= " + pp + "<br>"); + + var PW=ECDH.stringtobytes(pp); +/* private key S0 of size EGS bytes derived from Password and Salt */ + var S0=ECDH.PBKDF2(sha,PW,SALT,1000,EGS); + + window.document.write("Alice's private key= 0x"+ECDH.bytestostring(S0)+ "<br>"); +/* Generate Key pair S/W */ + ECDH.KEY_PAIR_GENERATE(null,S0,W0); + + window.document.write("Alice's public key= 0x"+ECDH.bytestostring(W0)+ "<br>"); + + res=ECDH.PUBLIC_KEY_VALIDATE(true,W0); + if (res!=0) + alert("ECP Public Key is invalid!"); +/* Random private key for other party */ + ECDH.KEY_PAIR_GENERATE(rng,S1,W1); + + window.document.write("Servers private key= 0x"+ECDH.bytestostring(S1)+ "<br>"); + window.document.write("Servers public key= 0x"+ECDH.bytestostring(W1)+ "<br>"); + + res=ECDH.PUBLIC_KEY_VALIDATE(true,W1); + if (res!=0) + alert("ECP Public Key is invalid!"); + + +/* Calculate common key using DH - IEEE 1363 method */ + + ECDH.ECPSVDP_DH(S0,W1,Z0); + ECDH.ECPSVDP_DH(S1,W0,Z1); + + var same=true; + for (i=0;i<ECDH.EFS;i++) + if (Z0[i]!=Z1[i]) same=false; + + if (!same) + alert("*** ECPSVDP-DH Failed"); + + var KEY=ECDH.KDF2(sha,Z0,null,ECDH.EAS); + + window.document.write("Alice's DH Key= 0x"+ECDH.bytestostring(KEY)+ "<br>"); + window.document.write("Servers DH Key= 0x"+ECDH.bytestostring(KEY)+ "<br>"); + + if (ROM.CURVETYPE!=ROM.MONTGOMERY) + { + window.document.write("Testing ECIES"+ "<br>"); + + P1[0]=0x0; P1[1]=0x1; P1[2]=0x2; + P2[0]=0x0; P2[1]=0x1; P2[2]=0x2; P2[3]=0x3; + + for (i=0;i<=16;i++) M[i]=i; + + var C=ECDH.ECIES_ENCRYPT(sha,P1,P2,rng,W1,M,V,T); + + window.document.write("Ciphertext= "+ "<br>"); + window.document.write("V= 0x"+ECDH.bytestostring(V)+ "<br>"); + window.document.write("C= 0x"+ECDH.bytestostring(C)+ "<br>"); + window.document.write("T= 0x"+ECDH.bytestostring(T)+ "<br>"); + + + M=ECDH.ECIES_DECRYPT(sha,P1,P2,V,C,T,S1); + if (M.length==0) + alert("*** ECIES Decryption Failed "); + else window.document.write("Decryption succeeded"+ "<br>"); + + window.document.write("Message is 0x"+ECDH.bytestostring(M)+ "<br>"); + + window.document.write("Testing ECDSA"+ "<br>"); + + if (ECDH.ECPSP_DSA(sha,rng,S0,M,CS,DS)!=0) + alert("***ECDSA Signature Failed"); + + window.document.write("Signature= "+ "<br>"); + window.document.write("C= 0x"+ECDH.bytestostring(CS)+ "<br>"); + window.document.write("D= 0x"+ECDH.bytestostring(DS)+ "<br>"); + + if (ECDH.ECPVP_DSA(sha,W0,M,CS,DS)!=0) + alert("***ECDSA Verification Failed"); + else window.document.write("ECDSA Signature/Verification succeeded "+ "<br>"); + } +//} +//window.document.write("Test Completed Successfully"+ "<br>"); +</script> +</body> +</html> http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/js/TestMPIN.html ---------------------------------------------------------------------- diff --git a/version22/js/TestMPIN.html b/version22/js/TestMPIN.html new file mode 100644 index 0000000..0cb6f67 --- /dev/null +++ b/version22/js/TestMPIN.html @@ -0,0 +1,330 @@ +<!DOCTYPE HTML> +<html> +<head> +<title>JavaScript Test MPIN</title> +</head> +<body> +<h1>JavaScript Test MPIN Example</h1> +<script type="text/javascript" src="DBIG.js"></script> +<script type="text/javascript" src="BIG.js"></script> +<script type="text/javascript" src="FP.js"></script> +<script type="text/javascript" src="ROM.js"></script> +<script type="text/javascript" src="UInt64.js"></script> +<script type="text/javascript" src="HASH256.js"></script> +<script type="text/javascript" src="HASH384.js"></script> +<script type="text/javascript" src="HASH512.js"></script> +<script type="text/javascript" src="RAND.js"></script> +<script type="text/javascript" src="AES.js"></script> +<script type="text/javascript" src="GCM.js"></script> +<script type="text/javascript" src="ECP.js"></script> +<script type="text/javascript" src="FP2.js"></script> +<script type="text/javascript" src="ECP2.js"></script> +<script type="text/javascript" src="FP4.js"></script> +<script type="text/javascript" src="FP12.js"></script> +<script type="text/javascript" src="PAIR.js"></script> +<script type="text/javascript" src="MPIN.js"></script> + +<script> +/* test driver and function exerciser for MPIN API Functions */ + + var i,res; + var result; + + var EGS=MPIN.EGS; + var EFS=MPIN.EFS; + var EAS=16; + + var sha=MPIN.HASH_TYPE; + + var rng=new RAND(); + rng.clean(); + + var RAW=[]; + for (i=0;i<100;i++) RAW[i]=i+1; + rng.seed(100,RAW); + + var G1S=2*EFS+1; /* Group 1 Size */ + var G2S=4*EFS; /* Group 2 Size */ + + var S=[]; + var SST=[]; + var TOKEN = []; + var PERMIT = []; + var SEC = []; + var xID = []; + var xCID = []; + var X= []; + var Y= []; + var E=[]; + var F=[]; + var HCID=[]; + var HID=[]; + var HTID=[]; + + var G1=[]; + var G2=[]; + var R=[]; + var Z=[]; + var W=[]; + var T=[]; + var CK=[]; + var SK=[]; + + var HSID=[]; + +/* Set configuration */ + var PERMITS=true; + var PINERROR=true; + var FULL=true; + var ONE_PASS=false; + var TIME_FUNCTIONS=false; + var total_time=0; + var nIter=100 +/* + var PR=[]; + pin=parseInt(prompt("Enter PIN= ")); + window.document.write("Test Pairing" + "<br>"); + for (i=0;i<100;i++) + MPIN.TEST_PAIR(PR); + window.document.write("Pairing= "+MPIN.bytestostring(PR) + "<br>"); + + pin=parseInt(prompt("Enter PIN= ")); +*/ + +/* Trusted Authority set-up */ + MPIN.RANDOM_GENERATE(rng,S); + window.document.write("Master Secret s: 0x"+MPIN.bytestostring(S) + "<br>"); + + /* Create Client Identity */ + var IDstr = "[email protected]"; + var CLIENT_ID = MPIN.stringtobytes(IDstr); + HCID=MPIN.HASH_ID(sha,CLIENT_ID); /* Either Client or TA calculates Hash(ID) - you decide! */ + + window.document.write("Client ID= "+MPIN.bytestostring(CLIENT_ID) + "<br>"); + +/* Client and Server are issued secrets by DTA */ + MPIN.GET_SERVER_SECRET(S,SST); + window.document.write("Server Secret SS: 0x"+MPIN.bytestostring(SST) + "<br>"); + + MPIN.GET_CLIENT_SECRET(S,HCID,TOKEN); + window.document.write("Client Secret CS: 0x"+MPIN.bytestostring(TOKEN) + "<br>"); + +/* Client extracts PIN from secret to create Token */ + var pin=1234; + window.document.write("Client extracts PIN= "+pin + "<br>"); + var rtn=MPIN.EXTRACT_PIN(sha,CLIENT_ID,pin,TOKEN); + if (rtn != 0) + window.document.write("Failed to extract PIN " + "<br>"); + + window.document.write("Client Token TK: 0x"+MPIN.bytestostring(TOKEN) + "<br>"); + + if (FULL) + { + MPIN.PRECOMPUTE(TOKEN,HCID,G1,G2); + } + + var date; + if (PERMITS) + { + date=MPIN.today(); +/* Client gets "Time Token" permit from DTA */ + MPIN.GET_CLIENT_PERMIT(sha,date,S,HCID,PERMIT); + window.document.write("Time Permit TP: 0x"+MPIN.bytestostring(PERMIT) + "<br>"); + +/* This encoding makes Time permit look random - Elligator squared */ + MPIN.ENCODING(rng,PERMIT); + window.document.write("Encoded Time Permit TP: 0x"+MPIN.bytestostring(PERMIT) + "<br>"); + MPIN.DECODING(PERMIT); + window.document.write("Decoded Time Permit TP: 0x"+MPIN.bytestostring(PERMIT) + "<br>"); + } + else date=0; + + + pin=parseInt(prompt("Enter PIN= ")); + +/* Set date=0 and PERMIT=null if time permits not in use + +Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and PERMIT. Output xID = x.H(CLIENT_ID) and re-combined secret SEC +If PERMITS are is use, then date!=0 and PERMIT is added to secret and xCID = x.(H(CLIENT_ID)+H_T(date|H(CLIENT_ID))) +Random value x is supplied externally if RNG=null, otherwise generated and passed out by RNG + +If Time Permits OFF set xCID = null, HTID=null and use xID and HID only +If Time permits are ON, AND pin error detection is required then all of xID, xCID, HID and HTID are required +If Time permits are ON, AND pin error detection is NOT required, set xID=null, HID=null and use xCID and HTID only. + + +*/ + var pxID=xID; + var pxCID=xCID; + var pHID=HID; + var pHTID=HTID; + var pE=E; + var pF=F; + var pPERMIT=PERMIT; + var prHID; + + if (date!=0) + { + prHID=pHTID; + if (!PINERROR) + { + pxID=null; + // pHID=null; + } + } + else + { + prHID=pHID; + pPERMIT=null; + pxCID=null; + pHTID=null; + } + if (!PINERROR) + { + pE=null; + pF=null; + } + + if (ONE_PASS) + { + window.document.write("MPIN Single Pass " + "<br>"); + timeValue = MPIN.GET_TIME(); + window.document.write("Epoch " + timeValue + "<br>"); + if (TIME_FUNCTIONS) + { + var start = new Date().getTime(); + for (i = 0; i < nIter; ++i) { + rtn=MPIN.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y); + } + var end = new Date().getTime(); + var t1 = end - start; + total_time = total_time + t1; + var iter_time = t1 / nIter; + var iter_per_sec = nIter / (t1 / 1000); + window.document.write("MPIN.CLIENT: time " + t1 + "ms iteration time " + iter_time + "ms iterations per second " + iter_per_sec + "<br>"); + } + else + { + rtn=MPIN.CLIENT(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT,timeValue,Y); + } + if (rtn != 0) + window.document.write("FAILURE: CLIENT rtn: " + rtn + "<br>"); + + if (FULL) + { + if (TIME_FUNCTIONS) + { + var start = new Date().getTime(); + for (i = 0; i < nIter; ++i) { + HCID=MPIN.HASH_ID(sha,CLIENT_ID); + MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z); + } + var end = new Date().getTime(); + var t2 = end - start; + total_time = total_time + t2; + var iter_time = t2 / nIter; + var iter_per_sec = nIter / (t2 / 1000); + window.document.write("MPIN.GET_G1_MULTIPLE: time " + t2 + "ms iteration time " + iter_time + "ms iterations per second " + iter_per_sec + "<br>"); + } + else + { + HCID=MPIN.HASH_ID(sha,CLIENT_ID); + MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z); /* Also Send Z=r.ID to Server, remember random r */ + } + } + + rtn=MPIN.SERVER(sha,date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF,CLIENT_ID,timeValue); + if (rtn != 0) + window.document.write("FAILURE: SERVER rtn: " + rtn+ "<br>"); + + if (FULL) + { + HSID=MPIN.HASH_ID(sha,CLIENT_ID); + MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T); /* Also send T=w.ID to client, remember random w */ + } + } + else + { + window.document.write("MPIN Multi Pass " + "<br>"); + rtn=MPIN.CLIENT_1(sha,date,CLIENT_ID,rng,X,pin,TOKEN,SEC,pxID,pxCID,pPERMIT); + if (rtn != 0) + window.document.write("FAILURE: CLIENT_1 rtn: " + rtn + "<br>"); + + if (FULL) + { + HCID=MPIN.HASH_ID(sha,CLIENT_ID); + MPIN.GET_G1_MULTIPLE(rng,1,R,HCID,Z); /* Also Send Z=r.ID to Server, remember random r */ + } + + /* Server calculates H(ID) and H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. */ + MPIN.SERVER_1(sha,date,CLIENT_ID,pHID,pHTID); + + /* Server generates Random number Y and sends it to Client */ + MPIN.RANDOM_GENERATE(rng,Y); + + if (FULL) + { + HSID=MPIN.HASH_ID(sha,CLIENT_ID); + MPIN.GET_G1_MULTIPLE(rng,0,W,prHID,T); /* Also send T=w.ID to client, remember random w */ + } + + /* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */ + rtn=MPIN.CLIENT_2(X,Y,SEC); + if (rtn != 0) + window.document.write("FAILURE: CLIENT_2 rtn: " + rtn + "<br>"); + /* Server Second pass. Inputs hashed client id, random Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */ + /* If PIN error not required, set E and F = NULL */ + rtn=MPIN.SERVER_2(date,pHID,pHTID,Y,SST,pxID,pxCID,SEC,pE,pF); + + if (rtn != 0) + window.document.write("FAILURE: SERVER_1 rtn: " + rtn+ "<br>"); + + } + + + if (rtn == this.MPIN.BAD_PIN) + { + window.document.write("Server says - Bad Pin. I don't know you. Feck off." + "<br>"); + if (PINERROR) + { + var err=MPIN.KANGAROO(E,F); + if (err!=0) window.document.write("(Client PIN is out by "+err + ")<br>"); + } + } + else + { + window.document.write("Server says - PIN is good! You really are "+IDstr + "<br>"); + if (FULL) + { + if (TIME_FUNCTIONS) + { + var start = new Date().getTime(); + for (i = 0; i < nIter; ++i) { + MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,T,CK); + } + var end = new Date().getTime(); + var t3 = end - start; + total_time = total_time + t3; + var iter_time = t3 / nIter; + var iter_per_sec = nIter / (t3 / 1000); + window.document.write("MPIN.CLIENT_KEY: time " + t1 + "ms iteration time " + iter_time + "ms iterations per second " + iter_per_sec + "<br>"); + } + else + { + H=MPIN.HASH_ALL(sha,HCID,pxID,pxCID,SEC,Y,Z,T); + MPIN.CLIENT_KEY(sha,G1,G2,pin,R,X,H,T,CK); + } + window.document.write("Client Key = 0x"+MPIN.bytestostring(CK) + "<br>"); + H=MPIN.HASH_ALL(sha,HSID,pxID,pxCID,SEC,Y,Z,T); + MPIN.SERVER_KEY(sha,Z,SST,W,H,pHID,pxID,pxCID,SK); + window.document.write("Server Key = 0x"+MPIN.bytestostring(SK) + "<br>"); + } + } + // var iter_time = total_time / nIter; + // var iter_per_sec = nIter / (total_time / 1000); + // window.document.write("CLIENT: total time " + total_time + "ms iteration time " + iter_time + "ms iterations per second " + iter_per_sec + "<br>"); + + +</script> +</body> +</html> http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/js/TestRSA.html ---------------------------------------------------------------------- diff --git a/version22/js/TestRSA.html b/version22/js/TestRSA.html new file mode 100644 index 0000000..ba650ca --- /dev/null +++ b/version22/js/TestRSA.html @@ -0,0 +1,115 @@ +<!DOCTYPE HTML> +<html> +<head> +<title>JavaScript Test RSA</title> +</head> +<body> +<h1>JavaScript Test RSA Example</h1> +<script type="text/javascript" src="ROM.js"></script> +<script type="text/javascript" src="DBIG.js"></script> +<script type="text/javascript" src="BIG.js"></script> +<script type="text/javascript" src="UInt64.js"></script> +<script type="text/javascript" src="HASH256.js"></script> +<script type="text/javascript" src="HASH384.js"></script> +<script type="text/javascript" src="HASH512.js"></script> +<script type="text/javascript" src="RAND.js"></script> +<script type="text/javascript" src="FF.js"></script> +<script type="text/javascript" src="RSA.js"></script> + + +<script> +/* test driver and function exerciser for RSA API Functions */ + + var i,j=0,res; + var result; + + var RFS=RSA.RFS; + var sha=RSA.HASH_TYPE; + + var message="Hello World\n"; + + var pub=new rsa_public_key(ROM.FFLEN); + var priv=new rsa_private_key(ROM.HFLEN); + + var ML=[]; + var C=[]; + var S=[]; + var RAW=[]; + + var rng=new RAND(); + rng.clean(); + + for (i=0;i<100;i++) RAW[i]=i; + rng.seed(100,RAW); + + var start,end,time; + start=new Date().getTime(); + window.document.write("Generating public/private key pair (slow!) <br>"); + RSA.KEY_PAIR(rng,65537,priv,pub); + end=new Date().getTime(); + time=end-start; + window.document.write("Time in ms= "+time+"<br>"); + + var M=RSA.stringtobytes(message); + window.document.write("Encrypting test string <br>"); + + var E=RSA.OAEP_ENCODE(sha,M,rng,null); /* OAEP encode message m to e */ + window.document.write("Encoding= 0x" + RSA.bytestohex(E) + "<br>"); + + window.document.write("Public key= 0x"+pub.n.toString() + "<br>"); + + start=new Date().getTime(); + RSA.ENCRYPT(pub,E,C); /* encrypt encoded message */ + end=new Date().getTime(); + time=end-start; + window.document.write("Time in ms= "+time+"<br>"); + + window.document.write("Ciphertext= 0x" + RSA.bytestohex(C) + "<br>"); + + window.document.write("Decrypting test string <br>"); + start=new Date().getTime(); + RSA.DECRYPT(priv,C,ML); + end=new Date().getTime(); + time=end-start; + window.document.write("Time in ms= "+time+"<br>"); + + var cmp=true; + if (E.length!=ML.length) cmp=false; + else + { + for (var j=0;j<E.length;j++) + if (E[j]!=ML[j]) cmp=false; + } + if (cmp) window.document.write("Decryption is OK <br>"); + else window.document.write("Decryption Failed <br>"); + + var MS=RSA.OAEP_DECODE(sha,null,ML); /* OAEP decode message */ + window.document.write("Decoding= 0x" + RSA.bytestohex(MS) + "<br>"); + + window.document.write("message= "+RSA.bytestostring(MS) + "<br>"); + + + window.document.write("Signing message <br>"); + RSA.PKCS15(sha,M,C); + + RSA.DECRYPT(priv,C,S); /* create signature in S */ + + window.document.write("Signature= 0x" + RSA.bytestohex(S) + "<br>"); + + RSA.ENCRYPT(pub,S,ML); + + cmp=true; + if (C.length!=ML.length) cmp=false; + else + { + for (var j=0;j<C.length;j++) + if (C[j]!=ML[j]) cmp=false; + } + if (cmp) window.document.write("Signature is valid <br>"); + else window.document.write("Signature is INVALID <br>"); + + RSA.PRIVATE_KEY_KILL(priv); + +</script> +</body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/js/UInt64.js ---------------------------------------------------------------------- diff --git a/version22/js/UInt64.js b/version22/js/UInt64.js new file mode 100644 index 0000000..2d93b9c --- /dev/null +++ b/version22/js/UInt64.js @@ -0,0 +1,54 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +/* rudimentary unsigned 64-bit type for SHA384 and SHA512 */ + +var UInt64 = function(top,bot) { + this.top=top; + this.bot=bot; +}; + +UInt64.prototype={ + add: function(y) + { + var t=(this.bot>>>0)+(y.bot>>>0); + var low=t >>> 0; + var high=(this.top>>>0)+(y.top>>>0); + + this.bot=low; + if (low!=t) + this.top=(high+1)>>>0; + else + this.top=high; + + return this; + }, + copy: function() + { + var r=new UInt64(this.top,this.bot); + return r; + }, + shlb: function() + { + var t=this.bot>>>24; + this.top=t+(this.top<<8); + this.bot<<=8; + return this; + } +}; http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/js/readme.txt ---------------------------------------------------------------------- diff --git a/version22/js/readme.txt b/version22/js/readme.txt new file mode 100644 index 0000000..e040021 --- /dev/null +++ b/version22/js/readme.txt @@ -0,0 +1,41 @@ +AMCL is very simple to build for JavaScript. + +First - decide the modulus type and curve type you want to use. Edit ROM.js +where indicated. You might want to use one of the curves whose details are +already in there. + +Three example API files are provided, MPIN.js which +supports our M-Pin (tm) protocol, ECDH.js which supports elliptic +curve key exchange, digital signature and public key crypto, and RSA.js +which supports RSA encryption. The first can be tested using the +TestMPIN.html driver programs, the second can be tested using TestECDH.html, +and the third using TestRSA.html + +In the ROM.js file you must provide the curve constants. Several examples +are provided there, if you are willing to use one of these. + +To help generate the ROM constants for your own curve some MIRACL helper +programs are included. The programs bngen.cpp and blsgen.cpp generate ROM +data for a BN and BLS pairing friendly curves, and the program ecgen.cpp +generates ROM data for regular EC curves. + +The MIRACL based program check.cpp helps choose the best number base for +big number representation, given the word-length and the size of the modulus. + +The program bigtobig.cpp converts a big number to the AMCL +BIG format. + + +For quick jumpstart:- + +Run Chrome browser and navigate to TestECDH.html + +or TestMPIN.html + +or BenchtestEC.html + +or BenchtestPAIR.html + +You might need to wait a couple of minutes for the output to appear. + + http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/rust/.gitignore ---------------------------------------------------------------------- diff --git a/version22/rust/.gitignore b/version22/rust/.gitignore new file mode 100644 index 0000000..fc8bcce --- /dev/null +++ b/version22/rust/.gitignore @@ -0,0 +1,5 @@ +cargo-registry +target +Cargo.lock +.idea + http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/rust/Cargo.toml ---------------------------------------------------------------------- diff --git a/version22/rust/Cargo.toml b/version22/rust/Cargo.toml new file mode 100644 index 0000000..5d07d78 --- /dev/null +++ b/version22/rust/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "amcl" +version = "0.1.3" +authors = [ + "Vyacheslav Gudkov <[email protected]>", + "Evgeniy Razinkov <[email protected]>" + ] + +description = "The Apache Milagro Cryptographic Library(version 2.2)" +license = "Apache-2.0" +repository = "https://github.com/MRJCrunch/amcl" +[lib] +name = "amcl" +path = "src/lib.rs" + +[features] +default = ["BLS383"] +Ed25519 = [] +GOLDILOCKS = [] +BN254 = [] +BLS383 = [] +BLS455 = [] + +[dependencies] \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/rust/readme.txt ---------------------------------------------------------------------- diff --git a/version22/rust/readme.txt b/version22/rust/readme.txt new file mode 100644 index 0000000..128f665 --- /dev/null +++ b/version22/rust/readme.txt @@ -0,0 +1,56 @@ +AMCL is very simple to build for Rust. + +This version supports both 32-bit and 64-bit builds. +If your processor and operating system are both 64-bit, a 64-bit build +will probably be best. Otherwise use a 32-bit build. + +First - decide the modulus and curve type you want to use. Edit rom32.rs +or rom64.rs where indicated. You will probably want to use one of the curves +whose details are already in there. You might want to "raid" the rom +file from the C version of the library for more curves. + +Three example API files are provided, mpin.rs which +supports our M-Pin (tm) protocol, ecdh.rs which supports elliptic +curve key exchange, digital signature and public key crypto, and rsa.rs +which supports the RSA method. The first can be tested using the +TestMPIN.rs driver program, the second can be tested using TestECDH.rs, +and the third with TestRSA.rs + + +In the rom32.rs/rom64.rs file you must provide the curve constants. Several +examples are provided there, if you are willing to use one of these. + +To help generate the ROM constants for your own curve some MIRACL helper +programs are included. The programs bngen.cpp and blsgen.cpp generate ROM +data for a BN and BLS pairing friendly curves, and the program ecgen.cpp +generates ROM data for regular EC curves. + +The MIRACL based program check.cpp helps choose the best number base for +big number representation, given the word-length and the size of the modulus. + +The program bigtobig.cpp converts a big number to the AMCL +BIG format. + +For a quick jumpstart:- + +Copy rom32.rs to rom.rs for a 32-bit build + +rustc --cfg D32 -O -A dead_code TestMPIN.rs + +or + +rustc --cfg D32 -O -A dead_code TestECDH.rs + +or + +rustc --cfg D32 -O -A dead_code TestRSA.rs + +also + +rustc --cfg D32 -O -A dead_code BenchtestEC.rs + +rustc --cfg D32 -O -A dead_code BenchtestPAIR.rs + + +For a 64-bit build copy rom64.rs to rom.rs, and use instead the +flag --cfg D64 http://git-wip-us.apache.org/repos/asf/incubator-milagro-crypto/blob/c25f9e5c/version22/rust/src/aes.rs ---------------------------------------------------------------------- diff --git a/version22/rust/src/aes.rs b/version22/rust/src/aes.rs new file mode 100644 index 0000000..5298837 --- /dev/null +++ b/version22/rust/src/aes.rs @@ -0,0 +1,628 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +pub const ECB: usize=0; +pub const CBC: usize=1; +pub const CFB1: usize=2; +pub const CFB2: usize=3; +pub const CFB4: usize=5; +pub const OFB1: usize=14; +pub const OFB2: usize=15; +pub const OFB4: usize=17; +pub const OFB8:usize=21; +pub const OFB16: usize=29; +pub const CTR1: usize=30; +pub const CTR2: usize=31; +pub const CTR4: usize=33; +pub const CTR8: usize=37; +pub const CTR16: usize=45; + +const INCO : [u8;4] = [0xB,0xD,0x9,0xE]; /* Inverse Coefficients */ + +const PTAB : [u8;256] = [ + 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, + 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, + 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49, + 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, + 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, + 131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, + 181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163, + 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160, + 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, + 195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, + 159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, + 155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, + 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, + 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, + 18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, + 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1]; + +const LTAB : [u8;256] = [ + 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, + 100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, + 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120, + 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142, + 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, + 102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, + 126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186, + 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87, + 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, + 44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, + 127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, + 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157, + 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209, + 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, + 68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, + 103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7]; + + +const FBSUB : [u8;256] = [ + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, + 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, + 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, + 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, + 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, + 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, + 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, + 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, + 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, + 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, + 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, + 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, + 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, + 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22]; + +const RBSUB : [u8;256] = [ + 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, + 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, + 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, + 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, + 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, + 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, + 144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, + 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107, + 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115, + 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, + 71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, + 252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, + 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, + 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, + 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, + 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125]; + +const RCO : [u8;16] = [1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47]; + +const FTABLE : [u32;256] = [ + 0xa56363c6,0x847c7cf8,0x997777ee,0x8d7b7bf6,0xdf2f2ff,0xbd6b6bd6, + 0xb16f6fde,0x54c5c591,0x50303060,0x3010102,0xa96767ce,0x7d2b2b56, + 0x19fefee7,0x62d7d7b5,0xe6abab4d,0x9a7676ec,0x45caca8f,0x9d82821f, + 0x40c9c989,0x877d7dfa,0x15fafaef,0xeb5959b2,0xc947478e,0xbf0f0fb, + 0xecadad41,0x67d4d4b3,0xfda2a25f,0xeaafaf45,0xbf9c9c23,0xf7a4a453, + 0x967272e4,0x5bc0c09b,0xc2b7b775,0x1cfdfde1,0xae93933d,0x6a26264c, + 0x5a36366c,0x413f3f7e,0x2f7f7f5,0x4fcccc83,0x5c343468,0xf4a5a551, + 0x34e5e5d1,0x8f1f1f9,0x937171e2,0x73d8d8ab,0x53313162,0x3f15152a, + 0xc040408,0x52c7c795,0x65232346,0x5ec3c39d,0x28181830,0xa1969637, + 0xf05050a,0xb59a9a2f,0x907070e,0x36121224,0x9b80801b,0x3de2e2df, + 0x26ebebcd,0x6927274e,0xcdb2b27f,0x9f7575ea,0x1b090912,0x9e83831d, + 0x742c2c58,0x2e1a1a34,0x2d1b1b36,0xb26e6edc,0xee5a5ab4,0xfba0a05b, + 0xf65252a4,0x4d3b3b76,0x61d6d6b7,0xceb3b37d,0x7b292952,0x3ee3e3dd, + 0x712f2f5e,0x97848413,0xf55353a6,0x68d1d1b9,0x0,0x2cededc1, + 0x60202040,0x1ffcfce3,0xc8b1b179,0xed5b5bb6,0xbe6a6ad4,0x46cbcb8d, + 0xd9bebe67,0x4b393972,0xde4a4a94,0xd44c4c98,0xe85858b0,0x4acfcf85, + 0x6bd0d0bb,0x2aefefc5,0xe5aaaa4f,0x16fbfbed,0xc5434386,0xd74d4d9a, + 0x55333366,0x94858511,0xcf45458a,0x10f9f9e9,0x6020204,0x817f7ffe, + 0xf05050a0,0x443c3c78,0xba9f9f25,0xe3a8a84b,0xf35151a2,0xfea3a35d, + 0xc0404080,0x8a8f8f05,0xad92923f,0xbc9d9d21,0x48383870,0x4f5f5f1, + 0xdfbcbc63,0xc1b6b677,0x75dadaaf,0x63212142,0x30101020,0x1affffe5, + 0xef3f3fd,0x6dd2d2bf,0x4ccdcd81,0x140c0c18,0x35131326,0x2fececc3, + 0xe15f5fbe,0xa2979735,0xcc444488,0x3917172e,0x57c4c493,0xf2a7a755, + 0x827e7efc,0x473d3d7a,0xac6464c8,0xe75d5dba,0x2b191932,0x957373e6, + 0xa06060c0,0x98818119,0xd14f4f9e,0x7fdcdca3,0x66222244,0x7e2a2a54, + 0xab90903b,0x8388880b,0xca46468c,0x29eeeec7,0xd3b8b86b,0x3c141428, + 0x79dedea7,0xe25e5ebc,0x1d0b0b16,0x76dbdbad,0x3be0e0db,0x56323264, + 0x4e3a3a74,0x1e0a0a14,0xdb494992,0xa06060c,0x6c242448,0xe45c5cb8, + 0x5dc2c29f,0x6ed3d3bd,0xefacac43,0xa66262c4,0xa8919139,0xa4959531, + 0x37e4e4d3,0x8b7979f2,0x32e7e7d5,0x43c8c88b,0x5937376e,0xb76d6dda, + 0x8c8d8d01,0x64d5d5b1,0xd24e4e9c,0xe0a9a949,0xb46c6cd8,0xfa5656ac, + 0x7f4f4f3,0x25eaeacf,0xaf6565ca,0x8e7a7af4,0xe9aeae47,0x18080810, + 0xd5baba6f,0x887878f0,0x6f25254a,0x722e2e5c,0x241c1c38,0xf1a6a657, + 0xc7b4b473,0x51c6c697,0x23e8e8cb,0x7cdddda1,0x9c7474e8,0x211f1f3e, + 0xdd4b4b96,0xdcbdbd61,0x868b8b0d,0x858a8a0f,0x907070e0,0x423e3e7c, + 0xc4b5b571,0xaa6666cc,0xd8484890,0x5030306,0x1f6f6f7,0x120e0e1c, + 0xa36161c2,0x5f35356a,0xf95757ae,0xd0b9b969,0x91868617,0x58c1c199, + 0x271d1d3a,0xb99e9e27,0x38e1e1d9,0x13f8f8eb,0xb398982b,0x33111122, + 0xbb6969d2,0x70d9d9a9,0x898e8e07,0xa7949433,0xb69b9b2d,0x221e1e3c, + 0x92878715,0x20e9e9c9,0x49cece87,0xff5555aa,0x78282850,0x7adfdfa5, + 0x8f8c8c03,0xf8a1a159,0x80898909,0x170d0d1a,0xdabfbf65,0x31e6e6d7, + 0xc6424284,0xb86868d0,0xc3414182,0xb0999929,0x772d2d5a,0x110f0f1e, + 0xcbb0b07b,0xfc5454a8,0xd6bbbb6d,0x3a16162c]; + +const RTABLE : [u32;256] = [ + 0x50a7f451,0x5365417e,0xc3a4171a,0x965e273a,0xcb6bab3b,0xf1459d1f, + 0xab58faac,0x9303e34b,0x55fa3020,0xf66d76ad,0x9176cc88,0x254c02f5, + 0xfcd7e54f,0xd7cb2ac5,0x80443526,0x8fa362b5,0x495ab1de,0x671bba25, + 0x980eea45,0xe1c0fe5d,0x2752fc3,0x12f04c81,0xa397468d,0xc6f9d36b, + 0xe75f8f03,0x959c9215,0xeb7a6dbf,0xda595295,0x2d83bed4,0xd3217458, + 0x2969e049,0x44c8c98e,0x6a89c275,0x78798ef4,0x6b3e5899,0xdd71b927, + 0xb64fe1be,0x17ad88f0,0x66ac20c9,0xb43ace7d,0x184adf63,0x82311ae5, + 0x60335197,0x457f5362,0xe07764b1,0x84ae6bbb,0x1ca081fe,0x942b08f9, + 0x58684870,0x19fd458f,0x876cde94,0xb7f87b52,0x23d373ab,0xe2024b72, + 0x578f1fe3,0x2aab5566,0x728ebb2,0x3c2b52f,0x9a7bc586,0xa50837d3, + 0xf2872830,0xb2a5bf23,0xba6a0302,0x5c8216ed,0x2b1ccf8a,0x92b479a7, + 0xf0f207f3,0xa1e2694e,0xcdf4da65,0xd5be0506,0x1f6234d1,0x8afea6c4, + 0x9d532e34,0xa055f3a2,0x32e18a05,0x75ebf6a4,0x39ec830b,0xaaef6040, + 0x69f715e,0x51106ebd,0xf98a213e,0x3d06dd96,0xae053edd,0x46bde64d, + 0xb58d5491,0x55dc471,0x6fd40604,0xff155060,0x24fb9819,0x97e9bdd6, + 0xcc434089,0x779ed967,0xbd42e8b0,0x888b8907,0x385b19e7,0xdbeec879, + 0x470a7ca1,0xe90f427c,0xc91e84f8,0x0,0x83868009,0x48ed2b32, + 0xac70111e,0x4e725a6c,0xfbff0efd,0x5638850f,0x1ed5ae3d,0x27392d36, + 0x64d90f0a,0x21a65c68,0xd1545b9b,0x3a2e3624,0xb1670a0c,0xfe75793, + 0xd296eeb4,0x9e919b1b,0x4fc5c080,0xa220dc61,0x694b775a,0x161a121c, + 0xaba93e2,0xe52aa0c0,0x43e0223c,0x1d171b12,0xb0d090e,0xadc78bf2, + 0xb9a8b62d,0xc8a91e14,0x8519f157,0x4c0775af,0xbbdd99ee,0xfd607fa3, + 0x9f2601f7,0xbcf5725c,0xc53b6644,0x347efb5b,0x7629438b,0xdcc623cb, + 0x68fcedb6,0x63f1e4b8,0xcadc31d7,0x10856342,0x40229713,0x2011c684, + 0x7d244a85,0xf83dbbd2,0x1132f9ae,0x6da129c7,0x4b2f9e1d,0xf330b2dc, + 0xec52860d,0xd0e3c177,0x6c16b32b,0x99b970a9,0xfa489411,0x2264e947, + 0xc48cfca8,0x1a3ff0a0,0xd82c7d56,0xef903322,0xc74e4987,0xc1d138d9, + 0xfea2ca8c,0x360bd498,0xcf81f5a6,0x28de7aa5,0x268eb7da,0xa4bfad3f, + 0xe49d3a2c,0xd927850,0x9bcc5f6a,0x62467e54,0xc2138df6,0xe8b8d890, + 0x5ef7392e,0xf5afc382,0xbe805d9f,0x7c93d069,0xa92dd56f,0xb31225cf, + 0x3b99acc8,0xa77d1810,0x6e639ce8,0x7bbb3bdb,0x97826cd,0xf418596e, + 0x1b79aec,0xa89a4f83,0x656e95e6,0x7ee6ffaa,0x8cfbc21,0xe6e815ef, + 0xd99be7ba,0xce366f4a,0xd4099fea,0xd67cb029,0xafb2a431,0x31233f2a, + 0x3094a5c6,0xc066a235,0x37bc4e74,0xa6ca82fc,0xb0d090e0,0x15d8a733, + 0x4a9804f1,0xf7daec41,0xe50cd7f,0x2ff69117,0x8dd64d76,0x4db0ef43, + 0x544daacc,0xdf0496e4,0xe3b5d19e,0x1b886a4c,0xb81f2cc1,0x7f516546, + 0x4ea5e9d,0x5d358c01,0x737487fa,0x2e410bfb,0x5a1d67b3,0x52d2db92, + 0x335610e9,0x1347d66d,0x8c61d79a,0x7a0ca137,0x8e14f859,0x893c13eb, + 0xee27a9ce,0x35c961b7,0xede51ce1,0x3cb1477a,0x59dfd29c,0x3f73f255, + 0x79ce1418,0xbf37c773,0xeacdf753,0x5baafd5f,0x146f3ddf,0x86db4478, + 0x81f3afca,0x3ec468b9,0x2c342438,0x5f40a3c2,0x72c31d16,0xc25e2bc, + 0x8b493c28,0x41950dff,0x7101a839,0xdeb30c08,0x9ce4b4d8,0x90c15664, + 0x6184cb7b,0x70b632d5,0x745c6c48,0x4257b8d0]; + + +pub struct AES { + nk: usize, + nr: usize, + mode: usize, + fkey: [u32;60], + rkey: [u32;60], + pub f: [u8;16] +} + +impl AES { + + fn rotl8(x: u32) -> u32 { + return ((x)<<8)|((x)>>24); + } + + fn rotl16(x: u32) -> u32 { + return ((x)<<16)|((x)>>16); + } + + fn rotl24(x: u32) -> u32 { + return ((x)<<24)|((x)>>8); + } + + fn pack(b: [u8;4]) -> u32 { /* pack bytes into a 32-bit Word */ + return ((((b[3])&0xff) as u32)<<24)|((((b[2])&0xff) as u32)<<16)|((((b[1])&0xff) as u32)<<8)|(((b[0])&0xff) as u32); + } + + fn unpack(a: u32) -> [u8;4] { /* unpack bytes from a word */ + let b:[u8;4]=[(a&0xff) as u8,((a>>8)&0xff) as u8,((a>>16)&0xff) as u8,((a>>24)&0xff) as u8]; + return b; + } + + fn bmul(x: u8,y: u8) -> u8 { /* x.y= AntiLog(Log(x) + Log(y)) */ + let ix=(x as usize)&0xff; + let iy=(y as usize)&0xff; + let lx=(LTAB[ix] as usize)&0xff; + let ly=(LTAB[iy] as usize)&0xff; + + if x != 0 && y != 0 { + return PTAB[(lx+ly)%255]; + } else {return 0} + } + + fn subbyte(a: u32) -> u32 { + let mut b=AES::unpack(a); + b[0]=FBSUB[b[0] as usize]; + b[1]=FBSUB[b[1] as usize]; + b[2]=FBSUB[b[2] as usize]; + b[3]=FBSUB[b[3] as usize]; + return AES::pack(b); + } + + fn product(x: u32,y: u32) -> u8 { /* dot product of two 4-byte arrays */ + let xb=AES::unpack(x); + let yb=AES::unpack(y); + + return AES::bmul(xb[0],yb[0])^AES::bmul(xb[1],yb[1])^AES::bmul(xb[2],yb[2])^AES::bmul(xb[3],yb[3]); + } + + fn invmixcol(x: u32) -> u32 { /* matrix Multiplication */ + let mut b:[u8;4]=[0;4]; + let mut m=AES::pack(INCO); + b[3]=AES::product(m,x); + m=AES::rotl24(m); + b[2]=AES::product(m,x); + m=AES::rotl24(m); + b[1]=AES::product(m,x); + m=AES::rotl24(m); + b[0]=AES::product(m,x); + let y=AES::pack(b); + return y; + } + + fn increment(f: &mut [u8;16]) { + for i in 0..16 { + f[i]+=1; + if f[i]!=0 {break} + } + } + + pub fn new() -> AES { + AES { + nk:0, + nr:0, + mode:0, + fkey:[0;60], + rkey:[0;60], + f:[0;16] + + } + } + +/* reset cipher */ + pub fn reset(&mut self,m: usize,iv: Option<[u8;16]>) { /* reset mode, or reset iv */ + self.mode=m; + for i in 0..16 {self.f[i]=0} + if self.mode != ECB + { + if let Some(x) = iv { + for i in 0..16 {self.f[i]=x[i]} + } + } + } + + pub fn init(&mut self,m: usize,nkey: usize,key: &[u8],iv: Option<[u8;16]>) -> bool { +/* Key Scheduler. Create expanded encryption key */ + let mut cipherkey:[u32;8]=[0;8]; + let mut b:[u8;4]=[0;4]; + let nk=nkey/4; + if nk!=4 && nk!=6 && nk!=8 {return false} + let nr=6+nk; + self.nk=nk; + self.nr=nr; + self.reset(m,iv); + let n=4*(nr+1); + + let mut j=0; + for i in 0..nk { + for k in 0..4 {b[k]=key[j+k]} + cipherkey[i]=AES::pack(b); + j+=4; + } + + for i in 0..nk {self.fkey[i]=cipherkey[i]} + j=nk; + let mut k=0; + while j<n { + self.fkey[j]=self.fkey[j-nk]^AES::subbyte(AES::rotl24(self.fkey[j-1]))^(RCO[k] as u32); + for i in 1..nk { + if (i+j) >= n {break} + self.fkey[i+j]=self.fkey[i+j-nk]^self.fkey[i+j-1]; + } + j+=nk; + k+=1; + } + + /* now for the expanded decrypt key in reverse order */ + + for j in 0..4 {self.rkey[j+n-4]=self.fkey[j]} + let mut i=4; + while i<n-4 { + let k=n-4-i; + for j in 0..4 {self.rkey[k+j]=AES::invmixcol(self.fkey[i+j])} + i+=4; + } + for j in n-4..n {self.rkey[j-n+4]=self.fkey[j]} + return true; + } + + pub fn getreg(&mut self) -> [u8;16] { + let mut ir:[u8;16]=[0;16]; + for i in 0..16 {ir[i]=self.f[i]} + return ir; + } + + /* Encrypt a single block */ + pub fn ecb_encrypt(&mut self,buff: &mut [u8;16]) { + let mut b:[u8;4]=[0;4]; + let mut p:[u32;4]=[0;4]; + let mut q:[u32;4]=[0;4]; + + let mut j=0; + for i in 0..4 { + for k in 0..4 {b[k]=buff[j+k]} + p[i]=AES::pack(b); + p[i]^=self.fkey[i]; + j+=4; + } + + let mut k=4; + + /* State alternates between p and q */ + for _ in 1..self.nr { + q[0]=self.fkey[k]^FTABLE[(p[0]&0xff) as usize]^AES::rotl8(FTABLE[((p[1]>>8)&0xff) as usize])^AES::rotl16(FTABLE[((p[2]>>16)&0xff) as usize])^AES::rotl24(FTABLE[((p[3]>>24)&0xff) as usize]); + + q[1]=self.fkey[k+1]^FTABLE[(p[1]&0xff) as usize]^AES::rotl8(FTABLE[((p[2]>>8)&0xff) as usize])^AES::rotl16(FTABLE[((p[3]>>16)&0xff) as usize])^AES::rotl24(FTABLE[((p[0]>>24)&0xff) as usize]); + + q[2]=self.fkey[k+2]^FTABLE[(p[2]&0xff) as usize]^AES::rotl8(FTABLE[((p[3]>>8)&0xff) as usize])^AES::rotl16(FTABLE[((p[0]>>16)&0xff) as usize])^AES::rotl24(FTABLE[((p[1]>>24)&0xff) as usize]); + + q[3]=self.fkey[k+3]^FTABLE[(p[3]&0xff) as usize]^AES::rotl8(FTABLE[((p[0]>>8)&0xff) as usize])^AES::rotl16(FTABLE[((p[1]>>16)&0xff) as usize])^AES::rotl24(FTABLE[((p[2]>>24)&0xff) as usize]); + + k+=4; + for j in 0..4 { + let t=p[j]; p[j]=q[j]; q[j]=t; + } + } + + /* Last Round */ + + q[0]=self.fkey[k]^(FBSUB[(p[0]&0xff) as usize] as u32)^AES::rotl8((FBSUB[((p[1]>>8)&0xff) as usize]) as u32)^AES::rotl16((FBSUB[((p[2]>>16)&0xff) as usize]) as u32)^AES::rotl24((FBSUB[((p[3]>>24)&0xff) as usize]) as u32); + + q[1]=self.fkey[k+1]^(FBSUB[(p[1]&0xff) as usize] as u32)^AES::rotl8((FBSUB[((p[2]>>8)&0xff) as usize]) as u32)^AES::rotl16((FBSUB[((p[3]>>16)&0xff) as usize]) as u32)^AES::rotl24((FBSUB[((p[0]>>24)&0xff) as usize]) as u32); + + q[2]=self.fkey[k+2]^(FBSUB[(p[2]&0xff) as usize] as u32)^AES::rotl8((FBSUB[((p[3]>>8)&0xff) as usize]) as u32)^AES::rotl16((FBSUB[((p[0]>>16)&0xff) as usize]) as u32)^AES::rotl24((FBSUB[((p[1]>>24)&0xff) as usize]) as u32); + + q[3]=self.fkey[k+3]^(FBSUB[(p[3]&0xff) as usize] as u32)^AES::rotl8((FBSUB[((p[0]>>8)&0xff) as usize]) as u32)^AES::rotl16((FBSUB[((p[1]>>16)&0xff) as usize]) as u32)^AES::rotl24((FBSUB[((p[2]>>24)&0xff) as usize]) as u32); + + j=0; + for i in 0..4 { + b=AES::unpack(q[i]); + for k in 0..4 {buff[j+k]=b[k]} + j+=4; + } + } + + /* Decrypt a single block */ + pub fn ecb_decrypt(&mut self,buff: &mut [u8;16]) { + let mut b:[u8;4]=[0;4]; + let mut p:[u32;4]=[0;4]; + let mut q:[u32;4]=[0;4]; + + let mut j=0; + for i in 0..4 { + for k in 0..4 {b[k]=buff[j+k]} + p[i]=AES::pack(b); + p[i]^=self.rkey[i]; + j+=4; + } + + let mut k=4; + + /* State alternates between p and q */ + for _ in 1..self.nr { + + q[0]=self.rkey[k]^RTABLE[(p[0]&0xff) as usize]^AES::rotl8(RTABLE[((p[3]>>8)&0xff) as usize])^AES::rotl16(RTABLE[((p[2]>>16)&0xff) as usize])^AES::rotl24(RTABLE[((p[1]>>24)&0xff) as usize]); + + q[1]=self.rkey[k+1]^RTABLE[(p[1]&0xff) as usize]^AES::rotl8(RTABLE[((p[0]>>8)&0xff) as usize])^AES::rotl16(RTABLE[((p[3]>>16)&0xff) as usize])^AES::rotl24(RTABLE[((p[2]>>24)&0xff) as usize]); + + + q[2]=self.rkey[k+2]^RTABLE[(p[2]&0xff) as usize]^AES::rotl8(RTABLE[((p[1]>>8)&0xff) as usize])^AES::rotl16(RTABLE[((p[0]>>16)&0xff) as usize])^AES::rotl24(RTABLE[((p[3]>>24)&0xff) as usize]); + + q[3]=self.rkey[k+3]^RTABLE[(p[3]&0xff) as usize]^AES::rotl8(RTABLE[((p[2]>>8)&0xff) as usize])^AES::rotl16(RTABLE[((p[1]>>16)&0xff) as usize])^AES::rotl24(RTABLE[((p[0]>>24)&0xff) as usize]); + + + k+=4; + for j in 0..4 { + let t=p[j]; p[j]=q[j]; q[j]=t; + } + } + + /* Last Round */ + + q[0]=self.rkey[k]^(RBSUB[(p[0]&0xff) as usize] as u32)^AES::rotl8((RBSUB[((p[3]>>8)&0xff) as usize]) as u32)^AES::rotl16((RBSUB[((p[2]>>16)&0xff) as usize]) as u32)^AES::rotl24((RBSUB[((p[1]>>24)&0xff) as usize]) as u32); + + q[1]=self.rkey[k+1]^(RBSUB[(p[1]&0xff) as usize] as u32)^AES::rotl8((RBSUB[((p[0]>>8)&0xff) as usize]) as u32)^AES::rotl16((RBSUB[((p[3]>>16)&0xff) as usize]) as u32)^AES::rotl24((RBSUB[((p[2]>>24)&0xff) as usize]) as u32); + + + q[2]=self.rkey[k+2]^(RBSUB[(p[2]&0xff) as usize] as u32)^AES::rotl8((RBSUB[((p[1]>>8)&0xff) as usize]) as u32)^AES::rotl16((RBSUB[((p[0]>>16)&0xff) as usize]) as u32)^AES::rotl24((RBSUB[((p[3]>>24)&0xff) as usize]) as u32); + + q[3]=self.rkey[k+3]^(RBSUB[((p[3])&0xff) as usize] as u32)^AES::rotl8((RBSUB[((p[2]>>8)&0xff) as usize]) as u32)^AES::rotl16((RBSUB[((p[1]>>16)&0xff) as usize]) as u32)^AES::rotl24((RBSUB[((p[0]>>24)&0xff) as usize]) as u32); + + j=0; + for i in 0..4 { + b=AES::unpack(q[i]); + for k in 0..4 {buff[j+k]=b[k]} + j+=4; + } + } + +/* Encrypt using selected mode of operation */ + pub fn encrypt(&mut self,buff: &mut [u8;16]) -> u32 { + let mut st:[u8;16]=[0;16]; + + // Supported Modes of Operation + + let mut fell_off: u32=0; + + match self.mode { + ECB => { + self.ecb_encrypt(buff); + return 0; + }, + CBC => { + for j in 0..16 {buff[j]^=self.f[j]} + self.ecb_encrypt(buff); + for j in 0..16 {self.f[j]=buff[j]} + return 0; + }, + + CFB1 | CFB2 | CFB4 => { + let bytes=self.mode-CFB1+1; + for j in 0..bytes {fell_off=(fell_off<<8)|(self.f[j] as u32)} + for j in 0..16 {st[j]=self.f[j]} + for j in bytes..16 {self.f[j-bytes]=self.f[j]} + self.ecb_encrypt(&mut st); + for j in 0..bytes { + buff[j]^=st[j]; + self.f[16-bytes+j]=buff[j]; + } + return fell_off; + }, + + OFB1 | OFB2 | OFB4 | OFB8 | OFB16 => { + let bytes=self.mode-OFB1+1; + for j in 0..16 {st[j]=self.f[j]} + self.ecb_encrypt(&mut st); + for j in 0..bytes {buff[j]^=st[j]} + for j in 0..16 {self.f[j]=st[j]} + + //self.ecb_encrypt(&mut (self.f)); + //for j in 0..bytes {buff[j]^=self.f[j]} + return 0; + }, + + CTR1 | CTR2 | CTR4 | CTR8 | CTR16 => { + let bytes=self.mode-CTR1+1; + for j in 0..16 {st[j]=self.f[j]} + self.ecb_encrypt(&mut st); + for j in 0..bytes {buff[j]^=st[j]} + AES::increment(&mut (self.f)); + return 0; + }, + + _ => { + return 0; + } + } + } + + /* Decrypt using selected mode of operation */ + pub fn decrypt(&mut self,buff: &mut [u8;16]) -> u32 { + + let mut st:[u8;16]=[0;16]; + + // Supported Modes of Operation + + let mut fell_off: u32=0; + + match self.mode { + ECB => { + self.ecb_decrypt(buff); + return 0; + }, + CBC => { + for j in 0..16 { + st[j]=self.f[j]; + self.f[j]=buff[j]; + } + self.ecb_decrypt(buff); + for j in 0..16 { + buff[j]^=st[j]; + st[j]=0; + } + return 0; + }, + CFB1 | CFB2 | CFB4 => { + let bytes=self.mode-CFB1+1; + for j in 0..bytes {fell_off=(fell_off<<8)|(self.f[j] as u32)} + for j in 0..16 {st[j]=self.f[j]} + for j in bytes..16 {self.f[j-bytes]=self.f[j]} + self.ecb_encrypt(&mut st); + for j in 0..bytes { + self.f[16-bytes+j]=buff[j]; + buff[j]^=st[j]; + } + return fell_off; + }, + OFB1 | OFB2 | OFB4 | OFB8 | OFB16 => { + let bytes=self.mode-OFB1+1; + for j in 0..16 {st[j]=self.f[j]} + self.ecb_encrypt(&mut st); + for j in 0..bytes {buff[j]^=st[j]} + for j in 0..16 {self.f[j]=st[j]} + // self.ecb_encrypt(A.f[:]); + // for j in 0..bytes {buff[j]^=self.f[j]} + return 0; + }, + + CTR1 | CTR2 | CTR4 | CTR8 | CTR16 => { + let bytes=self.mode-CTR1+1; + for j in 0..16 {st[j]=self.f[j]} + self.ecb_encrypt(&mut st); + for j in 0..bytes {buff[j]^=st[j]} + AES::increment(&mut (self.f)); + return 0; + }, + + _ => { + return 0; + } + } + } + +/* Clean up and delete left-overs */ + pub fn end(&mut self) { // clean up + for i in 0..4*(self.nr+1) {self.fkey[i]=0; self.rkey[i]=0} + for i in 0..16 {self.f[i]=0} + } +} + +/* +fn main() +{ + let mut key:[u8;32]=[0;32]; + let mut block:[u8;16]=[0;16]; + let mut iv: [u8;16] = [0;16]; + + for i in 0..32 {key[i]=0} + key[0]=1; + for i in 0..16 {iv[i]=i as u8} + for i in 0..16 {block[i]=i as u8} + + let mut aes=AES::new(); + aes.init(CTR16,32,&key,Some(iv)); + + println!("Plain= "); + for i in 0..16 {print!("{:02x} ",block[i])} + println!(""); + + aes.encrypt(&mut block); + + println!("Encrypt= "); + for i in 0..16 {print!("{:02x} ",block[i])} + println!(""); + + aes.reset(CTR16,Some(iv)); + aes.decrypt(&mut block); + + println!("Decrypt= "); + for i in 0..16 {print!("{:02x} ",block[i])} + println!(""); + + aes.end(); +} +*/
