16 changed files with 545 additions and 312 deletions
File diff suppressed because one or more lines are too long
@ -0,0 +1,139 @@ |
|||
var Script = require('./script'), |
|||
util = require('./util'), |
|||
conv = require('./convert'), |
|||
key = require('./eckey'), |
|||
base58 = require('./base58'), |
|||
Crypto = require('./crypto-js/crypto'), |
|||
ECPointFp = require('./jsbn/ec').ECPointFp, |
|||
sec = require('./jsbn/sec'), |
|||
ecparams = sec("secp256k1"); |
|||
|
|||
var BIP32key = function(opts) { |
|||
if (!opts) opts = {} |
|||
if (typeof opts == "string") { |
|||
try { |
|||
opts = BIP32key.prototype.deserialize(opts); |
|||
} |
|||
catch(e) { |
|||
opts = BIP32key.prototype.fromMasterKey(opts); |
|||
} |
|||
} |
|||
this.vbytes = opts.vbytes; |
|||
this.depth = opts.depth; |
|||
this.fingerprint = opts.fingerprint; |
|||
this.i = opts.i; |
|||
this.chaincode = opts.chaincode; |
|||
this.key = opts.key; |
|||
this.type = conv.bytesToString(this.vbytes) == PRIVDERIV ? 'priv' : 'pub' |
|||
return this; |
|||
} |
|||
|
|||
var PRIVDERIV = BIP32key.PRIVDERIV = '\x04\x88\xAD\xE4' |
|||
var PUBDERIV = BIP32key.PUBDERIV = '\x04\x88\xB2\x1E' |
|||
|
|||
BIP32key.prototype.deserialize = function(str) { |
|||
var bytes = base58.decode(str) |
|||
var front = bytes.slice(0,bytes.length-4), |
|||
back = bytes.slice(bytes.length-4); |
|||
var checksum = Crypto.SHA256(Crypto.SHA256(front,{asBytes: true}), {asBytes: true}) |
|||
.slice(0,4); |
|||
if (""+checksum != ""+back) { |
|||
throw new Error("Checksum failed"); |
|||
} |
|||
var type = conv.bytesToString(bytes.slice(0,4)) == PRIVDERIV ? 'priv' : 'pub'; |
|||
return new BIP32key({ |
|||
type: type, |
|||
vbytes: bytes.slice(0,4), |
|||
depth: bytes[4], |
|||
fingerprint: bytes.slice(5,9), |
|||
i: util.bytesToNum(bytes.slice(9,13).reverse()), |
|||
chaincode: bytes.slice(13,45), |
|||
key: new key(type == 'priv' ? bytes.slice(46,78).concat([1]) : bytes.slice(45,78)) |
|||
}) |
|||
} |
|||
|
|||
BIP32key.prototype.serialize = function() { |
|||
var bytes = this.vbytes.concat( |
|||
[this.depth], |
|||
this.fingerprint, |
|||
util.numToBytes(this.i,4).reverse(), |
|||
this.chaincode, |
|||
this.type == 'priv' ? [0].concat(this.key.export('bytes').slice(0,32)) |
|||
: this.key) |
|||
var checksum = Crypto.SHA256(Crypto.SHA256(bytes,{asBytes: true}), {asBytes: true}) |
|||
.slice(0,4) |
|||
return base58.encode(bytes.concat(checksum)) |
|||
} |
|||
|
|||
BIP32key.prototype.ckd = function(i) { |
|||
var priv, pub, newkey, fingerprint, blob, I; |
|||
if (this.type == 'priv') { |
|||
priv = this.key.export('bytes') |
|||
pub = this.key.getPub() |
|||
} |
|||
else pub = this.key |
|||
|
|||
if (i >= 2147483648) { |
|||
if (this.priv) throw new Error("Can't do private derivation on public key!") |
|||
blob = [0].concat(priv.slice(0,32),util.numToBytes(this.i,4).reverse()) |
|||
} |
|||
else blob = pub.concat(util.numToBytes(this.i,4).reverse()) |
|||
|
|||
I = Crypto.HMAC(Crypto.SHA512,blob,this.chaincode,{ asBytes: true }) |
|||
|
|||
if (this.type == 'priv') { |
|||
Ikey = Bitcoin.BigInteger.fromByteArrayUnsigned(I.slice(0,32)) |
|||
newkey = new key(this.key.priv.add(Ikey)) |
|||
newkey.compressed = true |
|||
fingerprint = util.sha256ripe160(this.key.getPub()).slice(0,4) |
|||
} |
|||
else { |
|||
newkey = ECPointFp.decodeFrom(ecparams.getCurve(),this.key) |
|||
.add(new key(I.slice(0,32).concat([1])).getPubPoint()) |
|||
.getEncoded(true); |
|||
fingerprint = util.sha256ripe160(this.key).slice(0,4) |
|||
} |
|||
return new BIP32key({ |
|||
vbytes: this.vbytes, |
|||
type: this.type, |
|||
depth: this.depth + 1, |
|||
fingerprint: fingerprint, |
|||
i: i, |
|||
chaincode: I.slice(32), |
|||
key: newkey |
|||
}) |
|||
} |
|||
|
|||
BIP32key.prototype.clone = function() { |
|||
return new BIP32key(this); |
|||
} |
|||
|
|||
BIP32key.prototype.privtopub = BIP32key.prototype.getPub = function() { |
|||
if (this.type == 'pub') return this.clone() |
|||
return new BIP32key({ |
|||
vbytes: conv.stringToBytes(PUBDERIV), |
|||
type: 'pub', |
|||
depth: this.depth, |
|||
fingerprint: this.fingerprint, |
|||
i: this.i, |
|||
chaincode: this.chaincode, |
|||
key: this.key.getPub() |
|||
}) |
|||
} |
|||
|
|||
BIP32key.prototype.fromMasterKey = function(seed) { |
|||
var I = Bitcoin.Crypto.HMAC(Bitcoin.Crypto.SHA512,seed,"Bitcoin seed",{ asBytes: true }) |
|||
return new BIP32key({ |
|||
vbytes: conv.stringToBytes(PRIVDERIV), |
|||
type: 'priv', |
|||
depth: 0, |
|||
fingerprint: [0,0,0,0], |
|||
i: 0, |
|||
chaincode: I.slice(32), |
|||
key: new key(I.slice(0,32).concat([1])) |
|||
}) |
|||
} |
|||
|
|||
BIP32key.prototype.getKey = function() { return this.key } |
|||
|
|||
module.exports = BIP32key; |
@ -1,165 +0,0 @@ |
|||
/* |
|||
function makeKeypair() |
|||
{ |
|||
// Generate private key
|
|||
var n = ecparams.getN(); |
|||
var n1 = n.subtract(BigInteger.ONE); |
|||
var r = new BigInteger(n.bitLength(), rng); |
|||
|
|||
var privateKey = r.mod(n1).add(BigInteger.ONE); |
|||
|
|||
// Generate public key
|
|||
var G = ecparams.getG(); |
|||
var publicPoint = G.multiply(privateKey); |
|||
|
|||
return {priv: privateKey, pubkey: publicPoint}; |
|||
}; |
|||
|
|||
function serializeTransaction(tx) |
|||
{ |
|||
var buffer = []; |
|||
buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(tx.version)])); |
|||
buffer = buffer.concat(numToVarInt(tx.ins.length)); |
|||
for (var i = 0; i < tx.ins.length; i++) { |
|||
var txin = tx.ins[i]; |
|||
buffer = buffer.concat(Crypto.util.hexToBytes(txin.outpoint.hash)); |
|||
buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.index)])); |
|||
var scriptBytes = Crypto.util.hexToBytes(txin.script); |
|||
buffer = buffer.concat(numToVarInt(scriptBytes.length)); |
|||
buffer = buffer.concat(scriptBytes); |
|||
buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.sequence)])); |
|||
} |
|||
buffer = buffer.concat(numToVarInt(tx.outs.length)); |
|||
for (var i = 0; i < tx.outs.length; i++) { |
|||
var txout = tx.outs[i]; |
|||
var valueHex = txout.value.toString(16); |
|||
while (valueHex.length < 16) valueHex = "0" + valueHex; |
|||
buffer = buffer.concat(Crypto.util.hexToBytes(valueHex)); |
|||
var scriptBytes = Crypto.util.hexToBytes(txout.script); |
|||
buffer = buffer.concat(numToVarInt(scriptBytes.length)); |
|||
buffer = buffer.concat(scriptBytes); |
|||
} |
|||
buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(tx.lock_time)])); |
|||
|
|||
return buffer; |
|||
}; |
|||
|
|||
var OP_CODESEPARATOR = 171; |
|||
|
|||
var SIGHASH_ALL = 1; |
|||
var SIGHASH_NONE = 2; |
|||
var SIGHASH_SINGLE = 3; |
|||
var SIGHASH_ANYONECANPAY = 80; |
|||
|
|||
function hashTransactionForSignature(scriptCode, tx, inIndex, hashType) |
|||
{ |
|||
// TODO: We need to actually deep copy here
|
|||
var txTmp = tx; |
|||
|
|||
// In case concatenating two scripts ends up with two codeseparators,
|
|||
// or an extra one at the end, this prevents all those possible incompatibilities.
|
|||
scriptCode = scriptCode.filter(function (val) { |
|||
return val !== OP_CODESEPARATOR; |
|||
}); |
|||
|
|||
// Blank out other inputs' signatures
|
|||
for (var i = 0; i < txTmp.ins.length; i++) { |
|||
txTmp.ins[i].script = Crypto.util.bytesToHex([]); |
|||
} |
|||
txTmp.ins[inIndex].script = Crypto.util.bytesToHex(scriptCode); |
|||
|
|||
// Blank out some of the outputs
|
|||
if ((hashType & 0x1f) == SIGHASH_NONE) { |
|||
txTmp.outs = []; |
|||
|
|||
// Let the others update at will
|
|||
for (var i = 0; i < txTmp.ins.length; i++) |
|||
if (i != inIndex) |
|||
txTmp.ins[i].sequence = 0; |
|||
} else if ((hashType & 0x1f) == SIGHASH_SINGLE) { |
|||
// TODO: Implement
|
|||
} |
|||
|
|||
// Blank out other inputs completely, not recommended for open transactions
|
|||
if (hashType & SIGHASH_ANYONECANPAY) { |
|||
txTmp.ins = [txTmp.ins[inIndex]]; |
|||
} |
|||
|
|||
var buffer = serializeTransaction(txTmp); |
|||
|
|||
buffer.concat(Crypto.util.wordsToBytes([parseInt(hashType)])); |
|||
|
|||
console.log(buffer); |
|||
|
|||
return Crypto.SHA256(Crypto.SHA256(buffer, {asBytes: true}), {asBytes: true}); |
|||
}; |
|||
|
|||
function verifyTransactionSignature(tx) { |
|||
var hash = hashTransactionForSignature([], tx, 0, 0); |
|||
return Crypto.util.bytesToHex(hash); |
|||
}; |
|||
|
|||
function numToVarInt(i) |
|||
{ |
|||
// TODO: THIS IS TOTALLY UNTESTED!
|
|||
if (i < 0xfd) { |
|||
// unsigned char
|
|||
return [i]; |
|||
} else if (i <= 1<<16) { |
|||
// unsigned short (LE)
|
|||
return [0xfd, i >>> 8, i & 255]; |
|||
} else if (i <= 1<<32) { |
|||
// unsigned int (LE)
|
|||
return [0xfe].concat(Crypto.util.wordsToBytes([i])); |
|||
} else { |
|||
// unsigned long long (LE)
|
|||
return [0xff].concat(Crypto.util.wordsToBytes([i >>> 32, i])); |
|||
} |
|||
}; |
|||
|
|||
var testTx = { |
|||
"version":"1", |
|||
"lock_time":"0", |
|||
"block": { |
|||
"hash":"N/A", |
|||
"height":115806 |
|||
}, |
|||
"index":6, |
|||
"hash":"WUFzjKubG1kqfJWMb4qZdlhU2F3l5NGXN7AUg8Jwl14=", |
|||
"ins":[{ |
|||
"outpoint":{ |
|||
"hash":"nqcbMM1oRhfLdZga11q7x0CpUMujm+vtxHXO9V0gnwE=", |
|||
"index":0 |
|||
}, |
|||
"script":"RzBEAiB2XXkx1pca9SlfCmCGNUVf+h2sAFBttcxG1VnypIcvEgIgXrOp7LSdYBYp3nPsQAz8BOLD3K4pAlXfZImP1rkzk2EBQQRi7NcODzNfnVqLtG79Axp5UF6EhFIhCmzqKqssfKpfCIOmzCuXEeDFUFvFzeGLJx5N+wp2qRS1TqYezGD3yERk", |
|||
"sequence":4294967295 |
|||
}], |
|||
"outs":[{ |
|||
"value":"3000000000", |
|||
"script":"dqkUBLZwqhAPRVgZvwI8MN5gLHbU8NOIrA==" |
|||
},{ |
|||
"value":"25937000000", |
|||
"script":"dqkUQ82gJ0O5vOBg6yK5/yorLLV5zLKIrA==" |
|||
}] |
|||
}; |
|||
|
|||
TODO: Make this stuff into test cases ;) |
|||
$(function () { |
|||
var key = new Bitcoin.ECKey(Crypto.util.hexToBytes("5c0b98e524ad188ddef35dc6abba13c34a351a05409e5d285403718b93336a4a")); |
|||
key = new Bitcoin.ECKey(Crypto.util.hexToBytes("180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19")); |
|||
//console.log(key.getBitcoinAddress().toString());
|
|||
//var message = Crypto.util.hexToBytes("2aec28d323ee7b06a799d540d224b351161fe48967174ca5e43164e86137da11");
|
|||
//message = [0];
|
|||
//var out = key.sign(message);
|
|||
//console.log("pubkey: "+Crypto.util.bytesToHex(key.getPub()));
|
|||
//console.log("sig: "+Crypto.util.bytesToHex(out));
|
|||
|
|||
//console.log(key.verify(message, out));
|
|||
|
|||
//console.log(Bitcoin.ECDSA.verify(message, Crypto.util.hexToBytes("3046022100dffbc26774fc841bbe1c1362fd643609c6e42dcb274763476d87af2c0597e89e022100c59e3c13b96b316cae9fa0ab0260612c7a133a6fe2b3445b6bf80b3123bf274d"), Crypto.util.hexToBytes("0401de173aa944eacf7e44e5073baca93fb34fe4b7897a1c82c92dfdc8a1f75ef58cd1b06e8052096980cb6e1ad6d3df143c34b3d7394bae2782a4df570554c2fb")));
|
|||
|
|||
//console.log(Bitcoin.ECDSA.verify(Crypto.util.hexToBytes("230aba77ccde46bb17fcb0295a92c0cc42a6ea9f439aaadeb0094625f49e6ed8"), Crypto.util.hexToBytes("3046022100a3ee5408f0003d8ef00ff2e0537f54ba09771626ff70dca1f01296b05c510e85022100d4dc70a5bb50685b65833a97e536909a6951dd247a2fdbde6688c33ba6d6407501"),Crypto.util.hexToBytes("04a19c1f07c7a0868d86dbb37510305843cc730eb3bea8a99d92131f44950cecd923788419bfef2f635fad621d753f30d4b4b63b29da44b4f3d92db974537ad5a4")));
|
|||
//console.log(Bitcoin.ECDSA.verify(Crypto.util.hexToBytes("c2c75bb77d7a5acddceb1d45ceef58e7451fd0d3abc9d4c16df7848eefafe00d"), Crypto.util.hexToBytes("3045022100ff9362dadcbf1f6ef954bc8eb27144bbb4f49abd32be1eb04c311151dcf4bcf802205112c2ca6a25aefb8be98bf460c5a9056c01253f31e118d80b81ec9604e3201a01"),Crypto.util.hexToBytes("04fe62ce7892ec209310c176ef7f06565865e286e8699e884603657efa9aa51086785099d544d4e04f1f7b4b065205c1783fade8daf4ba1e0d1962292e8eb722cd")));
|
|||
}); |
|||
//
|
|||
*/ |
@ -0,0 +1,38 @@ |
|||
/*! |
|||
* Crypto-JS v2.0.0 |
|||
* http://code.google.com/p/crypto-js/
|
|||
* Copyright (c) 2009, Jeff Mott. All rights reserved. |
|||
* http://code.google.com/p/crypto-js/wiki/License
|
|||
*/ |
|||
|
|||
var conv = require('../convert'), |
|||
util = require('../util'); |
|||
|
|||
// Shortcuts
|
|||
|
|||
module.exports = function (hasher, message, key, options) { |
|||
|
|||
// Convert to byte arrays
|
|||
if (message.constructor == String) message = conv.stringToBytes(message); |
|||
if (key.constructor == String) key = conv.stringToBytes(key); |
|||
/* else, assume byte arrays already */ |
|||
|
|||
// Allow arbitrary length keys
|
|||
if (key.length > hasher._blocksize) |
|||
key = hasher(key, { asBytes: true }); |
|||
|
|||
// XOR keys with pad constants
|
|||
var okey = key.slice(0), |
|||
ikey = key.slice(0); |
|||
for (var i = 0; i < hasher._blocksize; i++) { |
|||
okey[i] ^= 0x5C; |
|||
ikey[i] ^= 0x36; |
|||
} |
|||
|
|||
var hmacbytes = hasher(okey.concat(hasher(ikey.concat(message), { asBytes: true })), { asBytes: true }); |
|||
|
|||
return options && options.asBytes ? hmacbytes : |
|||
options && options.asString ? conv.bytesToString(hmacbytes) : |
|||
conv.bytesToHex(hmacbytes); |
|||
|
|||
}; |
@ -0,0 +1,240 @@ |
|||
|
|||
var conv = require('../convert'); |
|||
var util = require('../util'); |
|||
|
|||
var K = [ |
|||
[0x428a2f98, 0xd728ae22], [0x71374491, 0x23ef65cd], |
|||
[0xb5c0fbcf, 0xec4d3b2f], [0xe9b5dba5, 0x8189dbbc], |
|||
[0x3956c25b, 0xf348b538], [0x59f111f1, 0xb605d019], |
|||
[0x923f82a4, 0xaf194f9b], [0xab1c5ed5, 0xda6d8118], |
|||
[0xd807aa98, 0xa3030242], [0x12835b01, 0x45706fbe], |
|||
[0x243185be, 0x4ee4b28c], [0x550c7dc3, 0xd5ffb4e2], |
|||
[0x72be5d74, 0xf27b896f], [0x80deb1fe, 0x3b1696b1], |
|||
[0x9bdc06a7, 0x25c71235], [0xc19bf174, 0xcf692694], |
|||
[0xe49b69c1, 0x9ef14ad2], [0xefbe4786, 0x384f25e3], |
|||
[0x0fc19dc6, 0x8b8cd5b5], [0x240ca1cc, 0x77ac9c65], |
|||
[0x2de92c6f, 0x592b0275], [0x4a7484aa, 0x6ea6e483], |
|||
[0x5cb0a9dc, 0xbd41fbd4], [0x76f988da, 0x831153b5], |
|||
[0x983e5152, 0xee66dfab], [0xa831c66d, 0x2db43210], |
|||
[0xb00327c8, 0x98fb213f], [0xbf597fc7, 0xbeef0ee4], |
|||
[0xc6e00bf3, 0x3da88fc2], [0xd5a79147, 0x930aa725], |
|||
[0x06ca6351, 0xe003826f], [0x14292967, 0x0a0e6e70], |
|||
[0x27b70a85, 0x46d22ffc], [0x2e1b2138, 0x5c26c926], |
|||
[0x4d2c6dfc, 0x5ac42aed], [0x53380d13, 0x9d95b3df], |
|||
[0x650a7354, 0x8baf63de], [0x766a0abb, 0x3c77b2a8], |
|||
[0x81c2c92e, 0x47edaee6], [0x92722c85, 0x1482353b], |
|||
[0xa2bfe8a1, 0x4cf10364], [0xa81a664b, 0xbc423001], |
|||
[0xc24b8b70, 0xd0f89791], [0xc76c51a3, 0x0654be30], |
|||
[0xd192e819, 0xd6ef5218], [0xd6990624, 0x5565a910], |
|||
[0xf40e3585, 0x5771202a], [0x106aa070, 0x32bbd1b8], |
|||
[0x19a4c116, 0xb8d2d0c8], [0x1e376c08, 0x5141ab53], |
|||
[0x2748774c, 0xdf8eeb99], [0x34b0bcb5, 0xe19b48a8], |
|||
[0x391c0cb3, 0xc5c95a63], [0x4ed8aa4a, 0xe3418acb], |
|||
[0x5b9cca4f, 0x7763e373], [0x682e6ff3, 0xd6b2b8a3], |
|||
[0x748f82ee, 0x5defb2fc], [0x78a5636f, 0x43172f60], |
|||
[0x84c87814, 0xa1f0ab72], [0x8cc70208, 0x1a6439ec], |
|||
[0x90befffa, 0x23631e28], [0xa4506ceb, 0xde82bde9], |
|||
[0xbef9a3f7, 0xb2c67915], [0xc67178f2, 0xe372532b], |
|||
[0xca273ece, 0xea26619c], [0xd186b8c7, 0x21c0c207], |
|||
[0xeada7dd6, 0xcde0eb1e], [0xf57d4f7f, 0xee6ed178], |
|||
[0x06f067aa, 0x72176fba], [0x0a637dc5, 0xa2c898a6], |
|||
[0x113f9804, 0xbef90dae], [0x1b710b35, 0x131c471b], |
|||
[0x28db77f5, 0x23047d84], [0x32caab7b, 0x40c72493], |
|||
[0x3c9ebe0a, 0x15c9bebc], [0x431d67c4, 0x9c100d4c], |
|||
[0x4cc5d4be, 0xcb3e42b6], [0x597f299c, 0xfc657e2a], |
|||
[0x5fcb6fab, 0x3ad6faec], [0x6c44198c, 0x4a475817] |
|||
]; |
|||
// Reusable objects
|
|||
var W = []; |
|||
for (var i = 0; i < 80; i++) W.push([0,0]) |
|||
|
|||
/** |
|||
* SHA-512 hash algorithm. |
|||
*/ |
|||
var processBlock = function (H, M, offset) { |
|||
// Shortcuts
|
|||
var H0 = H[0]; |
|||
var H1 = H[1]; |
|||
var H2 = H[2]; |
|||
var H3 = H[3]; |
|||
var H4 = H[4]; |
|||
var H5 = H[5]; |
|||
var H6 = H[6]; |
|||
var H7 = H[7]; |
|||
|
|||
var H0h = H0[0]; |
|||
var H0l = H0[1]; |
|||
var H1h = H1[0]; |
|||
var H1l = H1[1]; |
|||
var H2h = H2[0]; |
|||
var H2l = H2[1]; |
|||
var H3h = H3[0]; |
|||
var H3l = H3[1]; |
|||
var H4h = H4[0]; |
|||
var H4l = H4[1]; |
|||
var H5h = H5[0]; |
|||
var H5l = H5[1]; |
|||
var H6h = H6[0]; |
|||
var H6l = H6[1]; |
|||
var H7h = H7[0]; |
|||
var H7l = H7[1]; |
|||
|
|||
// Working variables
|
|||
var ah = H0h; |
|||
var al = H0l; |
|||
var bh = H1h; |
|||
var bl = H1l; |
|||
var ch = H2h; |
|||
var cl = H2l; |
|||
var dh = H3h; |
|||
var dl = H3l; |
|||
var eh = H4h; |
|||
var el = H4l; |
|||
var fh = H5h; |
|||
var fl = H5l; |
|||
var gh = H6h; |
|||
var gl = H6l; |
|||
var hh = H7h; |
|||
var hl = H7l; |
|||
|
|||
// Rounds
|
|||
for (var i = 0; i < 80; i++) { |
|||
// Shortcut
|
|||
var Wi = W[i]; |
|||
|
|||
// Extend message
|
|||
if (i < 16) { |
|||
var Wih = Wi[0] = M[offset + i * 2] | 0; |
|||
var Wil = Wi[1] = M[offset + i * 2 + 1] | 0; |
|||
} else { |
|||
// Gamma0
|
|||
var gamma0x = W[i - 15]; |
|||
var gamma0xh = gamma0x[0]; |
|||
var gamma0xl = gamma0x[1]; |
|||
var gamma0h = ((gamma0xh >>> 1) | (gamma0xl << 31)) ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) ^ (gamma0xh >>> 7); |
|||
var gamma0l = ((gamma0xl >>> 1) | (gamma0xh << 31)) ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) ^ ((gamma0xl >>> 7) | (gamma0xh << 25)); |
|||
|
|||
// Gamma1
|
|||
var gamma1x = W[i - 2]; |
|||
var gamma1xh = gamma1x[0]; |
|||
var gamma1xl = gamma1x[1]; |
|||
var gamma1h = ((gamma1xh >>> 19) | (gamma1xl << 13)) ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) ^ (gamma1xh >>> 6); |
|||
var gamma1l = ((gamma1xl >>> 19) | (gamma1xh << 13)) ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) ^ ((gamma1xl >>> 6) | (gamma1xh << 26)); |
|||
|
|||
// W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]
|
|||
var Wi7 = W[i - 7]; |
|||
var Wi7h = Wi7[0]; |
|||
var Wi7l = Wi7[1]; |
|||
|
|||
var Wi16 = W[i - 16]; |
|||
var Wi16h = Wi16[0]; |
|||
var Wi16l = Wi16[1]; |
|||
|
|||
var Wil = gamma0l + Wi7l; |
|||
var Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0); |
|||
var Wil = Wil + gamma1l; |
|||
var Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0); |
|||
var Wil = Wil + Wi16l; |
|||
var Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0); |
|||
|
|||
Wi[0] = Wih; |
|||
Wi[1] = Wil; |
|||
} |
|||
|
|||
var chh = (eh & fh) ^ (~eh & gh); |
|||
var chl = (el & fl) ^ (~el & gl); |
|||
var majh = (ah & bh) ^ (ah & ch) ^ (bh & ch); |
|||
var majl = (al & bl) ^ (al & cl) ^ (bl & cl); |
|||
|
|||
var sigma0h = ((ah >>> 28) | (al << 4)) ^ ((ah << 30) | (al >>> 2)) ^ ((ah << 25) | (al >>> 7)); |
|||
var sigma0l = ((al >>> 28) | (ah << 4)) ^ ((al << 30) | (ah >>> 2)) ^ ((al << 25) | (ah >>> 7)); |
|||
var sigma1h = ((eh >>> 14) | (el << 18)) ^ ((eh >>> 18) | (el << 14)) ^ ((eh << 23) | (el >>> 9)); |
|||
var sigma1l = ((el >>> 14) | (eh << 18)) ^ ((el >>> 18) | (eh << 14)) ^ ((el << 23) | (eh >>> 9)); |
|||
|
|||
// t1 = h + sigma1 + ch + K[i] + W[i]
|
|||
var Ki = K[i]; |
|||
var Kih = Ki[0]; |
|||
var Kil = Ki[1]; |
|||
|
|||
var t1l = hl + sigma1l; |
|||
var t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0); |
|||
var t1l = t1l + chl; |
|||
var t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0); |
|||
var t1l = t1l + Kil; |
|||
var t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0); |
|||
var t1l = t1l + Wil; |
|||
var t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0); |
|||
|
|||
// t2 = sigma0 + maj
|
|||
var t2l = sigma0l + majl; |
|||
var t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0); |
|||
|
|||
// Update working variables
|
|||
hh = gh; |
|||
hl = gl; |
|||
gh = fh; |
|||
gl = fl; |
|||
fh = eh; |
|||
fl = el; |
|||
el = (dl + t1l) | 0; |
|||
eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0; |
|||
dh = ch; |
|||
dl = cl; |
|||
ch = bh; |
|||
cl = bl; |
|||
bh = ah; |
|||
bl = al; |
|||
al = (t1l + t2l) | 0; |
|||
ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0; |
|||
} |
|||
|
|||
// Intermediate hash value
|
|||
H0l = H0[1] = (H0l + al); |
|||
H0[0] = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0)); |
|||
H1l = H1[1] = (H1l + bl); |
|||
H1[0] = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0)); |
|||
H2l = H2[1] = (H2l + cl); |
|||
H2[0] = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0)); |
|||
H3l = H3[1] = (H3l + dl); |
|||
H3[0] = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0)); |
|||
H4l = H4[1] = (H4l + el); |
|||
H4[0] = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0)); |
|||
H5l = H5[1] = (H5l + fl); |
|||
H5[0] = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0)); |
|||
H6l = H6[1] = (H6l + gl); |
|||
H6[0] = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0)); |
|||
H7l = H7[1] = (H7l + hl); |
|||
H7[0] = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0)); |
|||
return H |
|||
} |
|||
|
|||
module.exports = function(message, options) {; |
|||
|
|||
var H = [ |
|||
[0x6a09e667, 0xf3bcc908], [0xbb67ae85, 0x84caa73b], |
|||
[0x3c6ef372, 0xfe94f82b], [0xa54ff53a, 0x5f1d36f1], |
|||
[0x510e527f, 0xade682d1], [0x9b05688c, 0x2b3e6c1f], |
|||
[0x1f83d9ab, 0xfb41bd6b], [0x5be0cd19, 0x137e2179] |
|||
]; |
|||
|
|||
if (message.constructor === String) { |
|||
message = conv.stringToBytes(message); |
|||
} |
|||
|
|||
var m = util.bytesToWords(message); |
|||
var l = message.length * 8; |
|||
|
|||
m[l >> 5] |= 0x80 << (24 - l % 32); |
|||
m[((l + 64 >> 10) << 5) + 31] = l; |
|||
|
|||
for (var i=0 ; i<m.length; i += 32) { |
|||
processBlock(H, m, i); |
|||
} |
|||
|
|||
var digestbytes = util.wordsToBytes(Array.prototype.concat.apply([],H)) |
|||
return options && options.asBytes ? digestbytes : |
|||
options && options.asString ? Binary.bytesToString(digestbytes) : |
|||
conv.bytesToHex(digestbytes); |
|||
}; |
|||
|
|||
module.exports._blocksize = 128 |
Loading…
Reference in new issue