From 09db28deeddfb3199db2a640f7132b9aeebf47b6 Mon Sep 17 00:00:00 2001 From: Yi-Cyuan Date: Wed, 23 Sep 2015 17:13:07 +0800 Subject: [PATCH] Support update interface. --- CHANGELOG.md | 4 + README.md | 17 +++ build/sha3.min.js | 27 ++-- src/sha3.js | 302 ++++++++++++++++++++++++++------------------ tests/test-shake.js | 9 ++ tests/test.js | 20 ++- 6 files changed, 246 insertions(+), 133 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9e4648..e330967 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v0.5.0 / 2015-09-23 + +* Support update interface. + # v0.4.1 / 2015-09-18 * Support to output Integer Array. diff --git a/README.md b/README.md index b4623f5..40e935f 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,23 @@ var buffer = keccak_224.buffer('Message to hash'); // Support Array output var buffer = keccak_224.array('Message to hash'); + +// update hash +sha3_512.update('Message ').update('to ').update('hash').hex(); +// specify shake output bits at first update +shake_128.update('Message ', 256).update('to ').update('hash').hex(); + +// or to use create +var hash = sha3_512.create(); +hash.update('...'); +hash.update('...'); +hash.hex(); + +// specify shake output bits when creating +var hash = shake_128.create(256); +hash.update('...'); +hash.update('...'); +hash.hex(); ``` If you use node.js, you should require the module first: ```JavaScript diff --git a/build/sha3.min.js b/build/sha3.min.js index 499d3a4..5a77525 100644 --- a/build/sha3.min.js +++ b/build/sha3.min.js @@ -1,5 +1,5 @@ /* - * js-sha3 v0.4.1 + * js-sha3 v0.5.0 * https://github.com/emn178/js-sha3 * * Copyright 2015, emn178@gmail.com @@ -7,14 +7,17 @@ * Licensed under the MIT license: * http://www.opensource.org/licenses/MIT */ -(function(E,Da){var xa="undefined"!=typeof module;xa&&(E=global,E.JS_SHA3_TEST&&(E.navigator={userAgent:"Chrome"}));for(var g="0123456789abcdef".split(""),r=[0,8,16,24],ya=[1,0,32898,0,32906,2147483648,2147516416,2147483648,32907,0,2147483649,0,2147516545,2147483648,32777,2147483648,138,0,136,0,2147516425,0,2147483658,0,2147516555,0,139,2147483648,32905,2147483648,32771,2147483648,32770,2147483648,128,2147483648,32778,0,2147483658,2147483648,2147516545,2147483648,32896,2147483648,2147483649,0,2147516424, -2147483648],m=[224,256,384,512],za=["hex","buffer","shake"],p=function(a,e,l){return function(f){return Aa(f,a,e,a,l)}},m=[{name:"keccak",padding:[1,256,65536,16777216],bits:m,createMethod:p},{name:"sha3",padding:[6,1536,393216,100663296],bits:m,createMethod:p},{name:"shake",padding:[31,7936,2031616,520093696],bits:[128,256],createMethod:function(a,e,l){return function(f,g){return Aa(f,a,e,g,l)}}}],e=[],a=[],F={},ua=0;uab;++b)a[b]=0;p=0;do{e[0]=p;for(b=1;b> -2]|=k[n]<h?e[b>>2]|=h<h?e[b>>2]|=(192|h>>6)<h||57344<=h?e[b>>2]|=(224|h>>12)<>2]|=(240|h>>18)<>2]|=(128|h>>12&63)<>2]|=(128|h>>6&63)<>2]|=(128|h&63)<>2]|=l[b&3],++n);p=e[t];n>G&&bb;b+=2)u=a[0]^a[10]^a[20]^a[30]^ -a[40],v=a[1]^a[11]^a[21]^a[31]^a[41],w=a[2]^a[12]^a[22]^a[32]^a[42],x=a[3]^a[13]^a[23]^a[33]^a[43],y=a[4]^a[14]^a[24]^a[34]^a[44],z=a[5]^a[15]^a[25]^a[35]^a[45],A=a[6]^a[16]^a[26]^a[36]^a[46],B=a[7]^a[17]^a[27]^a[37]^a[47],C=a[8]^a[18]^a[28]^a[38]^a[48],D=a[9]^a[19]^a[29]^a[39]^a[49],c=C^(w<<1|x>>>31),d=D^(x<<1|w>>>31),a[0]^=c,a[1]^=d,a[10]^=c,a[11]^=d,a[20]^=c,a[21]^=d,a[30]^=c,a[31]^=d,a[40]^=c,a[41]^=d,c=u^(y<<1|z>>>31),d=v^(z<<1|y>>>31),a[2]^=c,a[3]^=d,a[12]^=c,a[13]^=d,a[22]^=c,a[23]^=d,a[32]^= -c,a[33]^=d,a[42]^=c,a[43]^=d,c=w^(A<<1|B>>>31),d=x^(B<<1|A>>>31),a[4]^=c,a[5]^=d,a[14]^=c,a[15]^=d,a[24]^=c,a[25]^=d,a[34]^=c,a[35]^=d,a[44]^=c,a[45]^=d,c=y^(C<<1|D>>>31),d=z^(D<<1|C>>>31),a[6]^=c,a[7]^=d,a[16]^=c,a[17]^=d,a[26]^=c,a[27]^=d,a[36]^=c,a[37]^=d,a[46]^=c,a[47]^=d,c=A^(u<<1|v>>>31),d=B^(v<<1|u>>>31),a[8]^=c,a[9]^=d,a[18]^=c,a[19]^=d,a[28]^=c,a[29]^=d,a[38]^=c,a[39]^=d,a[48]^=c,a[49]^=d,c=a[0],d=a[1],ba=a[11]<<4|a[10]>>>28,ca=a[10]<<4|a[11]>>>28,J=a[20]<<3|a[21]>>>29,K=a[21]<<3|a[20]>>> -29,pa=a[31]<<9|a[30]>>>23,qa=a[30]<<9|a[31]>>>23,X=a[40]<<18|a[41]>>>14,Y=a[41]<<18|a[40]>>>14,P=a[2]<<1|a[3]>>>31,Q=a[3]<<1|a[2]>>>31,u=a[13]<<12|a[12]>>>20,v=a[12]<<12|a[13]>>>20,da=a[22]<<10|a[23]>>>22,ea=a[23]<<10|a[22]>>>22,L=a[33]<<13|a[32]>>>19,M=a[32]<<13|a[33]>>>19,ra=a[42]<<2|a[43]>>>30,sa=a[43]<<2|a[42]>>>30,ja=a[5]<<30|a[4]>>>2,ka=a[4]<<30|a[5]>>>2,R=a[14]<<6|a[15]>>>26,S=a[15]<<6|a[14]>>>26,w=a[25]<<11|a[24]>>>21,x=a[24]<<11|a[25]>>>21,fa=a[34]<<15|a[35]>>>17,ga=a[35]<<15|a[34]>>>17, -N=a[45]<<29|a[44]>>>3,O=a[44]<<29|a[45]>>>3,C=a[6]<<28|a[7]>>>4,D=a[7]<<28|a[6]>>>4,la=a[17]<<23|a[16]>>>9,ma=a[16]<<23|a[17]>>>9,T=a[26]<<25|a[27]>>>7,U=a[27]<<25|a[26]>>>7,y=a[36]<<21|a[37]>>>11,z=a[37]<<21|a[36]>>>11,ha=a[47]<<24|a[46]>>>8,ia=a[46]<<24|a[47]>>>8,Z=a[8]<<27|a[9]>>>5,aa=a[9]<<27|a[8]>>>5,H=a[18]<<20|a[19]>>>12,I=a[19]<<20|a[18]>>>12,na=a[29]<<7|a[28]>>>25,oa=a[28]<<7|a[29]>>>25,V=a[38]<<8|a[39]>>>24,W=a[39]<<8|a[38]>>>24,A=a[48]<<14|a[49]>>>18,B=a[49]<<14|a[48]>>>18,a[0]=c^~u&w, -a[1]=d^~v&x,a[10]=C^~H&J,a[11]=D^~I&K,a[20]=P^~R&T,a[21]=Q^~S&U,a[30]=Z^~ba&da,a[31]=aa^~ca&ea,a[40]=ja^~la&na,a[41]=ka^~ma&oa,a[2]=u^~w&y,a[3]=v^~x&z,a[12]=H^~J&L,a[13]=I^~K&M,a[22]=R^~T&V,a[23]=S^~U&W,a[32]=ba^~da&fa,a[33]=ca^~ea&ga,a[42]=la^~na&pa,a[43]=ma^~oa&qa,a[4]=w^~y&A,a[5]=x^~z&B,a[14]=J^~L&N,a[15]=K^~M&O,a[24]=T^~V&X,a[25]=U^~W&Y,a[34]=da^~fa&ha,a[35]=ea^~ga&ia,a[44]=na^~pa&ra,a[45]=oa^~qa&sa,a[6]=y^~A&c,a[7]=z^~B&d,a[16]=L^~N&C,a[17]=M^~O&D,a[26]=V^~X&P,a[27]=W^~Y&Q,a[36]=fa^~ha&Z,a[37]= -ga^~ia&aa,a[46]=pa^~ra&ja,a[47]=qa^~sa&ka,a[8]=A^~c&u,a[9]=B^~d&v,a[18]=N^~C&H,a[19]=O^~D&I,a[28]=X^~P&R,a[29]=Y^~Q&S,a[38]=ha^~Z&ba,a[39]=ia^~aa&ca,a[48]=ra^~ja&la,a[49]=sa^~ka&ma,a[0]^=ya[b],a[1]^=ya[b+1]}while(!F);k=parseInt(f/32);l=parseInt(f%32/8);if("buffer"==q){f/=8;q=l?new ArrayBuffer(4*(k+1)):new ArrayBuffer(f);m=new Uint32Array(q);for(b=0;b>4&15]+g[c&15]+g[c>>12&15]+g[c>>8&15]+g[c>>20&15]+g[c>>16& -15]+g[c>>28&15]+g[c>>24&15];l&&(c=a[b],0>4&15]+g[c&15]),1>12&15]+g[c>>8&15]),2>20&15]+g[c>>16&15]));return f};if(!E.JS_SHA3_TEST&&xa)module.exports=F;else if(E)for(var Ca in F)E[Ca]=F[Ca]})(this); \ No newline at end of file +(function(r,la){function n(a,b,c){this.blocks=[];this.s=[];this.padding=b;this.outputBits=c;this.reset=!0;this.start=this.block=0;this.blockCount=1600-(a<<1)>>5;this.byteCount=this.blockCount<<2;this.outputBlocks=c>>5;this.extraBytes=(c&31)>>3;for(t=0;50>t;++t)this.s[t]=0}var fa="undefined"!=typeof module;fa&&(r=global,r.JS_SHA3_TEST&&(r.navigator={userAgent:"Chrome"}));for(var l="0123456789abcdef".split(""),p=[0,8,16,24],ga=[1,0,32898,0,32906,2147483648,2147516416,2147483648,32907,0,2147483649,0, +2147516545,2147483648,32777,2147483648,138,0,136,0,2147516425,0,2147483658,0,2147516555,0,139,2147483648,32905,2147483648,32771,2147483648,32770,2147483648,128,2147483648,32778,0,2147483658,2147483648,2147516545,2147483648,32896,2147483648,2147483649,0,2147516424,2147483648],u=[224,256,384,512],x=["hex","buffer","array"],ha=function(a,b,c){return function(e){return(new n(a,b,a)).update(e)[c]()}},ia=function(a,b,c){return function(e,g){return(new n(a,b,g)).update(e)[c]()}},q=function(a,b){var c=ha(a, +b,"hex");c.create=function(){return new n(a,b,a)};c.update=function(a){return c.create().update(a)};for(var e=0;e>2]|=a[h]<m?e[d>>2]|=m<m?e[d>>2]|=(192|m>>6)<m||57344<=m?e[d>>2]|=(224|m>>12)<>2]|=(240|m>>18)<>2]|=(128|m>>12&63)<>2]|=(128|m>>6&63)<>2]|=(128|m&63)<=g){this.start=d-g;this.block=e[k];for(d=0;d>2]|=this.padding[b&3];if(this.lastByteIndex==this.byteCount)for(a[0]=a[c],b=1;b>4&15]+l[f&15]+l[f>>12&15]+l[f>>8&15]+l[f>> +20&15]+l[f>>16&15]+l[f>>28&15]+l[f>>24&15];0==k%a&&w(b)}e&&(f=b[g],0>4&15]+l[f&15]),1>12&15]+l[f>>8&15]),2>20&15]+l[f>>16&15]));return h};n.prototype.buffer=function(){this.finalize();var a=this.blockCount,b=this.s,c=this.outputBlocks,e=this.extraBytes,g=0,k=0,h=this.outputBits>>3,f;f=e?new ArrayBuffer(c+1<<2):new ArrayBuffer(h);for(var d=new Uint32Array(f);k>8&255,h[f+2]=d>>16&255,h[f+3]=d>>24&255;0==k%a&&w(b)}e&&(f=k<<2,d=b[g],0>8&255),2>16&255));return h};var w=function(a){var b,c,e,g,k,h,f,d,m,l,n,p,q,r,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,aa,ba,ca,da;for(e=0;48>e;e+=2)g=a[0]^ +a[10]^a[20]^a[30]^a[40],k=a[1]^a[11]^a[21]^a[31]^a[41],h=a[2]^a[12]^a[22]^a[32]^a[42],f=a[3]^a[13]^a[23]^a[33]^a[43],d=a[4]^a[14]^a[24]^a[34]^a[44],m=a[5]^a[15]^a[25]^a[35]^a[45],l=a[6]^a[16]^a[26]^a[36]^a[46],n=a[7]^a[17]^a[27]^a[37]^a[47],p=a[8]^a[18]^a[28]^a[38]^a[48],q=a[9]^a[19]^a[29]^a[39]^a[49],b=p^(h<<1|f>>>31),c=q^(f<<1|h>>>31),a[0]^=b,a[1]^=c,a[10]^=b,a[11]^=c,a[20]^=b,a[21]^=c,a[30]^=b,a[31]^=c,a[40]^=b,a[41]^=c,b=g^(d<<1|m>>>31),c=k^(m<<1|d>>>31),a[2]^=b,a[3]^=c,a[12]^=b,a[13]^=c,a[22]^= +b,a[23]^=c,a[32]^=b,a[33]^=c,a[42]^=b,a[43]^=c,b=h^(l<<1|n>>>31),c=f^(n<<1|l>>>31),a[4]^=b,a[5]^=c,a[14]^=b,a[15]^=c,a[24]^=b,a[25]^=c,a[34]^=b,a[35]^=c,a[44]^=b,a[45]^=c,b=d^(p<<1|q>>>31),c=m^(q<<1|p>>>31),a[6]^=b,a[7]^=c,a[16]^=b,a[17]^=c,a[26]^=b,a[27]^=c,a[36]^=b,a[37]^=c,a[46]^=b,a[47]^=c,b=l^(g<<1|k>>>31),c=n^(k<<1|g>>>31),a[8]^=b,a[9]^=c,a[18]^=b,a[19]^=c,a[28]^=b,a[29]^=c,a[38]^=b,a[39]^=c,a[48]^=b,a[49]^=c,b=a[0],c=a[1],M=a[11]<<4|a[10]>>>28,N=a[10]<<4|a[11]>>>28,u=a[20]<<3|a[21]>>>29,v= +a[21]<<3|a[20]>>>29,aa=a[31]<<9|a[30]>>>23,ba=a[30]<<9|a[31]>>>23,I=a[40]<<18|a[41]>>>14,J=a[41]<<18|a[40]>>>14,A=a[2]<<1|a[3]>>>31,B=a[3]<<1|a[2]>>>31,g=a[13]<<12|a[12]>>>20,k=a[12]<<12|a[13]>>>20,O=a[22]<<10|a[23]>>>22,P=a[23]<<10|a[22]>>>22,w=a[33]<<13|a[32]>>>19,x=a[32]<<13|a[33]>>>19,ca=a[42]<<2|a[43]>>>30,da=a[43]<<2|a[42]>>>30,U=a[5]<<30|a[4]>>>2,V=a[4]<<30|a[5]>>>2,C=a[14]<<6|a[15]>>>26,D=a[15]<<6|a[14]>>>26,h=a[25]<<11|a[24]>>>21,f=a[24]<<11|a[25]>>>21,Q=a[34]<<15|a[35]>>>17,R=a[35]<<15| +a[34]>>>17,y=a[45]<<29|a[44]>>>3,z=a[44]<<29|a[45]>>>3,p=a[6]<<28|a[7]>>>4,q=a[7]<<28|a[6]>>>4,W=a[17]<<23|a[16]>>>9,X=a[16]<<23|a[17]>>>9,E=a[26]<<25|a[27]>>>7,F=a[27]<<25|a[26]>>>7,d=a[36]<<21|a[37]>>>11,m=a[37]<<21|a[36]>>>11,S=a[47]<<24|a[46]>>>8,T=a[46]<<24|a[47]>>>8,K=a[8]<<27|a[9]>>>5,L=a[9]<<27|a[8]>>>5,r=a[18]<<20|a[19]>>>12,t=a[19]<<20|a[18]>>>12,Y=a[29]<<7|a[28]>>>25,Z=a[28]<<7|a[29]>>>25,G=a[38]<<8|a[39]>>>24,H=a[39]<<8|a[38]>>>24,l=a[48]<<14|a[49]>>>18,n=a[49]<<14|a[48]>>>18,a[0]=b^~g& +h,a[1]=c^~k&f,a[10]=p^~r&u,a[11]=q^~t&v,a[20]=A^~C&E,a[21]=B^~D&F,a[30]=K^~M&O,a[31]=L^~N&P,a[40]=U^~W&Y,a[41]=V^~X&Z,a[2]=g^~h&d,a[3]=k^~f&m,a[12]=r^~u&w,a[13]=t^~v&x,a[22]=C^~E&G,a[23]=D^~F&H,a[32]=M^~O&Q,a[33]=N^~P&R,a[42]=W^~Y&aa,a[43]=X^~Z&ba,a[4]=h^~d&l,a[5]=f^~m&n,a[14]=u^~w&y,a[15]=v^~x&z,a[24]=E^~G&I,a[25]=F^~H&J,a[34]=O^~Q&S,a[35]=P^~R&T,a[44]=Y^~aa&ca,a[45]=Z^~ba&da,a[6]=d^~l&b,a[7]=m^~n&c,a[16]=w^~y&p,a[17]=x^~z&q,a[26]=G^~I&A,a[27]=H^~J&B,a[36]=Q^~S&K,a[37]=R^~T&L,a[46]=aa^~ca&U,a[47]= +ba^~da&V,a[8]=l^~b&g,a[9]=n^~c&k,a[18]=y^~p&r,a[19]=z^~q&t,a[28]=I^~A&C,a[29]=J^~B&D,a[38]=S^~K&M,a[39]=T^~L&N,a[48]=ca^~U&W,a[49]=da^~V&X,a[0]^=ga[e],a[1]^=ga[e+1]};if(!r.JS_SHA3_TEST&&fa)module.exports=y;else if(r)for(var ja in y)r[ja]=y[ja]})(this); \ No newline at end of file diff --git a/src/sha3.js b/src/sha3.js index 4a5e67b..b1331e0 100644 --- a/src/sha3.js +++ b/src/sha3.js @@ -1,5 +1,5 @@ /* - * js-sha3 v0.4.1 + * js-sha3 v0.5.0 * https://github.com/emn178/js-sha3 * * Copyright 2015, emn178@gmail.com @@ -31,69 +31,106 @@ var SHAKE_BITS = [128, 256]; var OUTPUT_TYPES = ['hex', 'buffer', 'array']; - var createMethod = function(bits, padding, outputType) { + var createOutputMethod = function(bits, padding, outputType) { return function(message) { - return keccak(message, bits, padding, bits, outputType); + return new Keccak(bits, padding, bits).update(message)[outputType](); } }; - var createShakeMethod = function(bits, padding, outputType) { + var createShakeOutputMethod = function(bits, padding, outputType) { return function(message, outputBits) { - return keccak(message, bits, padding, outputBits, outputType); + return new Keccak(bits, padding, outputBits).update(message)[outputType](); } }; + var createMethod = function(bits, padding) { + var method = createOutputMethod(bits, padding, 'hex'); + method.create = function() { + return new Keccak(bits, padding, bits); + }; + method.update = function(message) { + return method.create().update(message); + }; + for(var i = 0;i < OUTPUT_TYPES.length;++i) { + var type = OUTPUT_TYPES[i]; + method[type] = createOutputMethod(bits, padding, type); + } + return method; + }; + + var createShakeMethod = function(bits, padding) { + var method = createShakeOutputMethod(bits, padding, 'hex'); + method.create = function(outputBits) { + return new Keccak(bits, padding, outputBits); + }; + method.update = function(message, outputBits) { + return method.create(outputBits).update(message); + }; + for(var i = 0;i < OUTPUT_TYPES.length;++i) { + var type = OUTPUT_TYPES[i]; + method[type] = createShakeOutputMethod(bits, padding, type); + } + return method; + }; + var algorithms = [ {name: 'keccak', padding: KECCAK_PADDING, bits: BITS, createMethod: createMethod}, {name: 'sha3', padding: PADDING, bits: BITS, createMethod: createMethod}, {name: 'shake', padding: SHAKE_PADDING, bits: SHAKE_BITS, createMethod: createShakeMethod} ]; - var blocks = [], s = [], methods = {}; + var methods = {}; for(var i = 0;i < algorithms.length;++i) { var algorithm = algorithms[i]; var bits = algorithm.bits; var createMethod = algorithm.createMethod; for(var j = 0;j < bits.length;++j) { - (function(algorithm, bits) { - var method = createMethod(bits, algorithm.padding, 'hex'); - methods[algorithm.name +'_' + bits] = method; - for(var k = 0;k < OUTPUT_TYPES.length;++k) { - var type = OUTPUT_TYPES[k]; - method[type] = createMethod(bits, algorithm.padding, type); - } - })(algorithm, bits[j]); + var method = algorithm.createMethod(bits[j], algorithm.padding); + methods[algorithm.name +'_' + bits[j]] = method; } } - var keccak = function(message, bits, padding, outputBits, outputType) { - var notString = typeof(message) != 'string'; - if(notString && message.constructor == root.ArrayBuffer) { - message = new Uint8Array(message); - } - - var block, code, end = false, index = 0, start = 0, length = message.length, - i, j, h; - var blockCount = (1600 - (bits << 1)) >> 5; - var byteCount = blockCount << 2; + function Keccak(bits, padding, outputBits) { + this.blocks = []; + this.s = []; + this.padding = padding; + this.outputBits = outputBits; + this.reset = true; + this.block = 0; + this.start = 0; + this.blockCount = (1600 - (bits << 1)) >> 5; + this.byteCount = this.blockCount << 2; + this.outputBlocks = outputBits >> 5; + this.extraBytes = (outputBits & 31) >> 3; for(i = 0;i < 50;++i) { - s[i] = 0; + this.s[i] = 0; } + }; - block = 0; - do { - blocks[0] = block; - for(i = 1;i < blockCount + 1;++i) { - blocks[i] = 0; + Keccak.prototype.update = function(message) { + var notString = typeof(message) != 'string'; + if(notString && message.constructor == root.ArrayBuffer) { + message = new Uint8Array(message); + } + var length = message.length, blocks = this.blocks, byteCount = this.byteCount, + blockCount = this.blockCount, index = 0, s = this.s, i, code; + + while(index < length) { + if(this.reset) { + this.reset = false; + blocks[0] = this.block; + for(i = 1;i < blockCount + 1;++i) { + blocks[i] = 0; + } } if(notString) { - for (i = start;index < length && i < byteCount; ++index) { + for (i = this.start;index < length && i < byteCount; ++index) { blocks[i >> 2] |= message[index] << SHIFT[i++ & 3]; } } else { - for (i = start;index < length && i < byteCount; ++index) { + for (i = this.start;index < length && i < byteCount; ++index) { code = message.charCodeAt(index); if (code < 0x80) { blocks[i >> 2] |= code << SHIFT[i++ & 3]; @@ -113,109 +150,135 @@ } } } - start = i - byteCount; - if(index == length) { - blocks[i >> 2] |= padding[i & 3]; - ++index; - } - block = blocks[blockCount]; - if(index > length && i < byteCount) { - blocks[blockCount - 1] |= 0x80000000; - end = true; + this.lastByteIndex = i; + if(i >= byteCount) { + this.start = i - byteCount; + this.block = blocks[blockCount]; + for(i = 0;i < blockCount;++i) { + s[i] ^= blocks[i]; + } + f(s); + this.reset = true; + } else { + this.start = i; } + } + return this; + }; - for(i = 0;i < blockCount;++i) { - s[i] ^= blocks[i]; + Keccak.prototype.finalize = function() { + var blocks = this.blocks, i = this.lastByteIndex, blockCount = this.blockCount, s = this.s; + blocks[i >> 2] |= this.padding[i & 3]; + if(this.lastByteIndex == this.byteCount) { + blocks[0] = blocks[blockCount]; + for(i = 1;i < blockCount + 1;++i) { + blocks[i] = 0; } + } + blocks[blockCount - 1] |= 0x80000000; + for(i = 0;i < blockCount;++i) { + s[i] ^= blocks[i]; + } + f(s); + }; - f(); - } while(!end); + Keccak.prototype.toString = Keccak.prototype.hex = function() { + this.finalize(); - var outputBlocks = outputBits >> 5; - var extraBytes = (outputBits & 31) >> 3; - j = 0, i = 0; - if(outputType == 'buffer') { - var bytes = outputBits >> 3; - var buffer; - if(extraBytes) { - buffer = new ArrayBuffer((outputBlocks + 1) << 2); - } else { - buffer = new ArrayBuffer(bytes); + var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks, + extraBytes = this.extraBytes, i = 0, j = 0; + var hex = '', block; + while(j < outputBlocks) { + for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) { + block = s[i]; + hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F] + + HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F] + + HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F] + + HEX_CHARS[(block >> 28) & 0x0F] + HEX_CHARS[(block >> 24) & 0x0F]; } - var array = new Uint32Array(buffer); - while(j < outputBlocks) { - for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) { - array[j] = s[i]; - } - if(j % blockCount == 0) { - f(); - } + if(j % blockCount == 0) { + f(s); } - if(extraBytes) { - array[i] = s[i]; - buffer = buffer.slice(0, bytes); + } + if(extraBytes) { + block = s[i]; + if(extraBytes > 0) { + hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F]; } - return buffer; - } else if(outputType == 'array') { - var array = [], offset; - while(j < outputBlocks) { - for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) { - offset = j << 2; - h = s[i]; - array[offset] = h & 0xFF; - array[offset + 1] = (h >> 8) & 0xFF; - array[offset + 2] = (h >> 16) & 0xFF; - array[offset + 3] = (h >> 24) & 0xFF; - } - if(j % blockCount == 0) { - f(); - } + if(extraBytes > 1) { + hex += HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F]; } - if(extraBytes) { - offset = j << 2; - h = s[i]; - if(extraBytes > 0) { - array[offset] = h & 0xFF; - } - if(extraBytes > 1) { - array[offset + 1] = (h >> 8) & 0xFF; - } - if(extraBytes > 2) { - array[offset + 2] = (h >> 16) & 0xFF; - } + if(extraBytes > 2) { + hex += HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F]; } - return array; + } + return hex; + }; + + Keccak.prototype.buffer = function() { + this.finalize(); + + var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks, + extraBytes = this.extraBytes, i = 0, j = 0; + var bytes = this.outputBits >> 3; + var buffer; + if(extraBytes) { + buffer = new ArrayBuffer((outputBlocks + 1) << 2); } else { - var hex = ''; - while(j < outputBlocks) { - for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) { - h = s[i]; - hex += HEX_CHARS[(h >> 4) & 0x0F] + HEX_CHARS[h & 0x0F] + - HEX_CHARS[(h >> 12) & 0x0F] + HEX_CHARS[(h >> 8) & 0x0F] + - HEX_CHARS[(h >> 20) & 0x0F] + HEX_CHARS[(h >> 16) & 0x0F] + - HEX_CHARS[(h >> 28) & 0x0F] + HEX_CHARS[(h >> 24) & 0x0F]; - } - if(j % blockCount == 0) { - f(); - } + buffer = new ArrayBuffer(bytes); + } + var array = new Uint32Array(buffer); + while(j < outputBlocks) { + for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) { + array[j] = s[i]; } - if(extraBytes) { - h = s[i]; - if(extraBytes > 0) { - hex += HEX_CHARS[(h >> 4) & 0x0F] + HEX_CHARS[h & 0x0F]; - } - if(extraBytes > 1) { - hex += HEX_CHARS[(h >> 12) & 0x0F] + HEX_CHARS[(h >> 8) & 0x0F]; - } - if(extraBytes > 2) { - hex += HEX_CHARS[(h >> 20) & 0x0F] + HEX_CHARS[(h >> 16) & 0x0F]; - } + if(j % blockCount == 0) { + f(s); + } + } + if(extraBytes) { + array[i] = s[i]; + buffer = buffer.slice(0, bytes); + } + return buffer; + }; + + Keccak.prototype.digest = Keccak.prototype.array = function() { + this.finalize(); + + var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks, + extraBytes = this.extraBytes, i = 0, j = 0; + var array = [], offset, block; + while(j < outputBlocks) { + for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) { + offset = j << 2; + block = s[i]; + array[offset] = block & 0xFF; + array[offset + 1] = (block >> 8) & 0xFF; + array[offset + 2] = (block >> 16) & 0xFF; + array[offset + 3] = (block >> 24) & 0xFF; + } + if(j % blockCount == 0) { + f(s); + } + } + if(extraBytes) { + offset = j << 2; + block = s[i]; + if(extraBytes > 0) { + array[offset] = block & 0xFF; + } + if(extraBytes > 1) { + array[offset + 1] = (block >> 8) & 0xFF; + } + if(extraBytes > 2) { + array[offset + 2] = (block >> 16) & 0xFF; } - return hex; } + return array; }; - var f = function() { + var f = function(s) { var h, l, n, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32, b33, @@ -400,7 +463,6 @@ } } - if(!root.JS_SHA3_TEST && NODE_JS) { module.exports = methods; } else if(root) { diff --git a/tests/test-shake.js b/tests/test-shake.js index eb4aaf1..31dad42 100644 --- a/tests/test-shake.js +++ b/tests/test-shake.js @@ -20,6 +20,8 @@ it('should be equal', function() { expect(shake_128('', 16)).to.be('7f9c'); expect(shake_128('', 24)).to.be('7f9c2b'); + expect(shake_128.array('', 16)).to.eql([0x7f, 0x9c]); + expect(shake_128.array('', 24)).to.eql([0x7f, 0x9c, 0x2b]); }); }); @@ -54,6 +56,13 @@ expect(shake_256.array([0x3A,0x3A,0x81,0x9C,0x48,0xEF,0xDE,0x2A,0xD9,0x14,0xFB,0xF0,0x0E,0x18,0xAB,0x6B,0xC4,0xF1,0x45,0x13,0xAB,0x27,0xD0,0xC1,0x78,0xA1,0x88,0xB6,0x14,0x31,0xE7,0xF5,0x62,0x3C,0xB6,0x6B,0x23,0x34,0x67,0x75,0xD3,0x86,0xB5,0x0E,0x98,0x2C,0x49,0x3A,0xDB,0xBF,0xC5,0x4B,0x9A,0x3C,0xD3,0x83,0x38,0x23,0x36,0xA1,0xA0,0xB2,0x15,0x0A,0x15,0x35,0x8F,0x33,0x6D,0x03,0xAE,0x18,0xF6,0x66,0xC7,0x57,0x3D,0x55,0xC4,0xFD,0x18,0x1C,0x29,0xE6,0xCC,0xFD,0xE6,0x3E,0xA3,0x5F,0x0A,0xDF,0x58,0x85,0xCF,0xC0,0xA3,0xD8,0x4A,0x2B,0x2E,0x4D,0xD2,0x44,0x96,0xDB,0x78,0x9E,0x66,0x31,0x70,0xCE,0xF7,0x47,0x98,0xAA,0x1B,0xBC,0xD4,0x57,0x4E,0xA0,0xBB,0xA4,0x04,0x89,0xD7,0x64,0xB2,0xF8,0x3A,0xAD,0xC6,0x6B,0x14,0x8B,0x4A,0x0C,0xD9,0x52,0x46,0xC1,0x27,0xD5,0x87,0x1C,0x4F,0x11,0x41,0x86,0x90,0xA5,0xDD,0xF0,0x12,0x46,0xA0,0xC8,0x0A,0x43,0xC7,0x00,0x88,0xB6,0x18,0x36,0x39,0xDC,0xFD,0xA4,0x12,0x5B,0xD1,0x13,0xA8,0xF4,0x9E,0xE2,0x3E,0xD3,0x06,0xFA,0xAC,0x57,0x6C,0x3F,0xB0,0xC1,0xE2,0x56,0x67,0x1D,0x81,0x7F,0xC2,0x53,0x4A,0x52,0xF5,0xB4,0x39,0xF7,0x2E,0x42,0x4D,0xE3,0x76,0xF4,0xC5,0x65,0xCC,0xA8,0x23,0x07,0xDD,0x9E,0xF7,0x6D,0xA5,0xB7,0xC4,0xEB,0x7E,0x08,0x51,0x72,0xE3,0x28,0x80,0x7C,0x02,0xD0,0x11,0xFF,0xBF,0x33,0x78,0x53,0x78,0xD7,0x9D,0xC2,0x66,0xF6,0xA5,0xBE,0x6B,0xB0,0xE4,0xA9,0x2E,0xCE,0xEB,0xAE,0xB1], 4100).toHexString()).to.be('8a5199b4a7e133e264a86202720655894d48cff344a928cf8347f48379cef347dfc5bcffab99b27b1f89aa2735e23d30088ffa03b9edb02b9635470ab9f1038985d55f9ca774572dd006470ea65145469609f9fa0831bf1ffd842dc24acade27bd9816e3b5bf2876cb112232a0eb4475f1dff9f5c713d9ffd4ccb89ae5607fe35731df06317949eef646e9591cf3be53add6b7dd2b6096e2b3fb06e662ec8b2d77422daad9463cd155204acdbd38e319613f39f99b6dfb35ca9365160066db19835888c2241ff9a731a4acbb5663727aac34a401247fbaa7499e7d5ee5b69d31025e63d04c35c798bca1262d5673a9cf0930b5ad89bd485599dc184528da4790f088ebd170b635d9581632d2ff90db79665ced430089af13c9f21f6d443a818064f17aec9e9c5457001fa8dc6afbadbe3138f388d89d0e6f22f66671255b210754ed63d81dce75ce8f189b534e6d6b3539aa51e837c42df9df59c71e6171cd4902fe1bdc73fb1775b5c754a1ed4ea7f3105fc543ee0418dad256f3f6118ea77114a16c15355b42877a1db2a7df0e155ae1d8670abcec3450f4e2eec9838f895423ef63d261138baaf5d9f104cb5a957aea06c0b9b8c78b0d441796dc0350ddeabb78a33b6f1f9e68ede3d1805c7b7e2cfd54e0fad62f0d8ca67a775dc4546af9096f2edb221db42843d65327861282dc946a0ba01a11863ab2d1dfd16e3973d4'); }); }); + + context('#update', function() { + it('should be equal', function() { + expect(shake_128.update('', 256).hex()).to.be('7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26'); + expect(shake_128.update('The quick brown fox ', 256).update('jumps over the lazy dog').hex()).to.be('f4202e3c5852f9182a0430fd8144f0a74b95e7417ecae17db0f8cfeed0e3e66e'); + }); + }); }); describe('shake_256', function() { diff --git a/tests/test.js b/tests/test.js index 5189205..ceeccfc 100644 --- a/tests/test.js +++ b/tests/test.js @@ -77,7 +77,25 @@ context('#hex', function() { it('should be equal', function() { - expect(sha3_512.hex('')).to.be(sha3_512('')); + expect(sha3_512.hex('')).to.be('a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26'); + }); + }); + + context('#update', function() { + it('should be equal', function() { + expect(sha3_512.update('').hex()).to.be('a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26'); + expect(sha3_512.update('The quick brown fox ').update('jumps over the lazy dog').hex()).to.be('01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450'); + }); + }); + + context('#create', function() { + it('should be equal', function() { + var bytes = [84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104, 101, 32, 108, 97, 122, 121, 32, 100, 111, 103]; + var hash = sha3_512.create(); + for(var i = 0;i < bytes.length;++i) { + hash.update([bytes[i]]); + } + expect(hash.hex()).to.be('01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450'); }); }); });