From bec89d596e7852e81b89ccc12d88b6b2b85d0fcf Mon Sep 17 00:00:00 2001 From: Chen Yi-Cyuan Date: Sun, 1 Mar 2015 11:00:07 +0800 Subject: [PATCH] Initial release --- .covignore | 1 + .travis.yml | 13 +++ CHANGELOG.md | 3 + LICENSE.txt | 20 ++++ README.md | 83 ++++++++++++++++ bower.json | 9 ++ build/md4.min.js | 7 ++ package.json | 31 ++++++ src/md4.js | 233 +++++++++++++++++++++++++++++++++++++++++++++ tests/index.html | 22 +++++ tests/node-test.js | 11 +++ tests/test.js | 47 +++++++++ 12 files changed, 480 insertions(+) create mode 100644 .covignore create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 bower.json create mode 100644 build/md4.min.js create mode 100644 package.json create mode 100644 src/md4.js create mode 100644 tests/index.html create mode 100644 tests/node-test.js create mode 100644 tests/test.js diff --git a/.covignore b/.covignore new file mode 100644 index 0000000..016f806 --- /dev/null +++ b/.covignore @@ -0,0 +1 @@ +/tests/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..aabe614 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +language: node_js +node_js: + - "0.11" + - "0.10" + - "0.8" +before_install: + - npm install mocha -g + - npm install coveralls -g + - npm install mocha-lcov-reporter -g +script: npm run-script coveralls +branches: + only: + - master diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..18e2537 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +# v0.1.0 / 2015-03-01 + +Initial release diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..df6ab18 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright 2015 emn178@gmail.com + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..dc82407 --- /dev/null +++ b/README.md @@ -0,0 +1,83 @@ +# js-md4 +[![Build Status](https://travis-ci.org/emn178/js-md4.svg?branch=master)](https://travis-ci.org/emn178/js-md4) +[![Coverage Status](https://coveralls.io/repos/emn178/js-md4/badge.svg?branch=master)](https://coveralls.io/r/emn178/js-md4?branch=master) +[![NPM](https://nodei.co/npm/js-md4.png?stars&downloads)](https://nodei.co/npm/js-md4/) +A simple MD4 hash function for JavaScript supports UTF-8 encoding. + +## Download +[Compress](https://raw.github.com/emn178/js-md4/master/build/md4.min.js) +[Uncompress](https://raw.github.com/emn178/js-md4/master/src/md4.js) + +## Installation +You can also install js-md4 by using Bower. + + bower install js-md4 + +For node.js, you can use this command to install: + + npm install js-md4 + +## Usage +You could use like this: +```JavaScript +md4('Message to hash'); +``` +If you use node.js, you should require the module first: +```JavaScript +md4 = require('js-md4'); +``` + +## Example +Code +```JavaScript +md4(''); +md4('The quick brown fox jumps over the lazy dog'); +md4('The quick brown fox jumps over the lazy dog.'); +``` +Output + + 31d6cfe0d16ae931b73c59d7e0c089c0 + 1bee69a46ba811185c194762abaeae90 + 2812c6c7136898c51f6f6739ad08750e + +It also supports UTF-8 encoding: + +Code +```JavaScript +md4('中文'); +``` +Output + + 223088bf7bd45a16436b15360c5fc5a0 + +## Extensions +### jQuery +If you prefer jQuery style, you can add following code to add a jQuery extension. + +Code +```JavaScript +jQuery.md4 = md4 +``` +And then you could use like this: +```JavaScript +$.md4('message'); +``` +### Prototype +If you prefer prototype style, you can add following code to add a prototype extension. + +Code +```JavaScript +String.prototype.md4 = function() { + return md4(this); +}; +``` +And then you could use like this: +```JavaScript +'message'.md4(); +``` +## License +The project is released under the [MIT license](http://www.opensource.org/licenses/MIT). + +## Contact +The project's website is located at https://github.com/emn178/js-md4 +Author: emn178@gmail.com diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..7b99925 --- /dev/null +++ b/bower.json @@ -0,0 +1,9 @@ +{ + "name": "js-md4", + "version": "0.1.0", + "main": ["build/md4.min.js"], + "ignore": [ + "samples", + "tests" + ] +} diff --git a/build/md4.min.js b/build/md4.min.js new file mode 100644 index 0000000..6fadf5c --- /dev/null +++ b/build/md4.min.js @@ -0,0 +1,7 @@ +(function(r,C){function n(c,d){return c<>>32-d}function p(c,d,h,k,l,b){return n(c+(d&h|~d&k)+l,b)}function q(c,d,h,k,l,b){return n(c+(d&h|d&k|h&k)+l+1518500249,b)}var w="undefined"!=typeof module;w&&(r=global,r.JS_MD4_TEST&&(r.navigator={userAgent:"Firefox"}));var A=(r.JS_MD4_TEST||!w)&&-1!=navigator.userAgent.indexOf("Firefox"),z=!r.JS_MD4_TEST&&"undefined"!=typeof ArrayBuffer,d="0123456789abcdef".split(""),B=[128,32768,8388608,-2147483648],x=[0,8,16,24],c=[],v;if(z){var u=new ArrayBuffer(68); +v=new Uint8Array(u);c=new Uint32Array(u)}u=function(g){var m,h,k,l,b,a,e,f,r=!1,t=0,u=0,w=0,y=g.length;m=1732584193;h=4023233417;k=2562383102;l=271733878;c[16]=0;do{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;if(z)for(a=u;ta;++t)b=g.charCodeAt(t),128>b?v[a++]=b:(2048>b?v[a++]=192|b>>6:(55296>b||57344<=b?v[a++]=224|b>>12:(b=65536+((b&1023)<<10|g.charCodeAt(++t)&1023),v[a++]=240|b>>18,v[a++]=128|b>>12&63),v[a++]=128|b>>6&63),v[a++]=128| +b&63);else for(a=u;ta;++t)b=g.charCodeAt(t),128>b?c[a>>2]|=b<b?c[a>>2]|=(192|b>>6)<b||57344<=b?c[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],++t);t>y&&56>a&&(c[14]=w<<3,r=!0);b=m;a=h;e=k;f=l;b=p(b,a,e,f,c[0],3);f=p(f,b,a,e,c[1],7);e=p(e,f,b,a,c[2],11);a=p(a,e,f, +b,c[3],19);b=p(b,a,e,f,c[4],3);f=p(f,b,a,e,c[5],7);e=p(e,f,b,a,c[6],11);a=p(a,e,f,b,c[7],19);b=p(b,a,e,f,c[8],3);f=p(f,b,a,e,c[9],7);e=p(e,f,b,a,c[10],11);a=p(a,e,f,b,c[11],19);b=p(b,a,e,f,c[12],3);f=p(f,b,a,e,c[13],7);e=p(e,f,b,a,c[14],11);a=p(a,e,f,b,c[15],19);b=q(b,a,e,f,c[0],3);f=q(f,b,a,e,c[4],5);e=q(e,f,b,a,c[8],9);a=q(a,e,f,b,c[12],13);b=q(b,a,e,f,c[1],3);f=q(f,b,a,e,c[5],5);e=q(e,f,b,a,c[9],9);a=q(a,e,f,b,c[13],13);b=q(b,a,e,f,c[2],3);f=q(f,b,a,e,c[6],5);e=q(e,f,b,a,c[10],9);a=q(a,e,f,b,c[14], +13);b=q(b,a,e,f,c[3],3);f=q(f,b,a,e,c[7],5);e=q(e,f,b,a,c[11],9);a=q(a,e,f,b,c[15],13);b=n(b+(a^e^f)+c[0]+1859775393,3);f=n(f+(b^a^e)+c[8]+1859775393,9);e=n(e+(f^b^a)+c[4]+1859775393,11);a=n(a+(e^f^b)+c[12]+1859775393,15);b=n(b+(a^e^f)+c[2]+1859775393,3);f=n(f+(b^a^e)+c[10]+1859775393,9);e=n(e+(f^b^a)+c[6]+1859775393,11);a=n(a+(e^f^b)+c[14]+1859775393,15);b=n(b+(a^e^f)+c[1]+1859775393,3);f=n(f+(b^a^e)+c[9]+1859775393,9);e=n(e+(f^b^a)+c[5]+1859775393,11);a=n(a+(e^f^b)+c[13]+1859775393,15);b=n(b+(a^ +e^f)+c[3]+1859775393,3);f=n(f+(b^a^e)+c[11]+1859775393,9);e=n(e+(f^b^a)+c[7]+1859775393,11);a=n(a+(e^f^b)+c[15]+1859775393,15);m=m+b<<0;h=h+a<<0;k=k+e<<0;l=l+f<<0}while(!r);return A?(g=d[m>>4&15]+d[m&15],g+=d[m>>12&15]+d[m>>8&15],g+=d[m>>20&15]+d[m>>16&15],g+=d[m>>28&15]+d[m>>24&15],g+=d[h>>4&15]+d[h&15],g+=d[h>>12&15]+d[h>>8&15],g+=d[h>>20&15]+d[h>>16&15],g+=d[h>>28&15]+d[h>>24&15],g+=d[k>>4&15]+d[k&15],g+=d[k>>12&15]+d[k>>8&15],g+=d[k>>20&15]+d[k>>16&15],g+=d[k>>28&15]+d[k>>24&15],g+=d[l>>4&15]+ +d[l&15],g+=d[l>>12&15]+d[l>>8&15],g+=d[l>>20&15]+d[l>>16&15],g+=d[l>>28&15]+d[l>>24&15]):d[m>>4&15]+d[m&15]+d[m>>12&15]+d[m>>8&15]+d[m>>20&15]+d[m>>16&15]+d[m>>28&15]+d[m>>24&15]+d[h>>4&15]+d[h&15]+d[h>>12&15]+d[h>>8&15]+d[h>>20&15]+d[h>>16&15]+d[h>>28&15]+d[h>>24&15]+d[k>>4&15]+d[k&15]+d[k>>12&15]+d[k>>8&15]+d[k>>20&15]+d[k>>16&15]+d[k>>28&15]+d[k>>24&15]+d[l>>4&15]+d[l&15]+d[l>>12&15]+d[l>>8&15]+d[l>>20&15]+d[l>>16&15]+d[l>>28&15]+d[l>>24&15]};!r.JS_MD4_TEST&&w?module.exports=u:r&&(r.md4=u)})(this); diff --git a/package.json b/package.json new file mode 100644 index 0000000..f5358ed --- /dev/null +++ b/package.json @@ -0,0 +1,31 @@ +{ + "name": "js-md4", + "version": "0.1.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" + }, + "scripts": { + "test": "mocha tests/node-test.js -r jscoverage", + "coveralls": "mocha tests/node-test.js -R mocha-lcov-reporter -r jscoverage | coveralls" + }, + "repository": { + "type": "git", + "url": "https://github.com/emn178/js-md4.git" + }, + "keywords": [ + "md4", + "hash", + "encryption", + "cryptography", + "HMAC" + ], + "license": "MIT", + "author": "emn178 ", + "homepage": "https://github.com/emn178/js-md4", + "bugs": { + "url": "https://github.com/emn178/js-md4/issues" + } +} diff --git a/src/md4.js b/src/md4.js new file mode 100644 index 0000000..18bc561 --- /dev/null +++ b/src/md4.js @@ -0,0 +1,233 @@ +/* + * js-md4 v0.1.0 + * https://github.com/emn178/js-md4 + * + * Copyright 2015, emn178@gmail.com + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ +;(function(root, undefined) { + 'use strict'; + + var NODE_JS = typeof(module) != 'undefined'; + 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 HEX_CHARS = '0123456789abcdef'.split(''); + var EXTRA = [128, 32768, 8388608, -2147483648]; + var SHIFT = [0, 8, 16, 24]; + + var blocks = [], buffer8; + if(ARRAY_BUFFER) { + var buffer = new ArrayBuffer(68); + buffer8 = new Uint8Array(buffer); + blocks = new Uint32Array(buffer); + } + + var md4 = function(message) { + var h0, h1, h2, h3, a, b, c, d, code, end = false, + index = 0, i, start = 0, bytes = 0, length = message.length; + + h0 = 0x67452301; + h1 = 0xefcdab89; + h2 = 0x98badcfe; + h3 = 0x10325476; + blocks[16] = 0; + do { + blocks[0] = blocks[16]; + blocks[16] = blocks[1] = blocks[2] = blocks[3] = + 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); + } + } + } 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]; + } + } + } + bytes += i - start; + start = i - 64; + if(index == length) { + blocks[i >> 2] |= EXTRA[i & 3]; + ++index; + } + if(index > length && i < 56) { + blocks[14] = bytes << 3; + end = true; + } + + a = h0; + b = h1; + c = h2; + d = h3; + + a = r1(a, b, c, d, blocks[0], 3); + d = r1(d, a, b, c, blocks[1], 7); + c = r1(c, d, a, b, blocks[2], 11); + b = r1(b, c, d, a, blocks[3], 19); + a = r1(a, b, c, d, blocks[4], 3); + d = r1(d, a, b, c, blocks[5], 7); + c = r1(c, d, a, b, blocks[6], 11); + b = r1(b, c, d, a, blocks[7], 19); + a = r1(a, b, c, d, blocks[8], 3); + d = r1(d, a, b, c, blocks[9], 7); + c = r1(c, d, a, b, blocks[10], 11); + b = r1(b, c, d, a, blocks[11], 19); + a = r1(a, b, c, d, blocks[12], 3); + d = r1(d, a, b, c, blocks[13], 7); + c = r1(c, d, a, b, blocks[14], 11); + b = r1(b, c, d, a, blocks[15], 19); + + a = r2(a, b, c, d, blocks[0], 3); + d = r2(d, a, b, c, blocks[4], 5); + c = r2(c, d, a, b, blocks[8], 9); + b = r2(b, c, d, a, blocks[12], 13); + a = r2(a, b, c, d, blocks[1], 3); + d = r2(d, a, b, c, blocks[5], 5); + c = r2(c, d, a, b, blocks[9], 9); + b = r2(b, c, d, a, blocks[13], 13); + a = r2(a, b, c, d, blocks[2], 3); + d = r2(d, a, b, c, blocks[6], 5); + c = r2(c, d, a, b, blocks[10], 9); + b = r2(b, c, d, a, blocks[14], 13); + a = r2(a, b, c, d, blocks[3], 3); + d = r2(d, a, b, c, blocks[7], 5); + c = r2(c, d, a, b, blocks[11], 9); + b = r2(b, c, d, a, blocks[15], 13); + + a = r3(a, b, c, d, blocks[0], 3); + d = r3(d, a, b, c, blocks[8], 9); + c = r3(c, d, a, b, blocks[4], 11); + b = r3(b, c, d, a, blocks[12], 15); + a = r3(a, b, c, d, blocks[2], 3); + d = r3(d, a, b, c, blocks[10], 9); + c = r3(c, d, a, b, blocks[6], 11); + b = r3(b, c, d, a, blocks[14], 15); + a = r3(a, b, c, d, blocks[1], 3); + d = r3(d, a, b, c, blocks[9], 9); + c = r3(c, d, a, b, blocks[5], 11); + b = r3(b, c, d, a, blocks[13], 15); + a = r3(a, b, c, d, blocks[3], 3); + d = r3(d, a, b, c, blocks[11], 9); + c = r3(c, d, a, b, blocks[7], 11); + b = r3(b, c, d, a, blocks[15], 15); + + h0 = h0 + a << 0; + h1 = h1 + b << 0; + h2 = h2 + c << 0; + h3 = h3 + d << 0; + } 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]; + } + }; + + function rotate(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)); + } + + function f(x, y, z) { + return (x & y) | (~x & z); + } + + function g(x, y, z) { + return (x & y) | (x & z) | (y & z); + } + + function h(x, y, z) { + return x ^ y ^ z; + } + + function r1(a, b, c, d, x, s) { + return rotate((a + f(b, c, d) + x), s); + } + + function r2(a, b, c, d, x, s) { + return rotate((a + g(b, c, d) + x + 0x5A827999), s); + } + + function r3(a, b, c, d, x, s) { + return rotate((a + h(b, c, d) + x + 0x6ED9EBA1), s); + } + + if(!root.JS_MD4_TEST && NODE_JS) { + module.exports = md4; + } else if(root) { + root.md4 = md4; + } +}(this)); diff --git a/tests/index.html b/tests/index.html new file mode 100644 index 0000000..5568f0f --- /dev/null +++ b/tests/index.html @@ -0,0 +1,22 @@ + + + + + MD4 + + + + + + +
+ + + + + diff --git a/tests/node-test.js b/tests/node-test.js new file mode 100644 index 0000000..7c58427 --- /dev/null +++ b/tests/node-test.js @@ -0,0 +1,11 @@ +md4 = require('../src/md4.js'); +expect = require('expect.js'); +require('./test.js'); + +delete require.cache[require.resolve('../src/md4.js')] +delete require.cache[require.resolve('./test.js')] +md4 = null + +JS_MD4_TEST = true; +require('../src/md4.js'); +require('./test.js'); diff --git a/tests/test.js b/tests/test.js new file mode 100644 index 0000000..6940d96 --- /dev/null +++ b/tests/test.js @@ -0,0 +1,47 @@ +(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'); + }); + }); + }); + + 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('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'); + }); + }); + }); +})(md4);