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 index c2658d7..dc6d1eb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ node_modules/ +covreporter +my_test diff --git a/.travis.yml b/.travis.yml index aabe614..4036a6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,11 @@ language: node_js node_js: - - "0.11" - - "0.10" - - "0.8" + - "0.12.15" + - "4.5" + - "6.5.0" 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 0d6107e..783807d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,30 +1,43 @@ -# v0.3.0 / 2015-03-04 - -* Support ArrayBuffer input. -* Improve performance. - -# v0.2.0 / 2015-02-16 - -* Support byte array input. -* Remove ascii parameter. -* Improve performance. -* Add test cases. - -# v0.1.3 / 2015-01-07 - -* Add bower package. -* Fixed JSHint warnings. -* Add travis. -* Add coveralls. - -# v0.1.2 / 2014-07-27 - - Fixed accents bug - -# v0.1.1 / 2014-01-05 - -Update license - -# v0.1.0 / 2014-01-04 - -Initial release +# Change Log + +## v0.4.0 / 2016-12-05 +### Added +- update method. +- support Array output. +- support ArrayBuffer output. +- support AMD. + +## v0.3.0 / 2015-03-04 +### Added +- support ArrayBuffer input. +### Changed +- improve performance. + +## v0.2.0 / 2015-02-16 +### Added +- support byte array input. +- test cases. +### Removed +- ascii parameter. +### Changed +- improve performance. + +## v0.1.3 / 2015-01-07 +### Added +- bower package. +- travis. +- coveralls. +### Fixed +- JSHint warnings. + +## v0.1.2 / 2014-07-27 +### Fixed +- accents bug. + +## v0.1.1 / 2014-01-05 +### Changed +- update license. + +## v0.1.0 / 2014-01-04 +### Added +- initial release. diff --git a/LICENSE.txt b/LICENSE.txt index 58074d3..1598c37 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright 2014-2015 emn178@gmail.com +Copyright 2014-2016 Chen, Yi-Cyuan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index 5e07dfa..836e8b3 100644 --- a/README.md +++ b/README.md @@ -24,79 +24,45 @@ For node.js, you can use this command to install: You could use like this: ```JavaScript sha1('Message to hash'); +var hash = sha1.create(); +hash.update('Message to hash'); +hash.hex(); ``` If you use node.js, you should require the module first: ```JavaScript sha1 = require('js-sha1'); ``` - -## Example -Code -```JavaScript -sha1(''); -sha1('The quick brown fox jumps over the lazy dog'); -sha1('The quick brown fox jumps over the lazy dog.'); -``` -Output - - da39a3ee5e6b4b0d3255bfef95601890afd80709 - 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 - 408d94384216f890ff7a0c3528e8bed1e0b01621 - -It also supports UTF-8 encoding: - -Code -```JavaScript -sha1('中文'); -``` -Output - - 7be2d2d20c106eee0836c9bc2b939890a78e8fb3 - -It also supports byte `Array`, `Uint8Array`, `ArrayBuffer` input: - -Code +It supports AMD: ```JavaScript -sha1([]); -sha1(new Uint8Array([])); +require(['your/path/sha1.js'], function(sha1) { +// ... +}); ``` -Output - - da39a3ee5e6b4b0d3255bfef95601890afd80709 - da39a3ee5e6b4b0d3255bfef95601890afd80709 - -## Benchmark -[UTF8](http://jsperf.com/sha1-speed-test/11) -[ASCII](http://jsperf.com/sha1-speed-test/10) -## Extensions -### jQuery -If you prefer jQuery style, you can add following code to add a jQuery extension. - -Code -```JavaScript -jQuery.sha1 = sha1; -``` -And then you could use like this: +## Example ```JavaScript -$.sha1('message'); +sha1(''); // da39a3ee5e6b4b0d3255bfef95601890afd80709 +sha1('The quick brown fox jumps over the lazy dog'); // 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 +sha1('The quick brown fox jumps over the lazy dog.'); // 408d94384216f890ff7a0c3528e8bed1e0b01621 + +// It also supports UTF-8 encoding +sha1('中文'); // 7be2d2d20c106eee0836c9bc2b939890a78e8fb3 + +// It also supports byte `Array`, `Uint8Array`, `ArrayBuffer` +sha1([]); // da39a3ee5e6b4b0d3255bfef95601890afd80709 +sha1(new Uint8Array([])); // da39a3ee5e6b4b0d3255bfef95601890afd80709 + +// Different output +sha1(''); // da39a3ee5e6b4b0d3255bfef95601890afd80709 +sha1.hex(''); // da39a3ee5e6b4b0d3255bfef95601890afd80709 +sha1.array(''); // [218, 57, 163, 238, 94, 107, 75, 13, 50, 85, 191, 239, 149, 96, 24, 144, 175, 216, 7, 9] +sha1.digest(''); // [218, 57, 163, 238, 94, 107, 75, 13, 50, 85, 191, 239, 149, 96, 24, 144, 175, 216, 7, 9] +sha1.arrayBuffer(''); // ArrayBuffer ``` -### Prototype -If you prefer prototype style, you can add following code to add a prototype extension. -Code -```JavaScript -String.prototype.sha1 = function() { - return sha1(this); -}; -``` -And then you could use like this: -```JavaScript -'message'.sha1(); -``` ## 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-sha1 -Author: emn178@gmail.com +Author: Chen, Yi-Cyuan (emn178@gmail.com) diff --git a/bower.json b/bower.json index 72fc168..eb2806a 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "js-sha1", - "version": "0.3.0", - "main": ["build/sha1.min.js"], + "version": "0.4.0", + "main": ["src/sha1.js"], "ignore": [ "samples", "tests" diff --git a/build/sha1.min.js b/build/sha1.min.js index 50e0a75..b1bb736 100644 --- a/build/sha1.min.js +++ b/build/sha1.min.js @@ -1,7 +1,9 @@ -(function(x,F){"undefined"!=typeof module&&(x=global);var k="0123456789abcdef".split(""),C=[-2147483648,8388608,32768,128],v=[24,16,8,0],b=[],D=function(w){var x="string"!=typeof w;x&&w.constructor==ArrayBuffer&&(w=new Uint8Array(w));var n,p,q,r,t,m=0,y=!1,a,l,h,u=0,z=0,B=0,A=w.length;n=1732584193;p=4023233417;q=2562383102;r=271733878;t=3285377520;do{b[0]=m;b[16]=b[1]=b[2]=b[3]=b[4]=b[5]=b[6]=b[7]=b[8]=b[9]=b[10]=b[11]=b[12]=b[13]=b[14]=b[15]=0;if(x)for(a=z;ua;++u)b[a>>2]|=w[u]<a;++u)m=w.charCodeAt(u),128>m?b[a>>2]|=m<m?b[a>>2]|=(192|m>>6)<m||57344<=m?b[a>>2]|=(224|m>>12)<>2]|=(240|m>>18)<>2]|=(128|m>>12&63)<>2]|=(128|m>>6&63)<>2]|=(128|m&63)<>2]|=C[a&3],++u);m=b[16];u>A&&56>a&&(b[15]=B<<3,y=!0);for(h=16;80>h;++h)a=b[h-3]^b[h-8]^b[h-14]^b[h-16],b[h]=a<<1|a>>>31;var c=n,d=p,e=q,f=r,g=t;for(h= -0;20>h;h+=5)l=d&e|~d&f,a=c<<5|c>>>27,g=a+l+g+1518500249+b[h]<<0,d=d<<30|d>>>2,l=c&d|~c&e,a=g<<5|g>>>27,f=a+l+f+1518500249+b[h+1]<<0,c=c<<30|c>>>2,l=g&c|~g&d,a=f<<5|f>>>27,e=a+l+e+1518500249+b[h+2]<<0,g=g<<30|g>>>2,l=f&g|~f&c,a=e<<5|e>>>27,d=a+l+d+1518500249+b[h+3]<<0,f=f<<30|f>>>2,l=e&f|~e&g,a=d<<5|d>>>27,c=a+l+c+1518500249+b[h+4]<<0,e=e<<30|e>>>2;for(;40>h;h+=5)l=d^e^f,a=c<<5|c>>>27,g=a+l+g+1859775393+b[h]<<0,d=d<<30|d>>>2,l=c^d^e,a=g<<5|g>>>27,f=a+l+f+1859775393+b[h+1]<<0,c=c<<30|c>>>2,l=g^c^d, -a=f<<5|f>>>27,e=a+l+e+1859775393+b[h+2]<<0,g=g<<30|g>>>2,l=f^g^c,a=e<<5|e>>>27,d=a+l+d+1859775393+b[h+3]<<0,f=f<<30|f>>>2,l=e^f^g,a=d<<5|d>>>27,c=a+l+c+1859775393+b[h+4]<<0,e=e<<30|e>>>2;for(;60>h;h+=5)l=d&e|d&f|e&f,a=c<<5|c>>>27,g=a+l+g-1894007588+b[h]<<0,d=d<<30|d>>>2,l=c&d|c&e|d&e,a=g<<5|g>>>27,f=a+l+f-1894007588+b[h+1]<<0,c=c<<30|c>>>2,l=g&c|g&d|c&d,a=f<<5|f>>>27,e=a+l+e-1894007588+b[h+2]<<0,g=g<<30|g>>>2,l=f&g|f&c|g&c,a=e<<5|e>>>27,d=a+l+d-1894007588+b[h+3]<<0,f=f<<30|f>>>2,l=e&f|e&g|f&g,a=d<< -5|d>>>27,c=a+l+c-1894007588+b[h+4]<<0,e=e<<30|e>>>2;for(;80>h;h+=5)l=d^e^f,a=c<<5|c>>>27,g=a+l+g-899497514+b[h]<<0,d=d<<30|d>>>2,l=c^d^e,a=g<<5|g>>>27,f=a+l+f-899497514+b[h+1]<<0,c=c<<30|c>>>2,l=g^c^d,a=f<<5|f>>>27,e=a+l+e-899497514+b[h+2]<<0,g=g<<30|g>>>2,l=f^g^c,a=e<<5|e>>>27,d=a+l+d-899497514+b[h+3]<<0,f=f<<30|f>>>2,l=e^f^g,a=d<<5|d>>>27,c=a+l+c-899497514+b[h+4]<<0,e=e<<30|e>>>2;n=n+c<<0;p=p+d<<0;q=q+e<<0;r=r+f<<0;t=t+g<<0}while(!y);return k[n>>28&15]+k[n>>24&15]+k[n>>20&15]+k[n>>16&15]+k[n>>12& -15]+k[n>>8&15]+k[n>>4&15]+k[n&15]+k[p>>28&15]+k[p>>24&15]+k[p>>20&15]+k[p>>16&15]+k[p>>12&15]+k[p>>8&15]+k[p>>4&15]+k[p&15]+k[q>>28&15]+k[q>>24&15]+k[q>>20&15]+k[q>>16&15]+k[q>>12&15]+k[q>>8&15]+k[q>>4&15]+k[q&15]+k[r>>28&15]+k[r>>24&15]+k[r>>20&15]+k[r>>16&15]+k[r>>12&15]+k[r>>8&15]+k[r>>4&15]+k[r&15]+k[t>>28&15]+k[t>>24&15]+k[t>>20&15]+k[t>>16&15]+k[t>>12&15]+k[t>>8&15]+k[t>>4&15]+k[t&15]};if(x.JS_SHA1_TEST||"undefined"==typeof module)x&&(x.sha1=D);else{var y=require("crypto"),E=require("buffer").Buffer; -module.exports=function(b){if("string"==typeof b)return y.createHash("sha1").update(b,"utf8").digest("hex");b.constructor==ArrayBuffer&&(b=new Uint8Array(b));return y.createHash("sha1").update(new E(b)).digest("hex")}}})(this); +/* + * [js-sha1]{@link https://github.com/emn178/js-sha1} + * + * @version 0.4.0 + * @author Chen, Yi-Cyuan [emn178@gmail.com] + * @copyright Chen, Yi-Cyuan 2014-2016 + * @license MIT + */ +!function(t){"use strict";function h(t){t?(f[0]=f[16]=f[1]=f[2]=f[3]=f[4]=f[5]=f[6]=f[7]=f[8]=f[9]=f[10]=f[11]=f[12]=f[13]=f[14]=f[15]=0,this.blocks=f):this.blocks=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],this.h0=1732584193,this.h1=4023233417,this.h2=2562383102,this.h3=271733878,this.h4=3285377520,this.block=this.start=this.bytes=0,this.finalized=this.hashed=!1,this.first=!0}var i="object"==typeof process&&process.versions&&process.versions.node;i&&(t=global);var s=!t.JS_SHA1_TEST&&"object"==typeof module&&module.exports,e="function"==typeof define&&define.amd,r="0123456789abcdef".split(""),o=[-2147483648,8388608,32768,128],n=[24,16,8,0],a=["hex","array","digest","arrayBuffer"],f=[],u=function(t){return function(i){return new h(!0).update(i)[t]()}},c=function(){var t=u("hex");i&&(t=p(t)),t.create=function(){return new h},t.update=function(h){return t.create().update(h)};for(var s=0;sr;){if(this.hashed&&(this.hashed=!1,a[0]=this.block,a[16]=a[1]=a[2]=a[3]=a[4]=a[5]=a[6]=a[7]=a[8]=a[9]=a[10]=a[11]=a[12]=a[13]=a[14]=a[15]=0),i)for(e=this.start;o>r&&64>e;++r)a[e>>2]|=h[r]<r&&64>e;++r)s=h.charCodeAt(r),128>s?a[e>>2]|=s<s?(a[e>>2]|=(192|s>>6)<>2]|=(128|63&s)<s||s>=57344?(a[e>>2]|=(224|s>>12)<>2]|=(128|s>>6&63)<>2]|=(128|63&s)<>2]|=(240|s>>18)<>2]|=(128|s>>12&63)<>2]|=(128|s>>6&63)<>2]|=(128|63&s)<=64?(this.block=a[16],this.start=e-64,this.hash(),this.hashed=!0):this.start=e}return this}},h.prototype.finalize=function(){if(!this.finalized){this.finalized=!0;var t=this.blocks,h=this.lastByteIndex;t[16]=this.block,t[h>>2]|=o[3&h],this.block=t[16],h>=56&&(this.hashed||this.hash(),t[0]=this.block,t[16]=t[1]=t[2]=t[3]=t[4]=t[5]=t[6]=t[7]=t[8]=t[9]=t[10]=t[11]=t[12]=t[13]=t[14]=t[15]=0),t[15]=this.bytes<<3,this.hash()}},h.prototype.hash=function(){var t,h,i,s=this.h0,e=this.h1,r=this.h2,o=this.h3,n=this.h4,a=this.blocks;for(h=16;80>h;++h)i=a[h-3]^a[h-8]^a[h-14]^a[h-16],a[h]=i<<1|i>>>31;for(h=0;20>h;h+=5)t=e&r|~e&o,i=s<<5|s>>>27,n=i+t+n+1518500249+a[h]<<0,e=e<<30|e>>>2,t=s&e|~s&r,i=n<<5|n>>>27,o=i+t+o+1518500249+a[h+1]<<0,s=s<<30|s>>>2,t=n&s|~n&e,i=o<<5|o>>>27,r=i+t+r+1518500249+a[h+2]<<0,n=n<<30|n>>>2,t=o&n|~o&s,i=r<<5|r>>>27,e=i+t+e+1518500249+a[h+3]<<0,o=o<<30|o>>>2,t=r&o|~r&n,i=e<<5|e>>>27,s=i+t+s+1518500249+a[h+4]<<0,r=r<<30|r>>>2;for(;40>h;h+=5)t=e^r^o,i=s<<5|s>>>27,n=i+t+n+1859775393+a[h]<<0,e=e<<30|e>>>2,t=s^e^r,i=n<<5|n>>>27,o=i+t+o+1859775393+a[h+1]<<0,s=s<<30|s>>>2,t=n^s^e,i=o<<5|o>>>27,r=i+t+r+1859775393+a[h+2]<<0,n=n<<30|n>>>2,t=o^n^s,i=r<<5|r>>>27,e=i+t+e+1859775393+a[h+3]<<0,o=o<<30|o>>>2,t=r^o^n,i=e<<5|e>>>27,s=i+t+s+1859775393+a[h+4]<<0,r=r<<30|r>>>2;for(;60>h;h+=5)t=e&r|e&o|r&o,i=s<<5|s>>>27,n=i+t+n-1894007588+a[h]<<0,e=e<<30|e>>>2,t=s&e|s&r|e&r,i=n<<5|n>>>27,o=i+t+o-1894007588+a[h+1]<<0,s=s<<30|s>>>2,t=n&s|n&e|s&e,i=o<<5|o>>>27,r=i+t+r-1894007588+a[h+2]<<0,n=n<<30|n>>>2,t=o&n|o&s|n&s,i=r<<5|r>>>27,e=i+t+e-1894007588+a[h+3]<<0,o=o<<30|o>>>2,t=r&o|r&n|o&n,i=e<<5|e>>>27,s=i+t+s-1894007588+a[h+4]<<0,r=r<<30|r>>>2;for(;80>h;h+=5)t=e^r^o,i=s<<5|s>>>27,n=i+t+n-899497514+a[h]<<0,e=e<<30|e>>>2,t=s^e^r,i=n<<5|n>>>27,o=i+t+o-899497514+a[h+1]<<0,s=s<<30|s>>>2,t=n^s^e,i=o<<5|o>>>27,r=i+t+r-899497514+a[h+2]<<0,n=n<<30|n>>>2,t=o^n^s,i=r<<5|r>>>27,e=i+t+e-899497514+a[h+3]<<0,o=o<<30|o>>>2,t=r^o^n,i=e<<5|e>>>27,s=i+t+s-899497514+a[h+4]<<0,r=r<<30|r>>>2;this.h0=this.h0+s<<0,this.h1=this.h1+e<<0,this.h2=this.h2+r<<0,this.h3=this.h3+o<<0,this.h4=this.h4+n<<0},h.prototype.hex=function(){this.finalize();var t=this.h0,h=this.h1,i=this.h2,s=this.h3,e=this.h4;return r[t>>28&15]+r[t>>24&15]+r[t>>20&15]+r[t>>16&15]+r[t>>12&15]+r[t>>8&15]+r[t>>4&15]+r[15&t]+r[h>>28&15]+r[h>>24&15]+r[h>>20&15]+r[h>>16&15]+r[h>>12&15]+r[h>>8&15]+r[h>>4&15]+r[15&h]+r[i>>28&15]+r[i>>24&15]+r[i>>20&15]+r[i>>16&15]+r[i>>12&15]+r[i>>8&15]+r[i>>4&15]+r[15&i]+r[s>>28&15]+r[s>>24&15]+r[s>>20&15]+r[s>>16&15]+r[s>>12&15]+r[s>>8&15]+r[s>>4&15]+r[15&s]+r[e>>28&15]+r[e>>24&15]+r[e>>20&15]+r[e>>16&15]+r[e>>12&15]+r[e>>8&15]+r[e>>4&15]+r[15&e]},h.prototype.toString=h.prototype.hex,h.prototype.digest=function(){this.finalize();var t=this.h0,h=this.h1,i=this.h2,s=this.h3,e=this.h4;return[t>>24&255,t>>16&255,t>>8&255,255&t,h>>24&255,h>>16&255,h>>8&255,255&h,i>>24&255,i>>16&255,i>>8&255,255&i,s>>24&255,s>>16&255,s>>8&255,255&s,e>>24&255,e>>16&255,e>>8&255,255&e]},h.prototype.array=h.prototype.digest,h.prototype.arrayBuffer=function(){this.finalize();var t=new ArrayBuffer(20),h=new DataView(t);return h.setUint32(0,this.h0),h.setUint32(4,this.h1),h.setUint32(8,this.h2),h.setUint32(12,this.h3),h.setUint32(16,this.h4),t};var d=c();s?module.exports=d:(t.sha1=d,e&&define(function(){return d}))}(this); \ No newline at end of file diff --git a/package.json b/package.json index 25dc60d..855da67 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,20 @@ { "name": "js-sha1", - "version": "0.3.0", + "version": "0.4.0", "description": "A simple SHA1 hash function for JavaScript supports UTF-8 encoding.", "main": "src/sha1.js", "devDependencies": { "expect.js": "~0.3.1", - "jscoverage": "~0.5.9" + "jscoverage": "~0.5.9", + "mocha": "~2.3.4", + "requirejs": "^2.1.22", + "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/sha1.js --compress --mangle --comments --output build/sha1.min.js" }, "repository": { "type": "git", @@ -23,7 +28,7 @@ "HMAC" ], "license": "MIT", - "author": "emn178 ", + "author": "Chen, Yi-Cyuan ", "homepage": "https://github.com/emn178/js-sha1", "bugs": { "url": "https://github.com/emn178/js-sha1/issues" diff --git a/src/sha1.js b/src/sha1.js index cbaadf7..7cb89fc 100644 --- a/src/sha1.js +++ b/src/sha1.js @@ -1,52 +1,124 @@ /* - * js-sha1 v0.3.0 - * https://github.com/emn178/js-sha1 + * [js-sha1]{@link https://github.com/emn178/js-sha1} * - * Copyright 2014-2015, emn178@gmail.com - * - * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT + * @version 0.4.0 + * @author Chen, Yi-Cyuan [emn178@gmail.com] + * @copyright Chen, Yi-Cyuan 2014-2016 + * @license MIT */ -;(function(root, undefined){ +(function(root) { 'use strict'; - var NODE_JS = typeof(module) != 'undefined'; - if(NODE_JS) { + var NODE_JS = typeof process == 'object' && process.versions && process.versions.node; + if (NODE_JS) { root = global; } + var COMMON_JS = !root.JS_SHA1_TEST && typeof module == 'object' && module.exports; + var AMD = typeof define == 'function' && define.amd; var HEX_CHARS = '0123456789abcdef'.split(''); var EXTRA = [-2147483648, 8388608, 32768, 128]; var SHIFT = [24, 16, 8, 0]; + var OUTPUT_TYPES = ['hex', 'array', 'digest', 'arrayBuffer']; var blocks = []; - var sha1 = function(message) { - var notString = typeof(message) != 'string'; - if(notString && message.constructor == ArrayBuffer) { - message = new Uint8Array(message); - } + var createOutputMethod = function (outputType) { + return function (message) { + return new Sha1(true).update(message)[outputType](); + }; + }; - var h0, h1, h2, h3, h4, block = 0, code, end = false, t, f, - i, j, index = 0, start = 0, bytes = 0, length = message.length; + var createMethod = function () { + var method = createOutputMethod('hex'); + if (NODE_JS) { + method = nodeWrap(method); + } + method.create = function () { + return new Sha1(); + }; + 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(type); + } + return method; + }; - h0 = 0x67452301; - h1 = 0xEFCDAB89; - h2 = 0x98BADCFE; - h3 = 0x10325476; - h4 = 0xC3D2E1F0; + var nodeWrap = function (method) { + var crypto, Buffer; + try { + if (root.JS_SHA1_TEST) { + throw 'JS_SHA1_TEST'; + } + crypto = require('crypto'); + Buffer = require('buffer').Buffer; + } catch (e) { + console.log(e); + return method; + } + var nodeMethod = function (message) { + if (typeof message == 'string') { + return crypto.createHash('sha1').update(message, 'utf8').digest('hex'); + } else if (message.constructor == ArrayBuffer) { + message = new Uint8Array(message); + } else if (message.length === undefined) { + return method(message); + } + return crypto.createHash('sha1').update(new Buffer(message)).digest('hex'); + }; + return nodeMethod; + }; - do { - blocks[0] = block; - blocks[16] = blocks[1] = blocks[2] = blocks[3] = + function Sha1(sharedMemory) { + if (sharedMemory) { + blocks[0] = 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; + this.blocks = blocks; + } else { + this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + } + + this.h0 = 0x67452301; + this.h1 = 0xEFCDAB89; + this.h2 = 0x98BADCFE; + this.h3 = 0x10325476; + this.h4 = 0xC3D2E1F0; + + this.block = this.start = this.bytes = 0; + this.finalized = this.hashed = false; + this.first = true; + } + + Sha1.prototype.update = function (message) { + if (this.finalized) { + return; + } + var notString = typeof(message) != 'string'; + if (notString && message.constructor == root.ArrayBuffer) { + message = new Uint8Array(message); + } + var code, index = 0, i, length = message.length || 0, blocks = this.blocks; + + while (index < length) { + if (this.hashed) { + this.hashed = false; + blocks[0] = this.block; + 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(notString) { - for (i = start;index < length && i < 64; ++index) { + for (i = this.start;index < length && i < 64; ++index) { blocks[i >> 2] |= message[index] << SHIFT[i++ & 3]; } } else { - for (i = start;index < length && i < 64; ++index) { + for (i = this.start;index < length && i < 64; ++index) { code = message.charCodeAt(index); if (code < 0x80) { blocks[i >> 2] |= code << SHIFT[i++ & 3]; @@ -66,138 +138,172 @@ } } } - bytes += i - start; - start = i - 64; - if(index == length) { - blocks[i >> 2] |= EXTRA[i & 3]; - ++index; - } - block = blocks[16]; - if(index > length && i < 56) { - blocks[15] = bytes << 3; - end = true; - } - for(j = 16;j < 80;++j) { - t = blocks[j - 3] ^ blocks[j - 8] ^ blocks[j - 14] ^ blocks[j - 16]; - blocks[j] = (t << 1) | (t >>> 31); + this.lastByteIndex = i; + this.bytes += i - this.start; + if (i >= 64) { + this.block = blocks[16]; + this.start = i - 64; + this.hash(); + this.hashed = true; + } else { + this.start = i; } + } + return this; + }; - var a = h0, b = h1, c = h2, d = h3, e = h4; - for(j = 0;j < 20;j += 5) { - f = (b & c) | ((~b) & d); - t = (a << 5) | (a >>> 27); - e = t + f + e + 1518500249 + blocks[j] << 0; - b = (b << 30) | (b >>> 2); - - f = (a & b) | ((~a) & c); - t = (e << 5) | (e >>> 27); - d = t + f + d + 1518500249 + blocks[j + 1] << 0; - a = (a << 30) | (a >>> 2); - - f = (e & a) | ((~e) & b); - t = (d << 5) | (d >>> 27); - c = t + f + c + 1518500249 + blocks[j + 2] << 0; - e = (e << 30) | (e >>> 2); - - f = (d & e) | ((~d) & a); - t = (c << 5) | (c >>> 27); - b = t + f + b + 1518500249 + blocks[j + 3] << 0; - d = (d << 30) | (d >>> 2); - - f = (c & d) | ((~c) & e); - t = (b << 5) | (b >>> 27); - a = t + f + a + 1518500249 + blocks[j + 4] << 0; - c = (c << 30) | (c >>> 2); + Sha1.prototype.finalize = function () { + if (this.finalized) { + return; + } + this.finalized = true; + var blocks = this.blocks, i = this.lastByteIndex; + blocks[16] = this.block; + blocks[i >> 2] |= EXTRA[i & 3]; + this.block = blocks[16]; + if (i >= 56) { + if (!this.hashed) { + this.hash(); } + blocks[0] = this.block; + 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; + } + blocks[15] = this.bytes << 3; + this.hash(); + }; - for(;j < 40;j += 5) { - f = b ^ c ^ d; - t = (a << 5) | (a >>> 27); - e = t + f + e + 1859775393 + blocks[j] << 0; - b = (b << 30) | (b >>> 2); - - f = a ^ b ^ c; - t = (e << 5) | (e >>> 27); - d = t + f + d + 1859775393 + blocks[j + 1] << 0; - a = (a << 30) | (a >>> 2); - - f = e ^ a ^ b; - t = (d << 5) | (d >>> 27); - c = t + f + c + 1859775393 + blocks[j + 2] << 0; - e = (e << 30) | (e >>> 2); - - f = d ^ e ^ a; - t = (c << 5) | (c >>> 27); - b = t + f + b + 1859775393 + blocks[j + 3] << 0; - d = (d << 30) | (d >>> 2); - - f = c ^ d ^ e; - t = (b << 5) | (b >>> 27); - a = t + f + a + 1859775393 + blocks[j + 4] << 0; - c = (c << 30) | (c >>> 2); - } + Sha1.prototype.hash = function () { + var a = this.h0, b = this.h1, c = this.h2, d = this.h3, e = this.h4; + var f, j, t, blocks = this.blocks; - for(;j < 60;j += 5) { - f = (b & c) | (b & d) | (c & d); - t = (a << 5) | (a >>> 27); - e = t + f + e - 1894007588 + blocks[j] << 0; - b = (b << 30) | (b >>> 2); - - f = (a & b) | (a & c) | (b & c); - t = (e << 5) | (e >>> 27); - d = t + f + d - 1894007588 + blocks[j + 1] << 0; - a = (a << 30) | (a >>> 2); - - f = (e & a) | (e & b) | (a & b); - t = (d << 5) | (d >>> 27); - c = t + f + c - 1894007588 + blocks[j + 2] << 0; - e = (e << 30) | (e >>> 2); - - f = (d & e) | (d & a) | (e & a); - t = (c << 5) | (c >>> 27); - b = t + f + b - 1894007588 + blocks[j + 3] << 0; - d = (d << 30) | (d >>> 2); - - f = (c & d) | (c & e) | (d & e); - t = (b << 5) | (b >>> 27); - a = t + f + a - 1894007588 + blocks[j + 4] << 0; - c = (c << 30) | (c >>> 2); - } + for(j = 16;j < 80;++j) { + t = blocks[j - 3] ^ blocks[j - 8] ^ blocks[j - 14] ^ blocks[j - 16]; + blocks[j] = (t << 1) | (t >>> 31); + } - for(;j < 80;j += 5) { - f = b ^ c ^ d; - t = (a << 5) | (a >>> 27); - e = t + f + e - 899497514 + blocks[j] << 0; - b = (b << 30) | (b >>> 2); - - f = a ^ b ^ c; - t = (e << 5) | (e >>> 27); - d = t + f + d - 899497514 + blocks[j + 1] << 0; - a = (a << 30) | (a >>> 2); - - f = e ^ a ^ b; - t = (d << 5) | (d >>> 27); - c = t + f + c - 899497514 + blocks[j + 2] << 0; - e = (e << 30) | (e >>> 2); - - f = d ^ e ^ a; - t = (c << 5) | (c >>> 27); - b = t + f + b - 899497514 + blocks[j + 3] << 0; - d = (d << 30) | (d >>> 2); - - f = c ^ d ^ e; - t = (b << 5) | (b >>> 27); - a = t + f + a - 899497514 + blocks[j + 4] << 0; - c = (c << 30) | (c >>> 2); - } + for(j = 0;j < 20;j += 5) { + f = (b & c) | ((~b) & d); + t = (a << 5) | (a >>> 27); + e = t + f + e + 1518500249 + blocks[j] << 0; + b = (b << 30) | (b >>> 2); + + f = (a & b) | ((~a) & c); + t = (e << 5) | (e >>> 27); + d = t + f + d + 1518500249 + blocks[j + 1] << 0; + a = (a << 30) | (a >>> 2); + + f = (e & a) | ((~e) & b); + t = (d << 5) | (d >>> 27); + c = t + f + c + 1518500249 + blocks[j + 2] << 0; + e = (e << 30) | (e >>> 2); + + f = (d & e) | ((~d) & a); + t = (c << 5) | (c >>> 27); + b = t + f + b + 1518500249 + blocks[j + 3] << 0; + d = (d << 30) | (d >>> 2); + + f = (c & d) | ((~c) & e); + t = (b << 5) | (b >>> 27); + a = t + f + a + 1518500249 + blocks[j + 4] << 0; + c = (c << 30) | (c >>> 2); + } + + for(;j < 40;j += 5) { + f = b ^ c ^ d; + t = (a << 5) | (a >>> 27); + e = t + f + e + 1859775393 + blocks[j] << 0; + b = (b << 30) | (b >>> 2); + + f = a ^ b ^ c; + t = (e << 5) | (e >>> 27); + d = t + f + d + 1859775393 + blocks[j + 1] << 0; + a = (a << 30) | (a >>> 2); + + f = e ^ a ^ b; + t = (d << 5) | (d >>> 27); + c = t + f + c + 1859775393 + blocks[j + 2] << 0; + e = (e << 30) | (e >>> 2); + + f = d ^ e ^ a; + t = (c << 5) | (c >>> 27); + b = t + f + b + 1859775393 + blocks[j + 3] << 0; + d = (d << 30) | (d >>> 2); + + f = c ^ d ^ e; + t = (b << 5) | (b >>> 27); + a = t + f + a + 1859775393 + blocks[j + 4] << 0; + c = (c << 30) | (c >>> 2); + } + + for(;j < 60;j += 5) { + f = (b & c) | (b & d) | (c & d); + t = (a << 5) | (a >>> 27); + e = t + f + e - 1894007588 + blocks[j] << 0; + b = (b << 30) | (b >>> 2); + + f = (a & b) | (a & c) | (b & c); + t = (e << 5) | (e >>> 27); + d = t + f + d - 1894007588 + blocks[j + 1] << 0; + a = (a << 30) | (a >>> 2); + + f = (e & a) | (e & b) | (a & b); + t = (d << 5) | (d >>> 27); + c = t + f + c - 1894007588 + blocks[j + 2] << 0; + e = (e << 30) | (e >>> 2); + + f = (d & e) | (d & a) | (e & a); + t = (c << 5) | (c >>> 27); + b = t + f + b - 1894007588 + blocks[j + 3] << 0; + d = (d << 30) | (d >>> 2); + + f = (c & d) | (c & e) | (d & e); + t = (b << 5) | (b >>> 27); + a = t + f + a - 1894007588 + blocks[j + 4] << 0; + c = (c << 30) | (c >>> 2); + } + + for(;j < 80;j += 5) { + f = b ^ c ^ d; + t = (a << 5) | (a >>> 27); + e = t + f + e - 899497514 + blocks[j] << 0; + b = (b << 30) | (b >>> 2); + + f = a ^ b ^ c; + t = (e << 5) | (e >>> 27); + d = t + f + d - 899497514 + blocks[j + 1] << 0; + a = (a << 30) | (a >>> 2); + + f = e ^ a ^ b; + t = (d << 5) | (d >>> 27); + c = t + f + c - 899497514 + blocks[j + 2] << 0; + e = (e << 30) | (e >>> 2); - h0 = h0 + a << 0; - h1 = h1 + b << 0; - h2 = h2 + c << 0; - h3 = h3 + d << 0; - h4 = h4 + e << 0; - } while(!end); + f = d ^ e ^ a; + t = (c << 5) | (c >>> 27); + b = t + f + b - 899497514 + blocks[j + 3] << 0; + d = (d << 30) | (d >>> 2); + + f = c ^ d ^ e; + t = (b << 5) | (b >>> 27); + a = t + f + a - 899497514 + blocks[j + 4] << 0; + c = (c << 30) | (c >>> 2); + } + + this.h0 = this.h0 + a << 0; + this.h1 = this.h1 + b << 0; + this.h2 = this.h2 + c << 0; + this.h3 = this.h3 + d << 0; + this.h4 = this.h4 + e << 0; + }; + + Sha1.prototype.hex = function () { + this.finalize(); + + var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4; return HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] + HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] + @@ -221,20 +327,47 @@ HEX_CHARS[(h4 >> 4) & 0x0F] + HEX_CHARS[h4 & 0x0F]; }; - if(!root.JS_SHA1_TEST && typeof(module) != 'undefined') { - var crypto = require('crypto'); - var Buffer = require('buffer').Buffer; + Sha1.prototype.toString = Sha1.prototype.hex; - module.exports = function(message) { - if(typeof(message) == 'string') { - return crypto.createHash('sha1').update(message, 'utf8').digest('hex'); - } - if(message.constructor == ArrayBuffer) { - message = new Uint8Array(message); - } - return crypto.createHash('sha1').update(new Buffer(message)).digest('hex'); - }; - } else if(root) { - root.sha1 = sha1; + Sha1.prototype.digest = function () { + this.finalize(); + + var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4; + + return [ + (h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, h0 & 0xFF, + (h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, h1 & 0xFF, + (h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, h2 & 0xFF, + (h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, h3 & 0xFF, + (h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, h4 & 0xFF + ]; + }; + + Sha1.prototype.array = Sha1.prototype.digest; + + Sha1.prototype.arrayBuffer = function () { + this.finalize(); + + var buffer = new ArrayBuffer(20); + var dataView = new DataView(buffer); + dataView.setUint32(0, this.h0); + dataView.setUint32(4, this.h1); + dataView.setUint32(8, this.h2); + dataView.setUint32(12, this.h3); + dataView.setUint32(16, this.h4); + return buffer; + }; + + var exports = createMethod(); + + if (COMMON_JS) { + module.exports = exports; + } else { + root.sha1 = exports; + if (AMD) { + define(function () { + return exports; + }); + } } }(this)); diff --git a/tests/node-test.js b/tests/node-test.js index d8a2426..dda12da 100644 --- a/tests/node-test.js +++ b/tests/node-test.js @@ -9,3 +9,15 @@ sha1 = null; JS_SHA1_TEST = true; require('../src/sha1.js'); require('./test.js'); + +delete require.cache[require.resolve('../src/sha1.js')]; +delete require.cache[require.resolve('./test.js')]; +sha1 = null; + +define = function (func) { + sha1 = func(); + require('./test.js'); +}; +define.amd = true; + +require('../src/sha1.js'); diff --git a/tests/test.js b/tests/test.js index 1bea771..df29504 100644 --- a/tests/test.js +++ b/tests/test.js @@ -1,66 +1,179 @@ (function(sha1) { - describe('ascii', function() { - describe('less than 64 bytes', function() { - it('should be successful', function() { - expect(sha1('')).to.be('da39a3ee5e6b4b0d3255bfef95601890afd80709'); - expect(sha1('The quick brown fox jumps over the lazy dog')).to.be('2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'); - expect(sha1('The quick brown fox jumps over the lazy dog.')).to.be('408d94384216f890ff7a0c3528e8bed1e0b01621'); - }); - }); + Array.prototype.toHexString = ArrayBuffer.prototype.toHexString = function () { + var array = new Uint8Array(this); + var hex = ''; + for (var i = 0;i < array.length;++i) { + var c = array[i].toString('16'); + hex += c.length == 1 ? '0' + c : c; + } + return hex; + }; - describe('more than 64 bytes', function() { - it('should be successful', function() { - expect(sha1('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('8690faab7755408a03875895176fac318f14a699'); - }); - }); - }); + var testCases = { + 'ascii': { + 'da39a3ee5e6b4b0d3255bfef95601890afd80709': '', + '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12': 'The quick brown fox jumps over the lazy dog', + '408d94384216f890ff7a0c3528e8bed1e0b01621': 'The quick brown fox jumps over the lazy dog.' + }, + 'ascii more than 64 bytes': { + '8690faab7755408a03875895176fac318f14a699': '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': { + '7be2d2d20c106eee0836c9bc2b939890a78e8fb3': '中文', + '9e4e5d978deced901d621475b03f1ded19e945bf': 'aécio', + '4667688a63420661469c8dbc0f871770349bab08': '𠜎' + }, + 'UTF8 more than 64 bytes': { + 'ad8aae581c915fe01c4964a5e8b322cae74ee5c5': '訊息摘要演算法第五版(英語:Message-Digest Algorithm 5,縮寫為MD5),是當前電腦領域用於確保資訊傳輸完整一致而廣泛使用的雜湊演算法之一', + '3a15ad3ce9efdd4bf982eaaaecdeda36a887a3f9': '訊息摘要演算法第五版(英語:Message-Digest Algorithm 5,縮寫為MD5),是當前電腦領域用於確保資訊傳輸完整一致而廣泛使用的雜湊演算法之一(又譯雜湊演算法、摘要演算法等),主流程式語言普遍已有MD5的實作。' + }, + 'special length': { + '4cdeae78e8b7285aef73e0a15eec7d5b30f3f3e3': '0123456780123456780123456780123456780123456780123456780', + 'e657e6bb6b5d0c2bf7e929451c14a5302589a60b': '01234567801234567801234567801234567801234567801234567801', + 'e7ad97591c1a99d54d80751d341899769884c75a': '0123456780123456780123456780123456780123456780123456780123456780', + '55a13698cdc010c0d16dab2f7dc10f43a713f12f': '01234567801234567801234567801234567801234567801234567801234567801234567', + '006575418c27b0158e55a6d261c46f86b33a496a': '012345678012345678012345678012345678012345678012345678012345678012345678' + }, + 'Array': { + 'da39a3ee5e6b4b0d3255bfef95601890afd80709': [], + '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12': [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], + '55a13698cdc010c0d16dab2f7dc10f43a713f12f': [48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55] + }, + 'Uint8Array': { + '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12': 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]) + }, + 'Int8Array': { + '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12': 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]) + }, + 'ArrayBuffer': { + '5ba93c9db0cff93f52b521d7420e43f6eda2784f': new ArrayBuffer(1) + }, + 'Object': { + 'da39a3ee5e6b4b0d3255bfef95601890afd80709': {}, + 'da39a3ee5e6b4b0d3255bfef95601890afd80709': {what: 'ever'} + } + }; - describe('UTF8', function() { - describe('less than 64 bytes', function() { - it('should be successful', function() { - expect(sha1('中文')).to.be('7be2d2d20c106eee0836c9bc2b939890a78e8fb3'); - expect(sha1('aécio')).to.be('9e4e5d978deced901d621475b03f1ded19e945bf'); - expect(sha1('𠜎')).to.be('4667688a63420661469c8dbc0f871770349bab08'); - }); - }); + if (typeof process == 'object') { + testCases['Buffer'] = { + 'da39a3ee5e6b4b0d3255bfef95601890afd80709': new Buffer(0), + '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12': new Buffer(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])) + } + } - describe('more than 64 bytes', function() { - it('should be successful', function() { - expect(sha1('訊息摘要演算法第五版(英語:Message-Digest Algorithm 5,縮寫為MD5),是當前電腦領域用於確保資訊傳輸完整一致而廣泛使用的雜湊演算法之一')).to.be('ad8aae581c915fe01c4964a5e8b322cae74ee5c5'); - expect(sha1('訊息摘要演算法第五版(英語:Message-Digest Algorithm 5,縮寫為MD5),是當前電腦領域用於確保資訊傳輸完整一致而廣泛使用的雜湊演算法之一(又譯雜湊演算法、摘要演算法等),主流程式語言普遍已有MD5的實作。')).to.be('3a15ad3ce9efdd4bf982eaaaecdeda36a887a3f9'); - }); - }); - }); - - describe('special length', function() { - it('should be successful', function() { - expect(sha1('0123456780123456780123456780123456780123456780123456780')).to.be('4cdeae78e8b7285aef73e0a15eec7d5b30f3f3e3'); - expect(sha1('01234567801234567801234567801234567801234567801234567801')).to.be('e657e6bb6b5d0c2bf7e929451c14a5302589a60b'); - expect(sha1('0123456780123456780123456780123456780123456780123456780123456780')).to.be('e7ad97591c1a99d54d80751d341899769884c75a'); - expect(sha1('01234567801234567801234567801234567801234567801234567801234567801234567')).to.be('55a13698cdc010c0d16dab2f7dc10f43a713f12f'); - expect(sha1('012345678012345678012345678012345678012345678012345678012345678012345678')).to.be('006575418c27b0158e55a6d261c46f86b33a496a'); - }); - }); + var methods = [ + { + name: 'sha1', + call: sha1, + }, + { + name: 'sha1.hex', + call: sha1.hex + }, + { + name: 'sha1.array', + call: function (message) { + return sha1.array(message).toHexString(); + } + }, + { + name: 'sha1.digest', + call: function (message) { + return sha1.digest(message).toHexString(); + } + }, + { + name: 'sha1.arrayBuffer', + call: function (message) { + return sha1.arrayBuffer(message).toHexString(); + } + } + ]; - describe('Array', function() { - describe('Array', function() { - it('should be successful', function() { - expect(sha1([])).to.be('da39a3ee5e6b4b0d3255bfef95601890afd80709'); - expect(sha1([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])).to.be('2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'); - expect(sha1([48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55, 56, 48, 49, 50, 51, 52, 53, 54, 55])).to.be('55a13698cdc010c0d16dab2f7dc10f43a713f12f'); - }); - }); + var classMethods = [ + { + name: 'create', + call: function (message) { + return sha1.create().update(message).toString(); + } + }, + { + name: 'update', + call: function (message) { + return sha1.update(message).toString(); + } + }, + { + name: 'hex', + call: function (message) { + return sha1.update(message).hex(); + } + }, + { + name: 'array', + call: function (message) { + return sha1.update(message).array().toHexString(); + } + }, + { + name: 'digest', + call: function (message) { + return sha1.update(message).digest().toHexString(); + } + }, + { + name: 'arrayBuffer', + call: function (message) { + return sha1.update(message).arrayBuffer().toHexString(); + } + }, + { + name: 'finalize', + call: function (message) { + var hash = sha1.update(message); + hash.hex(); + hash.update(message); + return hash.hex(); + } + } + ]; - describe('Uint8Array', function() { - it('should be successful', function() { - expect(sha1(new Uint8Array([]))).to.be('da39a3ee5e6b4b0d3255bfef95601890afd80709'); - }); + methods.forEach(function (method) { + describe('#' + method.name, 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(method.call(message)).to.be(hash); + }); + })(testCase[hash], hash); + } + }); + })(testCaseName); + } }); + }); - describe('ArrayBuffer', function() { - it('should be successful', function() { - expect(sha1(new ArrayBuffer(0))).to.be('da39a3ee5e6b4b0d3255bfef95601890afd80709'); - expect(sha1(new ArrayBuffer(1))).to.be('5ba93c9db0cff93f52b521d7420e43f6eda2784f'); + describe('Sha1', function () { + classMethods.forEach(function (method) { + describe('#' + method.name, 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(method.call(message)).to.be(hash); + }); + })(testCase[hash], hash); + } + }); + })(testCaseName); + } }); }); });