diff --git a/.covignore b/.covignore index 016f806..8c36f6f 100644 --- a/.covignore +++ b/.covignore @@ -1 +1,2 @@ /tests/ +node_modules/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5d763dc --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +covreporter +node_modules diff --git a/.travis.yml b/.travis.yml index aabe614..6d44cb9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,13 @@ language: node_js node_js: + - "4.1" + - "4.0" + - "0.12" - "0.11" - "0.10" - - "0.8" before_install: - - npm install mocha -g - - npm install coveralls -g - - npm install mocha-lcov-reporter -g + - npm install coveralls + - npm install mocha-lcov-reporter script: npm run-script coveralls branches: only: diff --git a/CHANGELOG.md b/CHANGELOG.md index 5660c6c..8b19d58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v0.2.0 / 2015-12-01 + +* Added support for bytes. +* Added support for AMD. + # v0.1.1 / 2015-03-01 Improve performance. diff --git a/README.md b/README.md index 329db69..7422fea 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,18 @@ Output 223088bf7bd45a16436b15360c5fc5a0 +It also supports byte `Array`, `Uint8Array`, `ArrayBuffer` input: + +Code +```JavaScript +md4([]); +md4(new Uint8Array([])); +``` +Output + + 31d6cfe0d16ae931b73c59d7e0c089c0 + 31d6cfe0d16ae931b73c59d7e0c089c0 + ## Extensions ### jQuery If you prefer jQuery style, you can add following code to add a jQuery extension. diff --git a/bower.json b/bower.json index 0138028..8ee2349 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "js-md4", - "version": "0.1.1", - "main": ["build/md4.min.js"], + "version": "0.2.0", + "main": ["src/md4.js"], "ignore": [ "samples", "tests" diff --git a/build/md4.min.js b/build/md4.min.js index 662a001..f972814 100644 --- a/build/md4.min.js +++ b/build/md4.min.js @@ -1,18 +1,10 @@ /* - * js-md4 v0.1.1 + * js-md4 v0.2.0 * https://github.com/emn178/js-md4 * * Copyright 2015, emn178@gmail.com * - * Licensed under the MIT license: + * @license under the MIT license: * http://www.opensource.org/licenses/MIT */ -(function(q,C){var v="undefined"!=typeof module;v&&(q=global,q.JS_MD4_TEST&&(q.navigator={userAgent:"Firefox"}));var A=(q.JS_MD4_TEST||!v)&&-1!=navigator.userAgent.indexOf("Firefox"),z=!q.JS_MD4_TEST&&"undefined"!=typeof ArrayBuffer,f="0123456789abcdef".split(""),B=[128,32768,8388608,-2147483648],w=[0,8,16,24],e=[],t;if(z){var u=new ArrayBuffer(68);t=new Uint8Array(u);e=new Uint32Array(u)}u=function(h){var l,m,n,p,b,a,d,c,k,g,q=!0,u=!1,r=0,x=0,v=0,y=h.length;e[16]=0;do{e[0]=e[16];e[16]=e[1]=e[2]= -e[3]=e[4]=e[5]=e[6]=e[7]=e[8]=e[9]=e[10]=e[11]=e[12]=e[13]=e[14]=e[15]=0;if(z)for(a=x;ra;++r)b=h.charCodeAt(r),128>b?t[a++]=b:(2048>b?t[a++]=192|b>>6:(55296>b||57344<=b?t[a++]=224|b>>12:(b=65536+((b&1023)<<10|h.charCodeAt(++r)&1023),t[a++]=240|b>>18,t[a++]=128|b>>12&63),t[a++]=128|b>>6&63),t[a++]=128|b&63);else for(a=x;ra;++r)b=h.charCodeAt(r),128>b?e[a>>2]|=b<b?e[a>>2]|=(192|b>>6)<b||57344<=b?e[a>>2]|=(224|b>>12)<>2]|=(240|b>>18)<>2]|=(128|b>>12&63)<>2]|=(128|b>>6&63)<>2]|=(128|b&63)<>2]|=B[a&3],++r);r>y&&56>a&&(e[14]=v<<3,u=!0);q?(b=e[0]-1,b=b<<3|b>>>29,c=(b&4023233417|~b&2562383102)+e[1]+271733878,c=c<<7|c>>>25,d=(c&b|~c&4023233417)+e[2]-1732584194,d=d<<11|d>>>21,a=(d&c|~d&b)+e[3]-271733879):(b=l,a=m,d=n,c=p,b+=(a&d|~a&c)+e[0],b=b<<3|b>>>29,c+=(b&a|~b&d)+e[1],c=c<<7|c>>>25,d+=(c&b|~c&a)+e[2],d=d<<11|d>>>21,a+=(d&c| -~d&b)+e[3]);a=a<<19|a>>>13;b+=(a&d|~a&c)+e[4];b=b<<3|b>>>29;c+=(b&a|~b&d)+e[5];c=c<<7|c>>>25;d+=(c&b|~c&a)+e[6];d=d<<11|d>>>21;a+=(d&c|~d&b)+e[7];a=a<<19|a>>>13;b+=(a&d|~a&c)+e[8];b=b<<3|b>>>29;c+=(b&a|~b&d)+e[9];c=c<<7|c>>>25;d+=(c&b|~c&a)+e[10];d=d<<11|d>>>21;a+=(d&c|~d&b)+e[11];a=a<<19|a>>>13;b+=(a&d|~a&c)+e[12];b=b<<3|b>>>29;c+=(b&a|~b&d)+e[13];c=c<<7|c>>>25;d+=(c&b|~c&a)+e[14];d=d<<11|d>>>21;a+=(d&c|~d&b)+e[15];a=a<<19|a>>>13;g=a&d;b+=(g|a&c|d&c)+e[0]+1518500249;b=b<<3|b>>>29;k=b&a;c+=(k|b&d| -g)+e[4]+1518500249;c=c<<5|c>>>27;g=c&b;d+=(g|c&a|k)+e[8]+1518500249;d=d<<9|d>>>23;k=d&c;a+=(k|d&b|g)+e[12]+1518500249;a=a<<13|a>>>19;g=a&d;b+=(g|a&c|k)+e[1]+1518500249;b=b<<3|b>>>29;k=b&a;c+=(k|b&d|g)+e[5]+1518500249;c=c<<5|c>>>27;g=c&b;d+=(g|c&a|k)+e[9]+1518500249;d=d<<9|d>>>23;k=d&c;a+=(k|d&b|g)+e[13]+1518500249;a=a<<13|a>>>19;g=a&d;b+=(g|a&c|k)+e[2]+1518500249;b=b<<3|b>>>29;k=b&a;c+=(k|b&d|g)+e[6]+1518500249;c=c<<5|c>>>27;g=c&b;d+=(g|c&a|k)+e[10]+1518500249;d=d<<9|d>>>23;k=d&c;a+=(k|d&b|g)+e[14]+ -1518500249;a=a<<13|a>>>19;g=a&d;b+=(g|a&c|k)+e[3]+1518500249;b=b<<3|b>>>29;k=b&a;c+=(k|b&d|g)+e[7]+1518500249;c=c<<5|c>>>27;g=c&b;d+=(g|c&a|k)+e[11]+1518500249;d=d<<9|d>>>23;a+=(d&c|d&b|g)+e[15]+1518500249;a=a<<13|a>>>19;g=a^d;b+=(g^c)+e[0]+1859775393;b=b<<3|b>>>29;c+=(g^b)+e[8]+1859775393;c=c<<9|c>>>23;g=c^b;d+=(g^a)+e[4]+1859775393;d=d<<11|d>>>21;a+=(g^d)+e[12]+1859775393;a=a<<15|a>>>17;g=a^d;b+=(g^c)+e[2]+1859775393;b=b<<3|b>>>29;c+=(g^b)+e[10]+1859775393;c=c<<9|c>>>23;g=c^b;d+=(g^a)+e[6]+1859775393; -d=d<<11|d>>>21;a+=(g^d)+e[14]+1859775393;a=a<<15|a>>>17;g=a^d;b+=(g^c)+e[1]+1859775393;b=b<<3|b>>>29;c+=(g^b)+e[9]+1859775393;c=c<<9|c>>>23;g=c^b;d+=(g^a)+e[5]+1859775393;d=d<<11|d>>>21;a+=(g^d)+e[13]+1859775393;a=a<<15|a>>>17;g=a^d;b+=(g^c)+e[3]+1859775393;b=b<<3|b>>>29;c+=(g^b)+e[11]+1859775393;c=c<<9|c>>>23;g=c^b;d+=(g^a)+e[7]+1859775393;d=d<<11|d>>>21;a+=(g^d)+e[15]+1859775393;a=a<<15|a>>>17;q?(l=b+1732584193<<0,m=a-271733879<<0,n=d-1732584194<<0,p=c+271733878<<0,q=!1):(l=l+b<<0,m=m+a<<0,n=n+ -d<<0,p=p+c<<0)}while(!u);return A?(h=f[l>>4&15]+f[l&15],h+=f[l>>12&15]+f[l>>8&15],h+=f[l>>20&15]+f[l>>16&15],h+=f[l>>28&15]+f[l>>24&15],h+=f[m>>4&15]+f[m&15],h+=f[m>>12&15]+f[m>>8&15],h+=f[m>>20&15]+f[m>>16&15],h+=f[m>>28&15]+f[m>>24&15],h+=f[n>>4&15]+f[n&15],h+=f[n>>12&15]+f[n>>8&15],h+=f[n>>20&15]+f[n>>16&15],h+=f[n>>28&15]+f[n>>24&15],h+=f[p>>4&15]+f[p&15],h+=f[p>>12&15]+f[p>>8&15],h+=f[p>>20&15]+f[p>>16&15],h+=f[p>>28&15]+f[p>>24&15]):f[l>>4&15]+f[l&15]+f[l>>12&15]+f[l>>8&15]+f[l>>20&15]+f[l>> -16&15]+f[l>>28&15]+f[l>>24&15]+f[m>>4&15]+f[m&15]+f[m>>12&15]+f[m>>8&15]+f[m>>20&15]+f[m>>16&15]+f[m>>28&15]+f[m>>24&15]+f[n>>4&15]+f[n&15]+f[n>>12&15]+f[n>>8&15]+f[n>>20&15]+f[n>>16&15]+f[n>>28&15]+f[n>>24&15]+f[p>>4&15]+f[p&15]+f[p>>12&15]+f[p>>8&15]+f[p>>20&15]+f[p>>16&15]+f[p>>28&15]+f[p>>24&15]};!q.JS_MD4_TEST&&v?module.exports=u:q&&(q.md4=u)})(this); +!function(e){"use strict";var r="object"==typeof process&&process.versions&&process.versions.node;r&&(e=global);var o,t=!e.JS_MD4_TEST&&"object"==typeof module&&module.exports,f="function"==typeof define&&define.amd,n=!e.JS_MD4_TEST&&"undefined"!=typeof ArrayBuffer,i="0123456789abcdef".split(""),s=[128,32768,8388608,-2147483648],a=[0,8,16,24],c=[];if(n){var d=new ArrayBuffer(68);o=new Uint8Array(d),c=new Uint32Array(d)}var u=function(e){var r="string"!=typeof e;r&&e.constructor==ArrayBuffer&&(e=new Uint8Array(e));var t,f,d,u,l,p,y,A,v,h,m,w,b,C,S=!0,T=!1,_=0,g=0,B=0,U=e.length||0;c[16]=0;do{if(c[0]=c[16],c[16]=c[1]=c[2]=c[3]=c[4]=c[5]=c[6]=c[7]=c[8]=c[9]=c[10]=c[11]=c[12]=c[13]=c[14]=c[15]=0,r)if(n)for(C=g;U>_&&64>C;++_)o[C++]=e[_];else for(C=g;U>_&&64>C;++_)c[C>>2]|=e[_]<_&&64>C;++_)b=e.charCodeAt(_),128>b?o[C++]=b:2048>b?(o[C++]=192|b>>6,o[C++]=128|63&b):55296>b||b>=57344?(o[C++]=224|b>>12,o[C++]=128|b>>6&63,o[C++]=128|63&b):(b=65536+((1023&b)<<10|1023&e.charCodeAt(++_)),o[C++]=240|b>>18,o[C++]=128|b>>12&63,o[C++]=128|b>>6&63,o[C++]=128|63&b);else for(C=g;U>_&&64>C;++_)b=e.charCodeAt(_),128>b?c[C>>2]|=b<b?(c[C>>2]|=(192|b>>6)<>2]|=(128|63&b)<b||b>=57344?(c[C>>2]|=(224|b>>12)<>2]|=(128|b>>6&63)<>2]|=(128|63&b)<>2]|=(240|b>>18)<>2]|=(128|b>>12&63)<>2]|=(128|b>>6&63)<>2]|=(128|63&b)<>2]|=s[3&C],++_),_>U&&56>C&&(c[14]=B<<3,T=!0),S?(l=c[0]-1,l=l<<3|l>>>29,A=(4023233417&l|2562383102&~l)+c[1]+271733878,A=A<<7|A>>>25,y=(A&l|4023233417&~A)+c[2]-1732584194,y=y<<11|y>>>21,p=(y&A|~y&l)+c[3]-271733879,p=p<<19|p>>>13):(l=t,p=f,y=d,A=u,l+=(p&y|~p&A)+c[0],l=l<<3|l>>>29,A+=(l&p|~l&y)+c[1],A=A<<7|A>>>25,y+=(A&l|~A&p)+c[2],y=y<<11|y>>>21,p+=(y&A|~y&l)+c[3],p=p<<19|p>>>13),l+=(p&y|~p&A)+c[4],l=l<<3|l>>>29,A+=(l&p|~l&y)+c[5],A=A<<7|A>>>25,y+=(A&l|~A&p)+c[6],y=y<<11|y>>>21,p+=(y&A|~y&l)+c[7],p=p<<19|p>>>13,l+=(p&y|~p&A)+c[8],l=l<<3|l>>>29,A+=(l&p|~l&y)+c[9],A=A<<7|A>>>25,y+=(A&l|~A&p)+c[10],y=y<<11|y>>>21,p+=(y&A|~y&l)+c[11],p=p<<19|p>>>13,l+=(p&y|~p&A)+c[12],l=l<<3|l>>>29,A+=(l&p|~l&y)+c[13],A=A<<7|A>>>25,y+=(A&l|~A&p)+c[14],y=y<<11|y>>>21,p+=(y&A|~y&l)+c[15],p=p<<19|p>>>13,h=p&y,l+=(h|p&A|y&A)+c[0]+1518500249,l=l<<3|l>>>29,v=l&p,A+=(v|l&y|h)+c[4]+1518500249,A=A<<5|A>>>27,w=A&l,y+=(w|A&p|v)+c[8]+1518500249,y=y<<9|y>>>23,m=y&A,p+=(m|y&l|w)+c[12]+1518500249,p=p<<13|p>>>19,h=p&y,l+=(h|p&A|m)+c[1]+1518500249,l=l<<3|l>>>29,v=l&p,A+=(v|l&y|h)+c[5]+1518500249,A=A<<5|A>>>27,w=A&l,y+=(w|A&p|v)+c[9]+1518500249,y=y<<9|y>>>23,m=y&A,p+=(m|y&l|w)+c[13]+1518500249,p=p<<13|p>>>19,h=p&y,l+=(h|p&A|m)+c[2]+1518500249,l=l<<3|l>>>29,v=l&p,A+=(v|l&y|h)+c[6]+1518500249,A=A<<5|A>>>27,w=A&l,y+=(w|A&p|v)+c[10]+1518500249,y=y<<9|y>>>23,m=y&A,p+=(m|y&l|w)+c[14]+1518500249,p=p<<13|p>>>19,h=p&y,l+=(h|p&A|m)+c[3]+1518500249,l=l<<3|l>>>29,v=l&p,A+=(v|l&y|h)+c[7]+1518500249,A=A<<5|A>>>27,w=A&l,y+=(w|A&p|v)+c[11]+1518500249,y=y<<9|y>>>23,p+=(y&A|y&l|w)+c[15]+1518500249,p=p<<13|p>>>19,h=p^y,l+=(h^A)+c[0]+1859775393,l=l<<3|l>>>29,A+=(h^l)+c[8]+1859775393,A=A<<9|A>>>23,w=A^l,y+=(w^p)+c[4]+1859775393,y=y<<11|y>>>21,p+=(w^y)+c[12]+1859775393,p=p<<15|p>>>17,h=p^y,l+=(h^A)+c[2]+1859775393,l=l<<3|l>>>29,A+=(h^l)+c[10]+1859775393,A=A<<9|A>>>23,w=A^l,y+=(w^p)+c[6]+1859775393,y=y<<11|y>>>21,p+=(w^y)+c[14]+1859775393,p=p<<15|p>>>17,h=p^y,l+=(h^A)+c[1]+1859775393,l=l<<3|l>>>29,A+=(h^l)+c[9]+1859775393,A=A<<9|A>>>23,w=A^l,y+=(w^p)+c[5]+1859775393,y=y<<11|y>>>21,p+=(w^y)+c[13]+1859775393,p=p<<15|p>>>17,h=p^y,l+=(h^A)+c[3]+1859775393,l=l<<3|l>>>29,A+=(h^l)+c[11]+1859775393,A=A<<9|A>>>23,w=A^l,y+=(w^p)+c[7]+1859775393,y=y<<11|y>>>21,p+=(w^y)+c[15]+1859775393,p=p<<15|p>>>17,S?(t=l+1732584193<<0,f=p-271733879<<0,d=y-1732584194<<0,u=A+271733878<<0,S=!1):(t=t+l<<0,f=f+p<<0,d=d+y<<0,u=u+A<<0)}while(!T);return i[t>>4&15]+i[15&t]+i[t>>12&15]+i[t>>8&15]+i[t>>20&15]+i[t>>16&15]+i[t>>28&15]+i[t>>24&15]+i[f>>4&15]+i[15&f]+i[f>>12&15]+i[f>>8&15]+i[f>>20&15]+i[f>>16&15]+i[f>>28&15]+i[f>>24&15]+i[d>>4&15]+i[15&d]+i[d>>12&15]+i[d>>8&15]+i[d>>20&15]+i[d>>16&15]+i[d>>28&15]+i[d>>24&15]+i[u>>4&15]+i[15&u]+i[u>>12&15]+i[u>>8&15]+i[u>>20&15]+i[u>>16&15]+i[u>>28&15]+i[u>>24&15]};t?module.exports=u:(e.md4=u,f&&define(function(){return u}))}(this); \ No newline at end of file diff --git a/package.json b/package.json index 911b4f2..eaf47dc 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,19 @@ { "name": "js-md4", - "version": "0.1.1", + "version": "0.2.0", "description": "A simple MD4 hash function for JavaScript supports UTF-8 encoding.", "main": "src/md4.js", "devDependencies": { "expect.js": "~0.3.1", - "jscoverage": "~0.5.9" + "jscoverage": "~0.5.9", + "mocha": "~2.3.4", + "uglifyjs": "~2.4.10" }, "scripts": { "test": "mocha tests/node-test.js -r jscoverage", - "coveralls": "mocha tests/node-test.js -R mocha-lcov-reporter -r jscoverage | coveralls" + "report": "mocha tests/node-test.js -r jscoverage --covout=html", + "coveralls": "mocha tests/node-test.js -R mocha-lcov-reporter -r jscoverage | coveralls", + "build": "uglifyjs src/md4.js --compress --mangle --comments --output build/md4.min.js" }, "repository": { "type": "git", diff --git a/src/md4.js b/src/md4.js index 9e8f814..2154034 100644 --- a/src/md4.js +++ b/src/md4.js @@ -1,24 +1,23 @@ /* - * js-md4 v0.1.1 + * js-md4 v0.2.0 * https://github.com/emn178/js-md4 * * Copyright 2015, emn178@gmail.com * - * Licensed under the MIT license: + * @license under the MIT license: * http://www.opensource.org/licenses/MIT */ -;(function(root, undefined) { +;(function(root) { 'use strict'; - var NODE_JS = typeof(module) != 'undefined'; + var NODE_JS = typeof process == 'object' && process.versions && process.versions.node; if(NODE_JS) { root = global; - if(root.JS_MD4_TEST) { - root.navigator = { userAgent: 'Firefox'}; - } } - var FIREFOX = (root.JS_MD4_TEST || !NODE_JS) && navigator.userAgent.indexOf('Firefox') != -1; - var ARRAY_BUFFER = !root.JS_MD4_TEST && typeof(ArrayBuffer) != 'undefined'; + var COMMON_JS = !root.JS_MD4_TEST && typeof module == 'object' && module.exports; + var AMD = typeof define == 'function' && define.amd; + + var ARRAY_BUFFER = !root.JS_MD4_TEST && typeof ArrayBuffer != 'undefined'; var HEX_CHARS = '0123456789abcdef'.split(''); var EXTRA = [128, 32768, 8388608, -2147483648]; var SHIFT = [0, 8, 16, 24]; @@ -31,8 +30,13 @@ } var md4 = function(message) { + var notString = typeof(message) != 'string'; + if(notString && message.constructor == ArrayBuffer) { + message = new Uint8Array(message); + } + var h0, h1, h2, h3, a, b, c, d, ab, bc, cd, da, code, first = true, end = false, - index = 0, i, start = 0, bytes = 0, length = message.length; + index = 0, i, start = 0, bytes = 0, length = message.length || 0; blocks[16] = 0; do { @@ -41,44 +45,56 @@ blocks[4] = blocks[5] = blocks[6] = blocks[7] = blocks[8] = blocks[9] = blocks[10] = blocks[11] = blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0; - if(ARRAY_BUFFER) { - for (i = start;index < length && i < 64; ++index) { - code = message.charCodeAt(index); - if (code < 0x80) { - buffer8[i++] = code; - } else if (code < 0x800) { - buffer8[i++] = 0xc0 | (code >> 6); - buffer8[i++] = 0x80 | (code & 0x3f); - } else if (code < 0xd800 || code >= 0xe000) { - buffer8[i++] = 0xe0 | (code >> 12); - buffer8[i++] = 0x80 | ((code >> 6) & 0x3f); - buffer8[i++] = 0x80 | (code & 0x3f); - } else { - code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); - buffer8[i++] = 0xf0 | (code >> 18); - buffer8[i++] = 0x80 | ((code >> 12) & 0x3f); - buffer8[i++] = 0x80 | ((code >> 6) & 0x3f); - buffer8[i++] = 0x80 | (code & 0x3f); + if(notString) { + if(ARRAY_BUFFER) { + for (i = start;index < length && i < 64; ++index) { + buffer8[i++] = message[index]; + } + } else { + for (i = start;index < length && i < 64; ++index) { + blocks[i >> 2] |= message[index] << SHIFT[i++ & 3]; } } } else { - for (i = start;index < length && i < 64; ++index) { - code = message.charCodeAt(index); - if (code < 0x80) { - blocks[i >> 2] |= code << SHIFT[i++ & 3]; - } else if (code < 0x800) { - blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3]; - blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; - } else if (code < 0xd800 || code >= 0xe000) { - blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3]; - blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; - blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; - } else { - code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); - blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3]; - blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3]; - blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; - blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + if(ARRAY_BUFFER) { + for (i = start;index < length && i < 64; ++index) { + code = message.charCodeAt(index); + if (code < 0x80) { + buffer8[i++] = code; + } else if (code < 0x800) { + buffer8[i++] = 0xc0 | (code >> 6); + buffer8[i++] = 0x80 | (code & 0x3f); + } else if (code < 0xd800 || code >= 0xe000) { + buffer8[i++] = 0xe0 | (code >> 12); + buffer8[i++] = 0x80 | ((code >> 6) & 0x3f); + buffer8[i++] = 0x80 | (code & 0x3f); + } else { + code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); + buffer8[i++] = 0xf0 | (code >> 18); + buffer8[i++] = 0x80 | ((code >> 12) & 0x3f); + buffer8[i++] = 0x80 | ((code >> 6) & 0x3f); + buffer8[i++] = 0x80 | (code & 0x3f); + } + } + } else { + for (i = start;index < length && i < 64; ++index) { + code = message.charCodeAt(index); + if (code < 0x80) { + blocks[i >> 2] |= code << SHIFT[i++ & 3]; + } else if (code < 0x800) { + blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + } else if (code < 0xd800 || code >= 0xe000) { + blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + } else { + code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); + blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + } } } } @@ -244,47 +260,32 @@ } } while(!end); - if(FIREFOX) { - var hex = HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F]; - hex += HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F]; - hex += HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F]; - hex += HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F]; - hex += HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F]; - hex += HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F]; - hex += HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F]; - hex += HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F]; - hex += HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F]; - hex += HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F]; - hex += HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F]; - hex += HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F]; - hex += HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F]; - hex += HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F]; - hex += HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F]; - hex += HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F]; - return hex; - } else { - return HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] + - HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] + - HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] + - HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] + - HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] + - HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] + - HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] + - HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] + - HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] + - HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] + - HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] + - HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] + - HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] + - HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] + - HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] + - HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F]; - } + return HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] + + HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] + + HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] + + HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] + + HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] + + HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] + + HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] + + HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] + + HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] + + HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] + + HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] + + HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] + + HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] + + HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] + + HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] + + HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F]; }; - if(!root.JS_MD4_TEST && NODE_JS) { + if(COMMON_JS) { module.exports = md4; - } else if(root) { + } else { root.md4 = md4; + if(AMD) { + define(function() { + return md4; + }); + } } }(this)); diff --git a/tests/node-test.js b/tests/node-test.js index 7c58427..7dfcf92 100644 --- a/tests/node-test.js +++ b/tests/node-test.js @@ -9,3 +9,15 @@ md4 = null JS_MD4_TEST = true; require('../src/md4.js'); require('./test.js'); + +delete require.cache[require.resolve('../src/md4.js')]; +delete require.cache[require.resolve('./test.js')]; +md4 = null; + +define = function(func) { + md4 = func(); + require('./test.js'); +}; +define.amd = true; + +require('../src/md4.js'); diff --git a/tests/requirejs.html b/tests/requirejs.html new file mode 100644 index 0000000..d28b06b --- /dev/null +++ b/tests/requirejs.html @@ -0,0 +1,24 @@ + + + + + MD4 + + + + + + +
+ + + diff --git a/tests/test.js b/tests/test.js index 6940d96..9068542 100644 --- a/tests/test.js +++ b/tests/test.js @@ -1,47 +1,67 @@ (function(md4) { - describe('md4', function() { - describe('ascii', function() { - describe('less than 64 bytes', function() { - it('should be successful', function() { - expect(md4('')).to.be('31d6cfe0d16ae931b73c59d7e0c089c0'); - expect(md4('The quick brown fox jumps over the lazy dog')).to.be('1bee69a46ba811185c194762abaeae90'); - expect(md4('The quick brown fox jumps over the lazy dog.')).to.be('2812c6c7136898c51f6f6739ad08750e'); - }); - }); - - describe('more than 64 bytes', function() { - it('should be successful', function() { - expect(md4('The MD5 message-digest algorithm is a widely used cryptographic hash function producing a 128-bit (16-byte) hash value, typically expressed in text format as a 32 digit hexadecimal number. MD5 has been utilized in a wide variety of cryptographic applications, and is also commonly used to verify data integrity.')).to.be('e995876fc5a7870c478d20312edf17da'); - }); - }); - }); + var testCases = { + 'ascii': { + '31d6cfe0d16ae931b73c59d7e0c089c0': '', + '1bee69a46ba811185c194762abaeae90': 'The quick brown fox jumps over the lazy dog', + '2812c6c7136898c51f6f6739ad08750e': 'The quick brown fox jumps over the lazy dog.' + }, + 'ascii more than 64 bytes': { + 'e995876fc5a7870c478d20312edf17da': 'The MD5 message-digest algorithm is a widely used cryptographic hash function producing a 128-bit (16-byte) hash value, typically expressed in text format as a 32 digit hexadecimal number. MD5 has been utilized in a wide variety of cryptographic applications, and is also commonly used to verify data integrity.' + }, + 'UTF8': { + '223088bf7bd45a16436b15360c5fc5a0': '中文', + '0b1f6347ef0be74383f7ae7547359a4c': 'aécio', + 'cb17a223ccf45757d08260b6bfab78ab': '𠜎' + }, + 'UTF8 more than 64 bytes': { + '968bd34f00469adbddbe6d803b28cff9': '訊息摘要演算法第五版(英語:Message-Digest Algorithm 5,縮寫為MD5),是當前電腦領域用於確保資訊傳輸完整一致而廣泛使用的雜湊演算法之一', + '2e03bd374f7be036d4fa838cb9662597': '訊息摘要演算法第五版(英語:Message-Digest Algorithm 5,縮寫為MD5),是當前電腦領域用於確保資訊傳輸完整一致而廣泛使用的雜湊演算法之一(又譯雜湊演算法、摘要演算法等),主流程式語言普遍已有MD5的實作。' + }, + 'special length': { + '91df808c37b8c5544391a3aa2196114e': '0123456780123456780123456780123456780123456780123456780', + '3825a0afe234b8029ccad9a31ec5f8ee': '01234567801234567801234567801234567801234567801234567801', + 'f9b968c94ec709be9f306d90cd424228': '0123456780123456780123456780123456780123456780123456780123456780', + '08b0ded59615dc18407569a9ceb263ba': '01234567801234567801234567801234567801234567801234567801234567801234567', + '9c637e494a39f7920c7e83b665284f03': '012345678012345678012345678012345678012345678012345678012345678012345678', + '47eebbaaa1fca842a7bff2d3b7c9f0c6': '012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678' + }, + 'Array': { + '31d6cfe0d16ae931b73c59d7e0c089c0': [], + '47c61a0fa8738ba77308a8a600f88e4b': [0], + '1bee69a46ba811185c194762abaeae90': [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], + '4c832b90373e2d3f4a8ce06172989e2b': [72, 69, 76, 76, 79] + }, + 'Uint8Array': { + '1bee69a46ba811185c194762abaeae90': new Uint8Array([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]), + '4c832b90373e2d3f4a8ce06172989e2b': new Uint8Array([72, 69, 76, 76, 79]) + }, + 'Int8Array': { + '1bee69a46ba811185c194762abaeae90': new Int8Array([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]), + '4c832b90373e2d3f4a8ce06172989e2b': new Int8Array([72, 69, 76, 76, 79]) + }, + 'ArrayBuffer': { + '47c61a0fa8738ba77308a8a600f88e4b': new ArrayBuffer(1) + }, + 'Object': { + '31d6cfe0d16ae931b73c59d7e0c089c0': {}, + '31d6cfe0d16ae931b73c59d7e0c089c0': {what: 'ever'} + } + }; - describe('UTF8', function() { - describe('less than 64 bytes', function() { - it('should be successful', function() { - expect(md4('中文')).to.be('223088bf7bd45a16436b15360c5fc5a0'); - expect(md4('aécio')).to.be('0b1f6347ef0be74383f7ae7547359a4c'); - expect(md4('𠜎')).to.be('cb17a223ccf45757d08260b6bfab78ab'); + describe('#md4', function() { + for(var testCaseName in testCases) { + (function(testCaseName) { + var testCase = testCases[testCaseName]; + context('when ' + testCaseName, function() { + for(var hash in testCase) { + (function(message, hash) { + it('should be equal', function() { + expect(md4(message)).to.be(hash); + }); + })(testCase[hash], hash); + } }); - }); - - describe('more than 64 bytes', function() { - it('should be successful', function() { - expect(md4('訊息摘要演算法第五版(英語:Message-Digest Algorithm 5,縮寫為MD5),是當前電腦領域用於確保資訊傳輸完整一致而廣泛使用的雜湊演算法之一')).to.be('968bd34f00469adbddbe6d803b28cff9'); - expect(md4('訊息摘要演算法第五版(英語:Message-Digest Algorithm 5,縮寫為MD5),是當前電腦領域用於確保資訊傳輸完整一致而廣泛使用的雜湊演算法之一(又譯雜湊演算法、摘要演算法等),主流程式語言普遍已有MD5的實作。')).to.be('2e03bd374f7be036d4fa838cb9662597'); - }); - }); - }); - - describe('special length', function() { - it('should be successful', function() { - expect(md4('0123456780123456780123456780123456780123456780123456780')).to.be('91df808c37b8c5544391a3aa2196114e'); - expect(md4('01234567801234567801234567801234567801234567801234567801')).to.be('3825a0afe234b8029ccad9a31ec5f8ee'); - expect(md4('0123456780123456780123456780123456780123456780123456780123456780')).to.be('f9b968c94ec709be9f306d90cd424228'); - expect(md4('01234567801234567801234567801234567801234567801234567801234567801234567')).to.be('08b0ded59615dc18407569a9ceb263ba'); - expect(md4('012345678012345678012345678012345678012345678012345678012345678012345678')).to.be('9c637e494a39f7920c7e83b665284f03'); - expect(md4('012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678012345678')).to.be('47eebbaaa1fca842a7bff2d3b7c9f0c6'); - }); - }); + })(testCaseName); + } }); })(md4);