diff --git a/.covignore b/.covignore new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f5cd45c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: node_js +node_js: + - "0.11" + - "0.10" + - "0.8" +install: + - npm install mocha -g + - npm install coveralls -g + - npm install mocha-lcov-reporter -g + - npm install +script: + - npm run-script coveralls diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a3b74a..8afb8d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 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 diff --git a/LICENSE.txt b/LICENSE.txt index dff2ebd..58074d3 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright 2014 emn178@gmail.com +Copyright 2014-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 diff --git a/README.md b/README.md index 4666dff..df290ee 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,49 @@ # js-sha1 +[](https://travis-ci.org/emn178/js-sha1) +[](https://coveralls.io/r/emn178/js-sha1?branch=master) +[](https://nodei.co/npm/js-sha1/) A simple SHA1 hash function for JavaScript supports UTF-8 encoding. -## Install +## Demo +[SHA1 Online](http://emn178.github.io/online-tools/sha1.html) + +## Download +[Compress](https://raw.github.com/emn178/js-sha1/master/build/sha1.min.js) +[Uncompress](https://raw.github.com/emn178/js-sha1/master/src/sha1.js) + +## Installation +You can also install js-sha1 by using Bower. + + bower install js-sha1 + For node.js, you can use this command to install: npm install js-sha1 ## Usage -If you use node.js, you should require the module first: +You could use like this: ```JavaScript -sha1 = require('js-sha1'); +sha1('Message to hash'); ``` -And you could use like this: +If you use node.js, you should require the module first: ```JavaScript -sha1('Message to hash'); +sha1 = require('js-sha1'); ``` + +### Methods + +#### sha1(str, asciiOnly) + +Hash string to sha1, set asciiOnly to true for better performace if you ensure input is ascii. + +##### *str: `String`* + +String to hash. + +##### *asciiOnly: `Boolean` (default: `false`)* + +Specify the string encoding is ASCII. + ## Example Code ```JavaScript @@ -38,15 +67,6 @@ Output 7be2d2d20c106eee0836c9bc2b939890a78e8fb3 -## Tests -You can open `tests/index.html` in browser or use node.js to run test - - node tests/node-test.js - -or - - npm test - ## 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 new file mode 100644 index 0000000..92d5c5a --- /dev/null +++ b/bower.json @@ -0,0 +1,9 @@ +{ + "name": "js-sha1", + "version": "0.1.3", + "main": ["build/sha1.min.js"], + "ignore": [ + "samples", + "tests" + ] +} diff --git a/package.json b/package.json index b9c6be0..3566fad 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,15 @@ { "name": "js-sha1", - "version": "0.1.2", + "version": "0.1.3", "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" + }, "scripts": { - "test": "node tests/node-test.js" + "test": "mocha tests/node-test.js -r jscoverage", + "coveralls": "mocha tests/node-test.js -R mocha-lcov-reporter -r jscoverage | coveralls" }, "repository": { "type": "git", diff --git a/src/sha1.js b/src/sha1.js index 61368c0..c594935 100644 --- a/src/sha1.js +++ b/src/sha1.js @@ -1,38 +1,36 @@ /* - * js-sha1 v0.1.2 + * js-sha1 v0.1.3 * https://github.com/emn178/js-sha1 * - * Copyright 2014, emn178@gmail.com + * Copyright 2014-2015, emn178@gmail.com * * Licensed under the MIT license: * http://www.opensource.org/licenses/MIT */ - -(function(root, undefined){ +;(function(root, undefined){ 'use strict'; - var HEX_CHARS = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; - var HEX_TABLE = { - '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, - 'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14, 'f': 15, - 'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15 - }; + var HEX_CHARS = '0123456789abcdef'.split(''); - var sha1 = function(message) { - var blocks = hasUTF8(message) ? UTF8toBlocks(message) : ASCIItoBlocks(message); - var h0 = 0x67452301; - var h1 = 0xEFCDAB89; - var h2 = 0x98BADCFE; - var h3 = 0x10325476; - var h4 = 0xC3D2E1F0; - - for(var i = 0, length = blocks.length;i < length;i += 16) - { - var w = []; - for(var j = 0;j < 16;++j) + var sha1 = function(message, asciiOnly) { + var blocks, h0, h1, h2, h3, h4; + if(!asciiOnly && /[^\x00-\x7F]/.test(message)) { + blocks = getBlocksFromUtf8(message); + } else { + blocks = getBlocksFromAscii(message); + } + h0 = 0x67452301; + h1 = 0xEFCDAB89; + h2 = 0x98BADCFE; + h3 = 0x10325476; + h4 = 0xC3D2E1F0; + + for(var i = 0, length = blocks.length;i < length;i += 16) { + var w = [], j; + for(j = 0;j < 16;++j) { w[j] = blocks[i + j]; - for(var j = 16;j < 80;++j) - { + } + for(j = 16;j < 80;++j) { var x = w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16]; w[j] = leftrotate(x, 1); } @@ -42,10 +40,9 @@ var c = h2; var d = h3; var e = h4; - var f, k, tmp; + var f, tmp; - for(var j = 0;j < 20;++j) - { + for(j = 0;j < 20;++j) { f = (b & c) | ((~b) & d); tmp = leftrotate(a, 5) + f + e + 0x5A827999 + w[j]; e = d; @@ -55,8 +52,7 @@ a = tmp; } - for(;j < 40;++j) - { + for(;j < 40;++j) { f = b ^ c ^ d; tmp = leftrotate(a, 5) + f + e + 0x6ED9EBA1 + w[j]; e = d; @@ -67,8 +63,7 @@ } // k = 0x8F1BBCDC; - for(;j < 60;++j) - { + for(;j < 60;++j) { f = (b & c) | (b & d) | (c & d); tmp = leftrotate(a, 5) + f + e + 0x8F1BBCDC + w[j]; e = d; @@ -78,8 +73,7 @@ a = tmp; } - for(;j < 80;++j) - { + for(;j < 80;++j) { f = b ^ c ^ d; tmp = leftrotate(a, 5) + f + e + 0xCA62C1D6 + w[j]; e = d; @@ -104,63 +98,76 @@ }; var toHexString = function(num) { - var hex = ""; - for(var i = 0; i < 4; i++) - { + var hex = ''; + for(var i = 0; i < 4; i++) { var offset = 3 - i << 3; hex += HEX_CHARS[(num >> (offset + 4)) & 0x0F] + HEX_CHARS[(num >> offset) & 0x0F]; } return hex; }; - var hasUTF8 = function(message) { - var i = message.length; - while(i--) - if(message.charCodeAt(i) > 127) - return true; - return false; + var getBytesFromUtf8 = function(str) { + var bytes = [], index = 0; + for (var i = 0;i < str.length; i++) { + var c = str.charCodeAt(i); + if (c < 0x80) { + bytes[index++] = c; + } else if (c < 0x800) { + bytes[index++] = 0xc0 | (c >> 6); + bytes[index++] = 0x80 | (c & 0x3f); + } else if (c < 0xd800 || c >= 0xe000) { + bytes[index++] = 0xe0 | (c >> 12); + bytes[index++] = 0x80 | ((c >> 6) & 0x3f); + bytes[index++] = 0x80 | (c & 0x3f); + } else { + c = 0x10000 + (((c & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff)); + bytes[index++] = 0xf0 | (c >> 18); + bytes[index++] = 0x80 | ((c >> 12) & 0x3f); + bytes[index++] = 0x80 | ((c >> 6) & 0x3f); + bytes[index++] = 0x80 | (c & 0x3f); + } + } + return bytes; }; - var ASCIItoBlocks = function(message) { + var getBlocksFromAscii = function(message) { // a block is 32 bits(4 bytes), a chunk is 512 bits(64 bytes) var length = message.length; var chunkCount = ((length + 8) >> 6) + 1; var blockCount = chunkCount << 4; // chunkCount * 16 - var blocks = []; - var i; - for(i = 0;i < blockCount;++i) + var blocks = [], i; + for(i = 0;i < blockCount;++i) { blocks[i] = 0; - for(i = 0;i < length;++i) - blocks[i >> 2] |= message.charCodeAt(i) << (3 - (i % 4) << 3); - blocks[i >> 2] |= 0x80 << (3 - (i % 4) << 3); + } + for(i = 0;i < length;++i) { + blocks[i >> 2] |= message.charCodeAt(i) << (3 - (i & 3) << 3); + } + blocks[i >> 2] |= 0x80 << (3 - (i & 3) << 3); blocks[blockCount - 1] = length << 3; // length * 8 return blocks; }; - var UTF8toBlocks = function(message) { - var uri = encodeURIComponent(message); - var blocks = []; - for(var i = 0, bytes = 0, length = uri.length;i < length;++i) - { - var c = uri.charCodeAt(i); - if(c == 37) // % - blocks[bytes >> 2] |= ((HEX_TABLE[uri.charAt(++i)] << 4) | HEX_TABLE[uri.charAt(++i)]) << (3 - (bytes % 4) << 3); - else - blocks[bytes >> 2] |= c << (3 - (bytes % 4) << 3); - ++bytes; - } - var chunkCount = ((bytes + 8) >> 6) + 1; + var getBlocksFromUtf8 = function(message) { + var bytes = getBytesFromUtf8(message); + var length = bytes.length; + var chunkCount = ((length + 8) >> 6) + 1; var blockCount = chunkCount << 4; // chunkCount * 16 - var index = bytes >> 2; - blocks[index] |= 0x80 << (3 - (bytes % 4) << 3); - for(var i = index + 1;i < blockCount;++i) + var blocks = [], i; + for(i = 0;i < blockCount;++i) { blocks[i] = 0; - blocks[blockCount - 1] = bytes << 3; // bytes * 8 + } + for(i = 0;i < length;++i) { + blocks[i >> 2] |= bytes[i] << (3 - (i & 3) << 3); + } + blocks[i >> 2] |= 0x80 << (3 - (i & 3) << 3); + blocks[blockCount - 1] = length << 3; // length * 8 return blocks; }; - if(typeof(module) != 'undefined') + if(typeof(module) != 'undefined') { module.exports = sha1; - else if(root) + } + else if(root) { root.sha1 = sha1; + } }(this)); diff --git a/tests/debug.js b/tests/debug.js deleted file mode 100644 index ceceea8..0000000 --- a/tests/debug.js +++ /dev/null @@ -1,12 +0,0 @@ -(function(root){ - var assert = function (title, expect, actual) { - if(expect == actual) - console.log(title + ': true'); - else - console.log(title + ': false', 'Except:' + expect, 'Actual: ' + actual); - }; - if(typeof(module) != 'undefined') - global.assert = assert; - else if(root) - root.assert = assert; -})(this); diff --git a/tests/index.html b/tests/index.html index f05a0d7..813dcb3 100644 --- a/tests/index.html +++ b/tests/index.html @@ -3,10 +3,20 @@