git-sha1.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. "use strict";
  2. var isNode = typeof process === 'object' &&
  3. typeof process.versions === 'object' &&
  4. process.versions.node &&
  5. process.__atom_type !== "renderer";
  6. var shared, create, crypto;
  7. if (isNode) {
  8. var nodeRequire = require; // Prevent mine.js from seeing this require
  9. crypto = nodeRequire('crypto');
  10. create = createNode;
  11. }
  12. else {
  13. shared = new Uint32Array(80);
  14. create = createJs;
  15. }
  16. // Input chunks must be either arrays of bytes or "raw" encoded strings
  17. module.exports = function sha1(buffer) {
  18. if (buffer === undefined) return create(false);
  19. var shasum = create(true);
  20. shasum.update(buffer);
  21. return shasum.digest();
  22. };
  23. // Use node's openssl bindings when available
  24. function createNode() {
  25. var shasum = crypto.createHash('sha1');
  26. return {
  27. update: function (buffer) {
  28. return shasum.update(buffer);
  29. },
  30. digest: function () {
  31. return shasum.digest('hex');
  32. }
  33. };
  34. }
  35. // A pure JS implementation of sha1 for non-node environments.
  36. function createJs(sync) {
  37. var h0 = 0x67452301;
  38. var h1 = 0xEFCDAB89;
  39. var h2 = 0x98BADCFE;
  40. var h3 = 0x10325476;
  41. var h4 = 0xC3D2E1F0;
  42. // The first 64 bytes (16 words) is the data chunk
  43. var block, offset = 0, shift = 24;
  44. var totalLength = 0;
  45. if (sync) block = shared;
  46. else block = new Uint32Array(80);
  47. return { update: update, digest: digest };
  48. // The user gave us more data. Store it!
  49. function update(chunk) {
  50. if (typeof chunk === "string") return updateString(chunk);
  51. var length = chunk.length;
  52. totalLength += length * 8;
  53. for (var i = 0; i < length; i++) {
  54. write(chunk[i]);
  55. }
  56. }
  57. function updateString(string) {
  58. var length = string.length;
  59. totalLength += length * 8;
  60. for (var i = 0; i < length; i++) {
  61. write(string.charCodeAt(i));
  62. }
  63. }
  64. function write(byte) {
  65. block[offset] |= (byte & 0xff) << shift;
  66. if (shift) {
  67. shift -= 8;
  68. }
  69. else {
  70. offset++;
  71. shift = 24;
  72. }
  73. if (offset === 16) processBlock();
  74. }
  75. // No more data will come, pad the block, process and return the result.
  76. function digest() {
  77. // Pad
  78. write(0x80);
  79. if (offset > 14 || (offset === 14 && shift < 24)) {
  80. processBlock();
  81. }
  82. offset = 14;
  83. shift = 24;
  84. // 64-bit length big-endian
  85. write(0x00); // numbers this big aren't accurate in javascript anyway
  86. write(0x00); // ..So just hard-code to zero.
  87. write(totalLength > 0xffffffffff ? totalLength / 0x10000000000 : 0x00);
  88. write(totalLength > 0xffffffff ? totalLength / 0x100000000 : 0x00);
  89. for (var s = 24; s >= 0; s -= 8) {
  90. write(totalLength >> s);
  91. }
  92. // At this point one last processBlock() should trigger and we can pull out the result.
  93. return toHex(h0) +
  94. toHex(h1) +
  95. toHex(h2) +
  96. toHex(h3) +
  97. toHex(h4);
  98. }
  99. // We have a full block to process. Let's do it!
  100. function processBlock() {
  101. // Extend the sixteen 32-bit words into eighty 32-bit words:
  102. for (var i = 16; i < 80; i++) {
  103. var w = block[i - 3] ^ block[i - 8] ^ block[i - 14] ^ block[i - 16];
  104. block[i] = (w << 1) | (w >>> 31);
  105. }
  106. // log(block);
  107. // Initialize hash value for this chunk:
  108. var a = h0;
  109. var b = h1;
  110. var c = h2;
  111. var d = h3;
  112. var e = h4;
  113. var f, k;
  114. // Main loop:
  115. for (i = 0; i < 80; i++) {
  116. if (i < 20) {
  117. f = d ^ (b & (c ^ d));
  118. k = 0x5A827999;
  119. }
  120. else if (i < 40) {
  121. f = b ^ c ^ d;
  122. k = 0x6ED9EBA1;
  123. }
  124. else if (i < 60) {
  125. f = (b & c) | (d & (b | c));
  126. k = 0x8F1BBCDC;
  127. }
  128. else {
  129. f = b ^ c ^ d;
  130. k = 0xCA62C1D6;
  131. }
  132. var temp = (a << 5 | a >>> 27) + f + e + k + (block[i]|0);
  133. e = d;
  134. d = c;
  135. c = (b << 30 | b >>> 2);
  136. b = a;
  137. a = temp;
  138. }
  139. // Add this chunk's hash to result so far:
  140. h0 = (h0 + a) | 0;
  141. h1 = (h1 + b) | 0;
  142. h2 = (h2 + c) | 0;
  143. h3 = (h3 + d) | 0;
  144. h4 = (h4 + e) | 0;
  145. // The block is now reusable.
  146. offset = 0;
  147. for (i = 0; i < 16; i++) {
  148. block[i] = 0;
  149. }
  150. }
  151. function toHex(word) {
  152. var hex = "";
  153. for (var i = 28; i >= 0; i -= 4) {
  154. hex += ((word >> i) & 0xf).toString(16);
  155. }
  156. return hex;
  157. }
  158. }