Kyle Drake
11 years ago
50 changed files with 4561 additions and 5454 deletions
@ -0,0 +1,6 @@ |
|||
language: node_js |
|||
node_js: |
|||
- "0.11" |
|||
- "0.10" |
|||
- "0.8" |
|||
- "0.6" |
@ -1,53 +0,0 @@ |
|||
var pkginfo = require('pkginfo')(module); |
|||
var minify = require('jake-uglify').minify; |
|||
|
|||
var headerJS = "\ |
|||
/**\n\ |
|||
* BitcoinJS-lib v"+exports.version+"-default\n\ |
|||
* Copyright (c) 2011 BitcoinJS Project\n\ |
|||
* \n\ |
|||
* This program is free software; you can redistribute it and/or modify\n\ |
|||
* it under the terms of the MIT license.\n\ |
|||
*/"; |
|||
|
|||
task({'default': [ |
|||
'build/bitcoinjs-min.js', |
|||
'build/bitcoinjs-exit-min.js' |
|||
]}); |
|||
|
|||
desc('General-purpose build containing most features'); |
|||
minify({'build/bitcoinjs-min.js': [ |
|||
'src/crypto-js/crypto.js', |
|||
'src/crypto-js/sha256.js', |
|||
'src/crypto-js/ripemd160.js', |
|||
'src/jsbn/prng4.js', |
|||
'src/jsbn/rng.js', |
|||
'src/jsbn/jsbn.js', |
|||
'src/jsbn/jsbn2.js', |
|||
|
|||
'src/jsbn/ec.js', |
|||
'src/jsbn/sec.js', |
|||
'src/events/eventemitter.js', |
|||
'src/bitcoin.js', |
|||
'src/util.js', |
|||
'src/base58.js', |
|||
|
|||
'src/address.js', |
|||
'src/ecdsa.js', |
|||
'src/eckey.js', |
|||
'src/opcode.js', |
|||
'src/script.js', |
|||
'src/transaction.js', |
|||
|
|||
'src/wallet.js', |
|||
'src/txdb.js' |
|||
]}, { |
|||
header: headerJS |
|||
}); |
|||
|
|||
desc('Exit node client implementation'); |
|||
minify({'build/bitcoinjs-exit-min.js': [ |
|||
'src/exit/client.js' |
|||
]}, { |
|||
header: headerJS |
|||
}); |
File diff suppressed because one or more lines are too long
@ -1,8 +0,0 @@ |
|||
/** |
|||
* BitcoinJS-lib v0.1.0-default |
|||
* Copyright (c) 2011 BitcoinJS Project |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the MIT license. |
|||
*/ |
|||
(function(a,b,c,d,e){function f(a,b,c){this.setUri(a,b,c),this.unique=1,this.connected=!1,this.callbacks=[]}a.ExitNode=f,b.EventEmitter.augment(f),f.prototype.setUri=function(a,b,c){this.uri=(c?"https://":"http://")+a+":"+b},f.prototype.connect=function(a){this.wallet=a,delete c.sockets[this.uri],c.j=[],this.socket=c.connect(this.uri),this.socket.on("connect",d.proxy(this.handleConnect,this)),this.socket.on("error",function(){console.log("error, test")}),this.socket.on("message",d.proxy(this.handleMessage,this)),this.socket.on("disconnect",d.proxy(this.handleDisconnect,this))},f.prototype.disconnect=function(){this.socket&&(this.socket.disconnect(),this.socket=null,this.connected=!1),this.trigger("connectStatus",{status:"unknown"})},f.prototype.call=function(a,b,c){this.socket.send(d.toJSON({method:a,params:[b],id:this.unique})),c&&(this.callbacks[this.unique]=c),this.unique++},f.prototype.handleConnect=function(){var a=this;this.connected=!0},f.prototype.listen=function(a){self.call("pubkeysRegister",{keys:a.join(",")},function(a,b){if(a){console.error("Could not register public keys");return}self.call("pubkeysListen",{handle:b.handle},function(a,b){self.trigger("blockInit",{height:b.height}),self.trigger("txData",{confirmed:!0,txs:b.txs}),self.trigger("connectStatus",{status:"ok"})}),self.call("pubkeysUnconfirmed",{handle:b.handle},function(a,b){self.trigger("txData",{confirmed:!1,txs:b.txs})})})},f.prototype.handleMessage=function(a){"undefined"!=typeof a.result&&"function"==typeof this.callbacks[a.id]?this.callbacks[a.id](a.error,a.result):"undefined"!=typeof a.method&&this.trigger(a.method,a.params[0])},f.prototype.handleDisconnect=function(){},f.prototype.query=function(a,b,c,e){"function"==typeof c&&(e=c,c=!1),b=b||{},e="function"==typeof e?e:function(){};var f=this.uri+"/"+a;c&&(f+="?callback=?"),d.getJSON(f,b,e)}})("undefined"!=typeof Bitcoin?Bitcoin:module.exports,"undefined"!=typeof Bitcoin?Bitcoin:require("bitcoinjs-lib"),"undefined"!=typeof io?io:require("io"),jQuery,this) |
File diff suppressed because one or more lines are too long
@ -1,71 +1,119 @@ |
|||
(function (Bitcoin) { |
|||
Bitcoin.Base58 = { |
|||
alphabet: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz", |
|||
validRegex: /^[1-9A-HJ-NP-Za-km-z]+$/, |
|||
base: BigInteger.valueOf(58), |
|||
|
|||
/** |
|||
* Convert a byte array to a base58-encoded string. |
|||
* |
|||
* Written by Mike Hearn for BitcoinJ. |
|||
* Copyright (c) 2011 Google Inc. |
|||
* |
|||
* Ported to JavaScript by Stefan Thomas. |
|||
*/ |
|||
encode: function (input) { |
|||
|
|||
// https://en.bitcoin.it/wiki/Base58Check_encoding
|
|||
|
|||
var BigInteger = require('./jsbn/jsbn'); |
|||
var Crypto = require('./crypto-js/crypto'); |
|||
var conv = require('./convert'); |
|||
|
|||
var alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; |
|||
var base = BigInteger.valueOf(58); |
|||
|
|||
var positions = {}; |
|||
for (var i=0 ; i < alphabet.length ; ++i) { |
|||
positions[alphabet[i]] = i; |
|||
} |
|||
|
|||
// Convert a byte array to a base58-encoded string.
|
|||
// Written by Mike Hearn for BitcoinJ.
|
|||
// Copyright (c) 2011 Google Inc.
|
|||
// Ported to JavaScript by Stefan Thomas.
|
|||
module.exports.encode = function (input) { |
|||
var bi = BigInteger.fromByteArrayUnsigned(input); |
|||
var chars = []; |
|||
|
|||
while (bi.compareTo(B58.base) >= 0) { |
|||
var mod = bi.mod(B58.base); |
|||
chars.unshift(B58.alphabet[mod.intValue()]); |
|||
bi = bi.subtract(mod).divide(B58.base); |
|||
while (bi.compareTo(base) >= 0) { |
|||
var mod = bi.mod(base); |
|||
chars.push(alphabet[mod.intValue()]); |
|||
bi = bi.subtract(mod).divide(base); |
|||
} |
|||
chars.unshift(B58.alphabet[bi.intValue()]); |
|||
chars.push(alphabet[bi.intValue()]); |
|||
|
|||
// Convert leading zeros too.
|
|||
for (var i = 0; i < input.length; i++) { |
|||
if (input[i] == 0x00) { |
|||
chars.unshift(B58.alphabet[0]); |
|||
chars.push(alphabet[0]); |
|||
} else break; |
|||
} |
|||
|
|||
return chars.join(''); |
|||
return chars.reverse().join(''); |
|||
}, |
|||
|
|||
/** |
|||
* Convert a base58-encoded string to a byte array. |
|||
* |
|||
* Written by Mike Hearn for BitcoinJ. |
|||
* Copyright (c) 2011 Google Inc. |
|||
* |
|||
* Ported to JavaScript by Stefan Thomas. |
|||
*/ |
|||
decode: function (input) { |
|||
var bi = BigInteger.valueOf(0); |
|||
var leadingZerosNum = 0; |
|||
for (var i = input.length - 1; i >= 0; i--) { |
|||
var alphaIndex = B58.alphabet.indexOf(input[i]); |
|||
if (alphaIndex < 0) { |
|||
throw "Invalid character"; |
|||
} |
|||
bi = bi.add(BigInteger.valueOf(alphaIndex) |
|||
.multiply(B58.base.pow(input.length - 1 -i))); |
|||
|
|||
// This counts leading zero bytes
|
|||
if (input[i] == "1") leadingZerosNum++; |
|||
else leadingZerosNum = 0; |
|||
} |
|||
var bytes = bi.toByteArrayUnsigned(); |
|||
|
|||
// Add leading zeros
|
|||
while (leadingZerosNum-- > 0) bytes.unshift(0); |
|||
module.exports.encodeHex = function (input) { |
|||
return conv.bytesToHex(module.exports.encode(input)); |
|||
} |
|||
|
|||
// decode a base58 string into a byte array
|
|||
// input should be a base58 encoded string
|
|||
// @return Array
|
|||
module.exports.decode = function (input) { |
|||
|
|||
var base = BigInteger.valueOf(58); |
|||
|
|||
var length = input.length; |
|||
var num = BigInteger.valueOf(0); |
|||
var leading_zero = 0; |
|||
var seen_other = false; |
|||
for (var i=0; i<length ; ++i) { |
|||
var chr = input[i]; |
|||
var p = positions[chr]; |
|||
|
|||
// if we encounter an invalid character, decoding fails
|
|||
if (p === undefined) { |
|||
throw new Error('invalid base58 string: ' + input); |
|||
} |
|||
|
|||
num = num.multiply(base).add(BigInteger.valueOf(p)); |
|||
|
|||
if (chr == '1' && !seen_other) { |
|||
++leading_zero; |
|||
} |
|||
else { |
|||
seen_other = true; |
|||
} |
|||
} |
|||
|
|||
var bytes = num.toByteArrayUnsigned(); |
|||
|
|||
// remove leading zeros
|
|||
while (leading_zero-- > 0) { |
|||
bytes.unshift(0); |
|||
} |
|||
|
|||
return bytes; |
|||
} |
|||
}; |
|||
|
|||
var B58 = Bitcoin.Base58; |
|||
})( |
|||
'undefined' != typeof Bitcoin ? Bitcoin : module.exports |
|||
); |
|||
module.exports.decodeHex = function (input) { |
|||
return module.exports.decode(conv.hexToBytes(input)); |
|||
} |
|||
|
|||
module.exports.checkEncode = function(input, vbyte) { |
|||
vbyte = vbyte || 0; |
|||
var front = [vbyte].concat(input); |
|||
var checksum = Crypto.SHA256(Crypto.SHA256(front, {asBytes: true}), {asBytes: true}) |
|||
.slice(0,4); |
|||
return module.exports.encode(front.concat(checksum)); |
|||
} |
|||
|
|||
module.exports.checkEncodeHex = function (input, vbyte) { |
|||
return conv.bytesToHex(module.exports.encode(input)); |
|||
} |
|||
|
|||
module.exports.checkDecode = function(input) { |
|||
var bytes = module.exports.decode(input), |
|||
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 o = front.slice(1); |
|||
o.version = front[0]; |
|||
return o; |
|||
} |
|||
|
|||
module.exports.checkDecodeHex = function (input) { |
|||
return module.exports.checkDecode(conv.hexToBytes(input)); |
|||
} |
|||
|
|||
|
|||
|
@ -1,175 +0,0 @@ |
|||
(function (exports) { |
|||
var Bitcoin = exports; |
|||
|
|||
if ('object' !== typeof module) { |
|||
Bitcoin.EventEmitter = EventEmitter; |
|||
} |
|||
})( |
|||
'object' === typeof module ? module.exports : (window.Bitcoin = {}) |
|||
); |
|||
|
|||
/* |
|||
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.base64ToBytes(txin.outpoint.hash)); |
|||
buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.index)])); |
|||
var scriptBytes = Crypto.util.base64ToBytes(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 = (new BigInteger(txout.value, 10)).toString(16); |
|||
while (valueHex.length < 16) valueHex = "0" + valueHex; |
|||
buffer = buffer.concat(Crypto.util.hexToBytes(valueHex)); |
|||
var scriptBytes = Crypto.util.base64ToBytes(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.bytesToBase64([]); |
|||
} |
|||
txTmp.ins[inIndex].script = Crypto.util.bytesToBase64(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,74 @@ |
|||
// convert to/from various values
|
|||
|
|||
var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
|||
|
|||
String.prototype.lpad = function(padString, length) { |
|||
var str = this; |
|||
while (str.length < length) str = padString + str; |
|||
return str; |
|||
} |
|||
|
|||
// Convert a byte array to a hex string
|
|||
module.exports.bytesToHex = function(bytes) { |
|||
return bytes.map(function(x) { return x.toString(16).lpad('0',2) }).join(''); |
|||
}; |
|||
|
|||
// Convert a hex string to a byte array
|
|||
module.exports.hexToBytes = function(hex) { |
|||
return hex.match(/../g).map(function(x) { return parseInt(x,16) }); |
|||
} |
|||
|
|||
// Convert a byte array to a base-64 string
|
|||
module.exports.bytesToBase64 = function(bytes) { |
|||
|
|||
for(var base64 = [], i = 0; i < bytes.length; i += 3) { |
|||
var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; |
|||
for (var j = 0; j < 4; j++) { |
|||
if (i * 8 + j * 6 <= bytes.length * 8) |
|||
base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F)); |
|||
else base64.push("="); |
|||
} |
|||
} |
|||
|
|||
return base64.join(""); |
|||
} |
|||
|
|||
|
|||
// Convert a base-64 string to a byte array
|
|||
module.exports.base64ToBytes = function(base64) { |
|||
|
|||
// Remove non-base-64 characters
|
|||
base64 = base64.replace(/[^A-Z0-9+\/]/ig, ""); |
|||
|
|||
for (var bytes = [], i = 0, imod4 = 0; i < base64.length; imod4 = ++i % 4) { |
|||
if (imod4 == 0) continue; |
|||
bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) | |
|||
(base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2))); |
|||
} |
|||
|
|||
return bytes; |
|||
} |
|||
|
|||
// Hex only (allowing bin would be potentially risky, as 01010101 = \x01 * 4 or 85)
|
|||
module.exports.coerceToBytes = function(input) { |
|||
if (typeof input == "string") return module.exports.hexToBytes(input); |
|||
return input; |
|||
} |
|||
|
|||
module.exports.binToBytes = function(bin) { |
|||
return bin.match(/......../g).map(function(x) { return parseInt(x,2) }); |
|||
} |
|||
|
|||
module.exports.bytesToBin = function(bytes) { |
|||
return bytes.map(function(x) { return x.toString(2).lpad('0',8) }).join(''); |
|||
} |
|||
|
|||
module.exports.bytesToString = function(bytes) { |
|||
return bytes.map(function(x){ return String.fromCharCode(x) }).join(''); |
|||
} |
|||
|
|||
module.exports.stringToBytes = function(string) { |
|||
return string.split('').map(function(x) { return x.charCodeAt(0) }); |
|||
} |
|||
|
|||
// utf8
|
@ -1,7 +0,0 @@ |
|||
/* |
|||
* 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
|
|||
*/ |
|||
(function(){var c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var d=window.Crypto={};var a=d.util={rotl:function(h,g){return(h<<g)|(h>>>(32-g))},rotr:function(h,g){return(h<<(32-g))|(h>>>g)},endian:function(h){if(h.constructor==Number){return a.rotl(h,8)&16711935|a.rotl(h,24)&4278255360}for(var g=0;g<h.length;g++){h[g]=a.endian(h[g])}return h},randomBytes:function(h){for(var g=[];h>0;h--){g.push(Math.floor(Math.random()*256))}return g},bytesToWords:function(h){for(var k=[],j=0,g=0;j<h.length;j++,g+=8){k[g>>>5]|=h[j]<<(24-g%32)}return k},wordsToBytes:function(i){for(var h=[],g=0;g<i.length*32;g+=8){h.push((i[g>>>5]>>>(24-g%32))&255)}return h},bytesToHex:function(g){for(var j=[],h=0;h<g.length;h++){j.push((g[h]>>>4).toString(16));j.push((g[h]&15).toString(16))}return j.join("")},hexToBytes:function(h){for(var g=[],i=0;i<h.length;i+=2){g.push(parseInt(h.substr(i,2),16))}return g},bytesToBase64:function(h){if(typeof btoa=="function"){return btoa(e.bytesToString(h))}for(var g=[],l=0;l<h.length;l+=3){var m=(h[l]<<16)|(h[l+1]<<8)|h[l+2];for(var k=0;k<4;k++){if(l*8+k*6<=h.length*8){g.push(c.charAt((m>>>6*(3-k))&63))}else{g.push("=")}}}return g.join("")},base64ToBytes:function(h){if(typeof atob=="function"){return e.stringToBytes(atob(h))}h=h.replace(/[^A-Z0-9+\/]/ig,"");for(var g=[],j=0,k=0;j<h.length;k=++j%4){if(k==0){continue}g.push(((c.indexOf(h.charAt(j-1))&(Math.pow(2,-2*k+8)-1))<<(k*2))|(c.indexOf(h.charAt(j))>>>(6-k*2)))}return g}};d.mode={};var b=d.charenc={};var f=b.UTF8={stringToBytes:function(g){return e.stringToBytes(unescape(encodeURIComponent(g)))},bytesToString:function(g){return decodeURIComponent(escape(e.bytesToString(g)))}};var e=b.Binary={stringToBytes:function(j){for(var g=[],h=0;h<j.length;h++){g.push(j.charCodeAt(h))}return g},bytesToString:function(g){for(var j=[],h=0;h<g.length;h++){j.push(String.fromCharCode(g[h]))}return j.join("")}}})(); |
@ -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); |
|||
|
|||
}; |
@ -1,170 +1,209 @@ |
|||
/*! |
|||
* 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
|
|||
* |
|||
* A JavaScript implementation of the RIPEMD-160 Algorithm |
|||
* Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009. |
|||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet |
|||
* Distributed under the BSD License |
|||
* See http://pajhome.org.uk/crypt/md5 for details.
|
|||
* Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
|
|||
* Ported to Crypto-JS by Stefan Thomas. |
|||
/* |
|||
CryptoJS v3.1.2 |
|||
code.google.com/p/crypto-js |
|||
(c) 2009-2013 by Jeff Mott. All rights reserved. |
|||
code.google.com/p/crypto-js/wiki/License |
|||
*/ |
|||
/** @preserve |
|||
(c) 2012 by Cédric Mesnil. All rights reserved. |
|||
|
|||
(function () { |
|||
// Shortcuts
|
|||
var C = Crypto, |
|||
util = C.util, |
|||
charenc = C.charenc, |
|||
UTF8 = charenc.UTF8, |
|||
Binary = charenc.Binary; |
|||
|
|||
// Convert a byte array to little-endian 32-bit words
|
|||
util.bytesToLWords = function (bytes) { |
|||
|
|||
var output = Array(bytes.length >> 2); |
|||
for (var i = 0; i < output.length; i++) |
|||
output[i] = 0; |
|||
for (var i = 0; i < bytes.length * 8; i += 8) |
|||
output[i>>5] |= (bytes[i / 8] & 0xFF) << (i%32); |
|||
return output; |
|||
}; |
|||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
|||
|
|||
// Convert little-endian 32-bit words to a byte array
|
|||
util.lWordsToBytes = function (words) { |
|||
var output = []; |
|||
for (var i = 0; i < words.length * 32; i += 8) |
|||
output.push((words[i>>5] >>> (i % 32)) & 0xff); |
|||
return output; |
|||
}; |
|||
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
|||
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
|||
|
|||
// Public API
|
|||
var RIPEMD160 = C.RIPEMD160 = function (message, options) { |
|||
var digestbytes = util.lWordsToBytes(RIPEMD160._rmd160(message)); |
|||
return options && options.asBytes ? digestbytes : |
|||
options && options.asString ? Binary.bytesToString(digestbytes) : |
|||
util.bytesToHex(digestbytes); |
|||
}; |
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
// The core
|
|||
RIPEMD160._rmd160 = function (message) |
|||
{ |
|||
// Convert to byte array
|
|||
if (message.constructor == String) message = UTF8.stringToBytes(message); |
|||
|
|||
var x = util.bytesToLWords(message), |
|||
len = message.length * 8; |
|||
|
|||
/* append padding */ |
|||
x[len >> 5] |= 0x80 << (len % 32); |
|||
x[(((len + 64) >>> 9) << 4) + 14] = len; |
|||
|
|||
var h0 = 0x67452301; |
|||
var h1 = 0xefcdab89; |
|||
var h2 = 0x98badcfe; |
|||
var h3 = 0x10325476; |
|||
var h4 = 0xc3d2e1f0; |
|||
|
|||
for (var i = 0; i < x.length; i += 16) { |
|||
var T; |
|||
var A1 = h0, B1 = h1, C1 = h2, D1 = h3, E1 = h4; |
|||
var A2 = h0, B2 = h1, C2 = h2, D2 = h3, E2 = h4; |
|||
for (var j = 0; j <= 79; ++j) { |
|||
T = safe_add(A1, rmd160_f(j, B1, C1, D1)); |
|||
T = safe_add(T, x[i + rmd160_r1[j]]); |
|||
T = safe_add(T, rmd160_K1(j)); |
|||
T = safe_add(bit_rol(T, rmd160_s1[j]), E1); |
|||
A1 = E1; E1 = D1; D1 = bit_rol(C1, 10); C1 = B1; B1 = T; |
|||
T = safe_add(A2, rmd160_f(79-j, B2, C2, D2)); |
|||
T = safe_add(T, x[i + rmd160_r2[j]]); |
|||
T = safe_add(T, rmd160_K2(j)); |
|||
T = safe_add(bit_rol(T, rmd160_s2[j]), E2); |
|||
A2 = E2; E2 = D2; D2 = bit_rol(C2, 10); C2 = B2; B2 = T; |
|||
} |
|||
T = safe_add(h1, safe_add(C1, D2)); |
|||
h1 = safe_add(h2, safe_add(D1, E2)); |
|||
h2 = safe_add(h3, safe_add(E1, A2)); |
|||
h3 = safe_add(h4, safe_add(A1, B2)); |
|||
h4 = safe_add(h0, safe_add(B1, C2)); |
|||
h0 = T; |
|||
} |
|||
return [h0, h1, h2, h3, h4]; |
|||
} |
|||
var conv = require('../convert'); |
|||
var UTF8 = require('./crypto').charenc.UTF8; |
|||
|
|||
function rmd160_f(j, x, y, z) |
|||
{ |
|||
return ( 0 <= j && j <= 15) ? (x ^ y ^ z) : |
|||
(16 <= j && j <= 31) ? (x & y) | (~x & z) : |
|||
(32 <= j && j <= 47) ? (x | ~y) ^ z : |
|||
(48 <= j && j <= 63) ? (x & z) | (y & ~z) : |
|||
(64 <= j && j <= 79) ? x ^ (y | ~z) : |
|||
"rmd160_f: j out of range"; |
|||
} |
|||
function rmd160_K1(j) |
|||
{ |
|||
return ( 0 <= j && j <= 15) ? 0x00000000 : |
|||
(16 <= j && j <= 31) ? 0x5a827999 : |
|||
(32 <= j && j <= 47) ? 0x6ed9eba1 : |
|||
(48 <= j && j <= 63) ? 0x8f1bbcdc : |
|||
(64 <= j && j <= 79) ? 0xa953fd4e : |
|||
"rmd160_K1: j out of range"; |
|||
} |
|||
function rmd160_K2(j) |
|||
{ |
|||
return ( 0 <= j && j <= 15) ? 0x50a28be6 : |
|||
(16 <= j && j <= 31) ? 0x5c4dd124 : |
|||
(32 <= j && j <= 47) ? 0x6d703ef3 : |
|||
(48 <= j && j <= 63) ? 0x7a6d76e9 : |
|||
(64 <= j && j <= 79) ? 0x00000000 : |
|||
"rmd160_K2: j out of range"; |
|||
} |
|||
var rmd160_r1 = [ |
|||
// Constants table
|
|||
var zl = [ |
|||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, |
|||
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, |
|||
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, |
|||
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, |
|||
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 |
|||
]; |
|||
var rmd160_r2 = [ |
|||
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]; |
|||
var zr = [ |
|||
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, |
|||
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, |
|||
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, |
|||
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, |
|||
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 |
|||
]; |
|||
var rmd160_s1 = [ |
|||
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]; |
|||
var sl = [ |
|||
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, |
|||
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, |
|||
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, |
|||
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, |
|||
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 |
|||
]; |
|||
var rmd160_s2 = [ |
|||
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 ]; |
|||
var sr = [ |
|||
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, |
|||
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, |
|||
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, |
|||
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, |
|||
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 |
|||
]; |
|||
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 ]; |
|||
|
|||
/* |
|||
* Add integers, wrapping at 2^32. This uses 16-bit operations internally |
|||
* to work around bugs in some JS interpreters. |
|||
*/ |
|||
function safe_add(x, y) |
|||
{ |
|||
var lsw = (x & 0xFFFF) + (y & 0xFFFF); |
|||
var msw = (x >> 16) + (y >> 16) + (lsw >> 16); |
|||
return (msw << 16) | (lsw & 0xFFFF); |
|||
var hl = [ 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]; |
|||
var hr = [ 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]; |
|||
|
|||
var bytesToWords = function (bytes) { |
|||
var words = []; |
|||
for (var i = 0, b = 0; i < bytes.length; i++, b += 8) { |
|||
words[b >>> 5] |= bytes[i] << (24 - b % 32); |
|||
} |
|||
return words; |
|||
}; |
|||
|
|||
/* |
|||
* Bitwise rotate a 32-bit number to the left. |
|||
var wordsToBytes = function (words) { |
|||
var bytes = []; |
|||
for (var b = 0; b < words.length * 32; b += 8) { |
|||
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); |
|||
} |
|||
return bytes; |
|||
}; |
|||
|
|||
var processBlock = function (H, M, offset) { |
|||
|
|||
// Swap endian
|
|||
for (var i = 0; i < 16; i++) { |
|||
var offset_i = offset + i; |
|||
var M_offset_i = M[offset_i]; |
|||
|
|||
// Swap
|
|||
M[offset_i] = ( |
|||
(((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | |
|||
(((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) |
|||
); |
|||
} |
|||
|
|||
// Working variables
|
|||
var al, bl, cl, dl, el; |
|||
var ar, br, cr, dr, er; |
|||
|
|||
ar = al = H[0]; |
|||
br = bl = H[1]; |
|||
cr = cl = H[2]; |
|||
dr = dl = H[3]; |
|||
er = el = H[4]; |
|||
// Computation
|
|||
var t; |
|||
for (var i = 0; i < 80; i += 1) { |
|||
t = (al + M[offset+zl[i]])|0; |
|||
if (i<16){ |
|||
t += f1(bl,cl,dl) + hl[0]; |
|||
} else if (i<32) { |
|||
t += f2(bl,cl,dl) + hl[1]; |
|||
} else if (i<48) { |
|||
t += f3(bl,cl,dl) + hl[2]; |
|||
} else if (i<64) { |
|||
t += f4(bl,cl,dl) + hl[3]; |
|||
} else {// if (i<80) {
|
|||
t += f5(bl,cl,dl) + hl[4]; |
|||
} |
|||
t = t|0; |
|||
t = rotl(t,sl[i]); |
|||
t = (t+el)|0; |
|||
al = el; |
|||
el = dl; |
|||
dl = rotl(cl, 10); |
|||
cl = bl; |
|||
bl = t; |
|||
|
|||
t = (ar + M[offset+zr[i]])|0; |
|||
if (i<16){ |
|||
t += f5(br,cr,dr) + hr[0]; |
|||
} else if (i<32) { |
|||
t += f4(br,cr,dr) + hr[1]; |
|||
} else if (i<48) { |
|||
t += f3(br,cr,dr) + hr[2]; |
|||
} else if (i<64) { |
|||
t += f2(br,cr,dr) + hr[3]; |
|||
} else {// if (i<80) {
|
|||
t += f1(br,cr,dr) + hr[4]; |
|||
} |
|||
t = t|0; |
|||
t = rotl(t,sr[i]) ; |
|||
t = (t+er)|0; |
|||
ar = er; |
|||
er = dr; |
|||
dr = rotl(cr, 10); |
|||
cr = br; |
|||
br = t; |
|||
} |
|||
// Intermediate hash value
|
|||
t = (H[1] + cl + dr)|0; |
|||
H[1] = (H[2] + dl + er)|0; |
|||
H[2] = (H[3] + el + ar)|0; |
|||
H[3] = (H[4] + al + br)|0; |
|||
H[4] = (H[0] + bl + cr)|0; |
|||
H[0] = t; |
|||
}; |
|||
|
|||
function f1(x, y, z) { |
|||
return ((x) ^ (y) ^ (z)); |
|||
|
|||
} |
|||
|
|||
function f2(x, y, z) { |
|||
return (((x)&(y)) | ((~x)&(z))); |
|||
} |
|||
|
|||
function f3(x, y, z) { |
|||
return (((x) | (~(y))) ^ (z)); |
|||
} |
|||
|
|||
function f4(x, y, z) { |
|||
return (((x) & (z)) | ((y)&(~(z)))); |
|||
} |
|||
|
|||
function f5(x, y, z) { |
|||
return ((x) ^ ((y) |(~(z)))); |
|||
|
|||
} |
|||
|
|||
function rotl(x,n) { |
|||
return (x<<n) | (x>>>(32-n)); |
|||
} |
|||
|
|||
/** |
|||
* RIPEMD160 hash algorithm. |
|||
*/ |
|||
function bit_rol(num, cnt) |
|||
{ |
|||
return (num << cnt) | (num >>> (32 - cnt)); |
|||
module.exports = function(message, options) { |
|||
|
|||
if (message.constructor === String) { |
|||
message = UTF8.stringToBytes(message); |
|||
} |
|||
|
|||
var H = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]; |
|||
var m = bytesToWords(message); |
|||
|
|||
var nBitsLeft = message.length * 8; |
|||
var nBitsTotal = message.length * 8; |
|||
|
|||
// Add padding
|
|||
m[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); |
|||
m[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( |
|||
(((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff) | |
|||
(((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00) |
|||
); |
|||
|
|||
for (var i=0 ; i<m.length; i += 16) { |
|||
processBlock(H, m, i); |
|||
} |
|||
})(); |
|||
|
|||
// Swap endian
|
|||
for (var i = 0; i < 5; i++) { |
|||
// Shortcut
|
|||
var H_i = H[i]; |
|||
|
|||
// Swap
|
|||
H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | |
|||
(((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); |
|||
} |
|||
|
|||
var digestbytes = wordsToBytes(H); |
|||
return options && options.asBytes ? digestbytes : |
|||
options && options.asString ? Binary.bytesToString(digestbytes) : |
|||
conv.bytesToHex(digestbytes); |
|||
}; |
|||
|
@ -1,7 +0,0 @@ |
|||
/* |
|||
* 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
|
|||
*/ |
|||
(function(){var g=Crypto,b=g.util,c=g.charenc,f=c.UTF8,e=c.Binary;var a=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298];var d=g.SHA256=function(j,h){var i=b.wordsToBytes(d._sha256(j));return h&&h.asBytes?i:h&&h.asString?e.bytesToString(i):b.bytesToHex(i)};d._sha256=function(q){if(q.constructor==String){q=f.stringToBytes(q)}var y=b.bytesToWords(q),z=q.length*8,r=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225],s=[],K,J,I,G,F,E,D,C,B,A,p,o;y[z>>5]|=128<<(24-z%32);y[((z+64>>9)<<4)+15]=z;for(var B=0;B<y.length;B+=16){K=r[0];J=r[1];I=r[2];G=r[3];F=r[4];E=r[5];D=r[6];C=r[7];for(var A=0;A<64;A++){if(A<16){s[A]=y[A+B]}else{var n=s[A-15],u=s[A-2],M=((n<<25)|(n>>>7))^((n<<14)|(n>>>18))^(n>>>3),L=((u<<15)|(u>>>17))^((u<<13)|(u>>>19))^(u>>>10);s[A]=M+(s[A-7]>>>0)+L+(s[A-16]>>>0)}var t=F&E^~F&D,k=K&J^K&I^J&I,x=((K<<30)|(K>>>2))^((K<<19)|(K>>>13))^((K<<10)|(K>>>22)),v=((F<<26)|(F>>>6))^((F<<21)|(F>>>11))^((F<<7)|(F>>>25));p=(C>>>0)+v+t+(a[A])+(s[A]>>>0);o=x+k;C=D;D=E;E=F;F=G+p;G=I;I=J;J=K;K=p+o}r[0]+=K;r[1]+=J;r[2]+=I;r[3]+=G;r[4]+=F;r[5]+=E;r[6]+=D;r[7]+=C}return r};d._blocksize=16})(); |
@ -1,133 +1,134 @@ |
|||
/*! |
|||
* 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
|
|||
/* |
|||
CryptoJS v3.1.2 |
|||
code.google.com/p/crypto-js |
|||
(c) 2009-2013 by Jeff Mott. All rights reserved. |
|||
code.google.com/p/crypto-js/wiki/License |
|||
*/ |
|||
(function(){ |
|||
|
|||
// Shortcuts
|
|||
var C = Crypto, |
|||
util = C.util, |
|||
charenc = C.charenc, |
|||
UTF8 = charenc.UTF8, |
|||
Binary = charenc.Binary; |
|||
|
|||
// Constants
|
|||
var K = [ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, |
|||
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, |
|||
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, |
|||
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, |
|||
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, |
|||
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, |
|||
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, |
|||
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, |
|||
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, |
|||
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, |
|||
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, |
|||
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, |
|||
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, |
|||
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, |
|||
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, |
|||
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 ]; |
|||
|
|||
// Public API
|
|||
var SHA256 = C.SHA256 = function (message, options) { |
|||
var digestbytes = util.wordsToBytes(SHA256._sha256(message)); |
|||
return options && options.asBytes ? digestbytes : |
|||
options && options.asString ? Binary.bytesToString(digestbytes) : |
|||
util.bytesToHex(digestbytes); |
|||
}; |
|||
|
|||
// The core
|
|||
SHA256._sha256 = function (message) { |
|||
var conv = require('../convert'), |
|||
util = require('../util'); |
|||
|
|||
// Convert to byte array
|
|||
if (message.constructor == String) message = UTF8.stringToBytes(message); |
|||
/* else, assume byte array already */ |
|||
|
|||
var m = util.bytesToWords(message), |
|||
l = message.length * 8, |
|||
H = [ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, |
|||
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 ], |
|||
w = [], |
|||
a, b, c, d, e, f, g, h, i, j, |
|||
t1, t2; |
|||
|
|||
// Padding
|
|||
m[l >> 5] |= 0x80 << (24 - l % 32); |
|||
m[((l + 64 >> 9) << 4) + 15] = l; |
|||
// Initialization round constants tables
|
|||
var K = []; |
|||
|
|||
for (var i = 0; i < m.length; i += 16) { |
|||
// Compute constants
|
|||
(function () { |
|||
function isPrime(n) { |
|||
var sqrtN = Math.sqrt(n); |
|||
for (var factor = 2; factor <= sqrtN; factor++) { |
|||
if (!(n % factor)) { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
a = H[0]; |
|||
b = H[1]; |
|||
c = H[2]; |
|||
d = H[3]; |
|||
e = H[4]; |
|||
f = H[5]; |
|||
g = H[6]; |
|||
h = H[7]; |
|||
return true; |
|||
} |
|||
|
|||
for (var j = 0; j < 64; j++) { |
|||
function getFractionalBits(n) { |
|||
return ((n - (n | 0)) * 0x100000000) | 0; |
|||
} |
|||
|
|||
if (j < 16) w[j] = m[j + i]; |
|||
else { |
|||
var n = 2; |
|||
var nPrime = 0; |
|||
while (nPrime < 64) { |
|||
if (isPrime(n)) { |
|||
K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3)); |
|||
nPrime++; |
|||
} |
|||
|
|||
var gamma0x = w[j - 15], |
|||
gamma1x = w[j - 2], |
|||
gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ |
|||
n++; |
|||
} |
|||
}()); |
|||
|
|||
// Reusable object
|
|||
var W = []; |
|||
|
|||
var processBlock = function (H, M, offset) { |
|||
|
|||
// Working variables
|
|||
var a = H[0]; |
|||
var b = H[1]; |
|||
var c = H[2]; |
|||
var d = H[3]; |
|||
var e = H[4]; |
|||
var f = H[5]; |
|||
var g = H[6]; |
|||
var h = H[7]; |
|||
|
|||
// Computation
|
|||
for (var i = 0; i < 64; i++) { |
|||
if (i < 16) { |
|||
W[i] = M[offset + i] | 0; |
|||
} else { |
|||
var gamma0x = W[i - 15]; |
|||
var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ |
|||
((gamma0x << 14) | (gamma0x >>> 18)) ^ |
|||
(gamma0x >>> 3), |
|||
gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ |
|||
(gamma0x >>> 3); |
|||
|
|||
var gamma1x = W[i - 2]; |
|||
var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ |
|||
((gamma1x << 13) | (gamma1x >>> 19)) ^ |
|||
(gamma1x >>> 10); |
|||
|
|||
w[j] = gamma0 + (w[j - 7] >>> 0) + |
|||
gamma1 + (w[j - 16] >>> 0); |
|||
|
|||
W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; |
|||
} |
|||
|
|||
var ch = e & f ^ ~e & g, |
|||
maj = a & b ^ a & c ^ b & c, |
|||
sigma0 = ((a << 30) | (a >>> 2)) ^ |
|||
((a << 19) | (a >>> 13)) ^ |
|||
((a << 10) | (a >>> 22)), |
|||
sigma1 = ((e << 26) | (e >>> 6)) ^ |
|||
((e << 21) | (e >>> 11)) ^ |
|||
((e << 7) | (e >>> 25)); |
|||
var ch = (e & f) ^ (~e & g); |
|||
var maj = (a & b) ^ (a & c) ^ (b & c); |
|||
|
|||
var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)); |
|||
var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); |
|||
|
|||
t1 = (h >>> 0) + sigma1 + ch + (K[j]) + (w[j] >>> 0); |
|||
t2 = sigma0 + maj; |
|||
var t1 = h + sigma1 + ch + K[i] + W[i]; |
|||
var t2 = sigma0 + maj; |
|||
|
|||
h = g; |
|||
g = f; |
|||
f = e; |
|||
e = d + t1; |
|||
e = (d + t1) | 0; |
|||
d = c; |
|||
c = b; |
|||
b = a; |
|||
a = t1 + t2; |
|||
|
|||
a = (t1 + t2) | 0; |
|||
} |
|||
|
|||
H[0] += a; |
|||
H[1] += b; |
|||
H[2] += c; |
|||
H[3] += d; |
|||
H[4] += e; |
|||
H[5] += f; |
|||
H[6] += g; |
|||
H[7] += h; |
|||
// Intermediate hash value
|
|||
H[0] = (H[0] + a) | 0; |
|||
H[1] = (H[1] + b) | 0; |
|||
H[2] = (H[2] + c) | 0; |
|||
H[3] = (H[3] + d) | 0; |
|||
H[4] = (H[4] + e) | 0; |
|||
H[5] = (H[5] + f) | 0; |
|||
H[6] = (H[6] + g) | 0; |
|||
H[7] = (H[7] + h) | 0; |
|||
}; |
|||
|
|||
/** |
|||
* SHA-256 hash algorithm. |
|||
*/ |
|||
module.exports = function(message, options) {; |
|||
|
|||
var H =[ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, |
|||
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 ]; |
|||
|
|||
if (message.constructor === String) { |
|||
message = conv.stringToBytes(message); |
|||
} |
|||
|
|||
return H; |
|||
var m = util.bytesToWords(message); |
|||
var l = message.length * 8; |
|||
|
|||
}; |
|||
m[l >> 5] |= 0x80 << (24 - l % 32); |
|||
m[((l + 64 >> 9) << 4) + 15] = l; |
|||
|
|||
for (var i=0 ; i<m.length; i += 16) { |
|||
processBlock(H, m, i); |
|||
} |
|||
|
|||
// Package private blocksize
|
|||
SHA256._blocksize = 16; |
|||
var digestbytes = util.wordsToBytes(H); |
|||
return options && options.asBytes ? digestbytes : |
|||
options && options.asString ? Binary.bytesToString(digestbytes) : |
|||
conv.bytesToHex(digestbytes); |
|||
}; |
|||
|
|||
})(); |
|||
module.exports._blocksize = 64 |
|||
|
@ -0,0 +1,239 @@ |
|||
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 |
@ -1,131 +1,179 @@ |
|||
Bitcoin.ECKey = (function () { |
|||
var ECDSA = Bitcoin.ECDSA; |
|||
var ecparams = getSECCurveByName("secp256k1"); |
|||
var rng = new SecureRandom(); |
|||
|
|||
var ECKey = function (input) { |
|||
var BigInteger = require('./jsbn/jsbn'); |
|||
var sec = require('./jsbn/sec'); |
|||
var base58 = require('./base58'); |
|||
var Crypto = require('./crypto-js/crypto'); |
|||
var util = require('./util'); |
|||
var conv = require('./convert'); |
|||
var Address = require('./address'); |
|||
var ecdsa = require('./ecdsa'); |
|||
var ECPointFp = require('./jsbn/ec').ECPointFp; |
|||
|
|||
var ecparams = sec("secp256k1"); |
|||
|
|||
// input can be nothing, array of bytes, hex string, or base58 string
|
|||
var ECKey = function (input,compressed) { |
|||
if (!(this instanceof ECKey)) { return new ECKey(input); } |
|||
if (!input) { |
|||
// Generate new key
|
|||
var n = ecparams.getN(); |
|||
this.priv = ECDSA.getBigRandom(n); |
|||
} else if (input instanceof BigInteger) { |
|||
// Input is a private key value
|
|||
this.priv = input; |
|||
} else if (Bitcoin.Util.isArray(input)) { |
|||
// Prepend zero byte to prevent interpretation as negative integer
|
|||
this.priv = BigInteger.fromByteArrayUnsigned(input); |
|||
} else if ("string" == typeof input) { |
|||
if (input.length == 51 && input[0] == '5') { |
|||
// Base58 encoded private key
|
|||
this.priv = BigInteger.fromByteArrayUnsigned(ECKey.decodeString(input)); |
|||
} else { |
|||
// Prepend zero byte to prevent interpretation as negative integer
|
|||
this.priv = BigInteger.fromByteArrayUnsigned(Crypto.util.base64ToBytes(input)); |
|||
} |
|||
} |
|||
this.compressed = !!ECKey.compressByDefault; |
|||
this.priv = ecdsa.getBigRandom(n); |
|||
this.compressed = compressed || false; |
|||
} |
|||
else this.import(input,compressed) |
|||
}; |
|||
|
|||
/** |
|||
* Whether public keys should be returned compressed by default. |
|||
*/ |
|||
ECKey.compressByDefault = false; |
|||
|
|||
/** |
|||
* Set whether the public key should be returned compressed or not. |
|||
*/ |
|||
ECKey.prototype.setCompressed = function (v) { |
|||
this.compressed = !!v; |
|||
ECKey.prototype.import = function (input,compressed) { |
|||
function has(li,v) { return li.indexOf(v) >= 0 } |
|||
function fromBin(x) { return BigInteger.fromByteArrayUnsigned(x) } |
|||
this.priv = |
|||
input instanceof ECKey ? input.priv |
|||
: input instanceof BigInteger ? input.mod(ecparams.getN()) |
|||
: util.isArray(input) ? fromBin(input.slice(0,32)) |
|||
: typeof input != "string" ? null |
|||
: input.length == 51 && input[0] == '5' ? fromBin(base58.checkDecode(input)) |
|||
: input.length == 52 && has('LK',input[0]) ? fromBin(base58.checkDecode(input)) |
|||
: has([64,65],input.length) ? fromBin(conv.hexToBytes(input.slice(0,64))) |
|||
: null |
|||
|
|||
this.compressed = |
|||
compressed !== undefined ? compressed |
|||
: input instanceof ECKey ? input.compressed |
|||
: input instanceof BigInteger ? false |
|||
: util.isArray(input) ? false |
|||
: typeof input != "string" ? null |
|||
: input.length == 51 && input[0] == '5' ? false |
|||
: input.length == 52 && has('LK',input[0]) ? true |
|||
: input.length == 64 ? false |
|||
: input.length == 65 ? true |
|||
: null |
|||
}; |
|||
|
|||
ECKey.prototype.getPub = function(compressed) { |
|||
if (compressed === undefined) compressed = this.compressed |
|||
return ECPubKey(ecparams.getG().multiply(this.priv),compressed) |
|||
} |
|||
|
|||
/** |
|||
* Return public key in DER encoding. |
|||
* @deprecated Reserved keyword, factory pattern. Use toHex, toBytes, etc. |
|||
*/ |
|||
ECKey.prototype.getPub = function () { |
|||
return this.getPubPoint().getEncoded(this.compressed); |
|||
ECKey.prototype['export'] = function(format) { |
|||
format || (format = 'hex') |
|||
return this['to' + format.substr(0, 1).toUpperCase() + format.substr(1)]() |
|||
}; |
|||
|
|||
/** |
|||
* Return public point as ECPoint object. |
|||
*/ |
|||
ECKey.prototype.getPubPoint = function () { |
|||
if (!this.pub) this.pub = ecparams.getG().multiply(this.priv); |
|||
ECKey.prototype.toBin = function() { |
|||
return conv.bytesToString(this.toBytes()) |
|||
} |
|||
|
|||
return this.pub; |
|||
}; |
|||
ECKey.prototype.toBase58 = function() { |
|||
return base58.checkEncode(this.toBytes(), 128) |
|||
} |
|||
|
|||
/** |
|||
* Get the pubKeyHash for this key. |
|||
* |
|||
* This is calculated as RIPE160(SHA256([encoded pubkey])) and returned as |
|||
* a byte array. |
|||
*/ |
|||
ECKey.prototype.getPubKeyHash = function () { |
|||
if (this.pubKeyHash) return this.pubKeyHash; |
|||
ECKey.prototype.toWif = ECKey.prototype.toBase58 |
|||
|
|||
return this.pubKeyHash = Bitcoin.Util.sha256ripe160(this.getPub()); |
|||
}; |
|||
ECKey.prototype.toHex = function() { |
|||
return conv.bytesToHex(this.toBytes()) |
|||
} |
|||
|
|||
ECKey.prototype.getBitcoinAddress = function () { |
|||
var hash = this.getPubKeyHash(); |
|||
var addr = new Bitcoin.Address(hash); |
|||
return addr; |
|||
}; |
|||
ECKey.prototype.toBytes = function() { |
|||
var bytes = this.priv.toByteArrayUnsigned(); |
|||
if (this.compressed) bytes.push(1) |
|||
return bytes |
|||
} |
|||
|
|||
ECKey.prototype.getExportedPrivateKey = function () { |
|||
var hash = this.priv.toByteArrayUnsigned(); |
|||
while (hash.length < 32) hash.unshift(0); |
|||
hash.unshift(0x80); |
|||
var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); |
|||
var bytes = hash.concat(checksum.slice(0,4)); |
|||
return Bitcoin.Base58.encode(bytes); |
|||
}; |
|||
ECKey.prototype.toString = ECKey.prototype.toBase58 |
|||
|
|||
ECKey.prototype.setPub = function (pub) { |
|||
this.pub = ECPointFp.decodeFrom(ecparams.getCurve(), pub); |
|||
}; |
|||
ECKey.prototype.getBitcoinAddress = function(v) { |
|||
return this.getPub().getBitcoinAddress(v) |
|||
} |
|||
|
|||
ECKey.prototype.toString = function (format) { |
|||
if (format === "base64") { |
|||
return Crypto.util.bytesToBase64(this.priv.toByteArrayUnsigned()); |
|||
} else { |
|||
return Crypto.util.bytesToHex(this.priv.toByteArrayUnsigned()); |
|||
ECKey.prototype.add = function(key) { |
|||
return ECKey(this.priv.add(ECKey(key).priv),this.compressed) |
|||
} |
|||
}; |
|||
|
|||
ECKey.prototype.sign = function (hash) { |
|||
return ECDSA.sign(hash, this.priv); |
|||
}; |
|||
ECKey.prototype.multiply = function(key) { |
|||
return ECKey(this.priv.multiply(ECKey(key).priv),this.compressed) |
|||
} |
|||
|
|||
ECKey.prototype.verify = function (hash, sig) { |
|||
return ECDSA.verify(hash, sig, this.getPub()); |
|||
}; |
|||
var ECPubKey = function(input,compressed) { |
|||
if (!(this instanceof ECPubKey)) { return new ECPubKey(input,compressed); } |
|||
if (!input) { |
|||
// Generate new key
|
|||
var n = ecparams.getN(); |
|||
this.pub = ecparams.getG().multiply(ecdsa.getBigRandom(n)) |
|||
this.compressed = compressed || false; |
|||
} |
|||
else this.import(input,compressed) |
|||
} |
|||
|
|||
/** |
|||
* Parse an exported private key contained in a string. |
|||
*/ |
|||
ECKey.decodeString = function (string) { |
|||
var bytes = Bitcoin.Base58.decode(string); |
|||
ECPubKey.prototype.import = function(input,compressed) { |
|||
var decode = function(x) { return ECPointFp.decodeFrom(ecparams.getCurve(), x) } |
|||
this.pub = |
|||
input instanceof ECPointFp ? input |
|||
: input instanceof ECKey ? ecparams.getG().multiply(input.priv) |
|||
: input instanceof ECPubKey ? input.pub |
|||
: typeof input == "string" ? decode(conv.hexToBytes(input)) |
|||
: util.isArray(input) ? decode(input) |
|||
: ecparams.getG().multiply(ecdsa.getBigRandom(ecparams.getN())) |
|||
|
|||
this.compressed = |
|||
arguments.length > 1 ? compressed |
|||
: input instanceof ECPointFp ? input.compressed |
|||
: input instanceof ECPubKey ? input.compressed |
|||
: (this.pub[0] < 4) |
|||
} |
|||
|
|||
var hash = bytes.slice(0, 33); |
|||
ECPubKey.prototype.add = function(key) { |
|||
return ECPubKey(this.pub.add(ECPubKey(key).pub),this.compressed) |
|||
} |
|||
|
|||
ECPubKey.prototype.multiply = function(key) { |
|||
return ECPubKey(this.pub.multiply(ECKey(key).priv),this.compressed) |
|||
} |
|||
|
|||
var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); |
|||
ECPubKey.prototype['export'] = function(format) { |
|||
format || (format = 'hex') |
|||
return this['to' + format.substr(0, 1).toUpperCase() + format.substr(1)]() |
|||
} |
|||
|
|||
if (checksum[0] != bytes[33] || |
|||
checksum[1] != bytes[34] || |
|||
checksum[2] != bytes[35] || |
|||
checksum[3] != bytes[36]) { |
|||
throw "Checksum validation failed!"; |
|||
ECPubKey.prototype.toBytes = function(compressed) { |
|||
if (compressed === undefined) compressed = this.compressed |
|||
return this.pub.getEncoded(compressed) |
|||
} |
|||
|
|||
var version = hash.shift(); |
|||
ECPubKey.prototype.toHex = function() { |
|||
return conv.bytesToHex(this.toBytes()) |
|||
} |
|||
|
|||
ECPubKey.prototype.toBin = function() { |
|||
return conv.bytesToString(this.toBytes()) |
|||
} |
|||
|
|||
if (version != 0x80) { |
|||
throw "Version "+version+" not supported!"; |
|||
ECPubKey.prototype.toBase58 = function() { |
|||
return base58.checkEncode(this.toBytes(), 128) |
|||
} |
|||
|
|||
return hash; |
|||
ECPubKey.prototype.toWif = ECPubKey.prototype.toBase58 |
|||
|
|||
ECPubKey.prototype.toString = function() { |
|||
return this.getBitcoinAddress().toString() |
|||
} |
|||
|
|||
ECPubKey.prototype.getBitcoinAddress = function(v) { |
|||
return new Address(util.sha256ripe160(this.toBytes()), v); |
|||
} |
|||
|
|||
ECKey.prototype.sign = function (hash) { |
|||
return ecdsa.sign(hash, this.priv); |
|||
}; |
|||
|
|||
ECKey.prototype.verify = function (hash, sig) { |
|||
return ecdsa.verify(hash, sig, this.getPub()['export']('bytes')); |
|||
}; |
|||
|
|||
return ECKey; |
|||
})(); |
|||
/** |
|||
* Parse an exported private key contained in a string. |
|||
*/ |
|||
|
|||
|
|||
module.exports = { ECKey: ECKey, ECPubKey: ECPubKey }; |
|||
|
@ -0,0 +1,235 @@ |
|||
var convert = require('./convert.js') |
|||
, base58 = require('./base58.js') |
|||
, assert = require('assert') |
|||
, format = require('util').format |
|||
, util = require('./util.js') |
|||
, Crypto = require('./crypto-js/crypto.js') |
|||
, ECKey = require('./eckey.js').ECKey |
|||
, ECPubKey = require('./eckey.js').ECPubKey |
|||
, Address = require('./address.js') |
|||
|
|||
var HDWallet = module.exports = function(seed, network) { |
|||
if (seed === undefined) return |
|||
|
|||
var I = Crypto.HMAC(Crypto.SHA512, seed, 'Bitcoin seed', { asBytes: true }) |
|||
this.chaincode = I.slice(32) |
|||
this.priv = new ECKey(I.slice(0, 32).concat([1]), true) |
|||
this.pub = this.priv.getPub() |
|||
this.network = network || 'Bitcoin' |
|||
this.index = 0 |
|||
this.depth = 0 |
|||
} |
|||
|
|||
HDWallet.HIGHEST_BIT = 0x80000000 |
|||
HDWallet.LENGTH = 78 |
|||
|
|||
HDWallet.VERSIONS = { |
|||
Bitcoin: [0x0488B21E, 0x0488ADE4], |
|||
BitcoinTest: [0x043587CF, 0x04358394] |
|||
} |
|||
|
|||
function arrayEqual(a, b) { |
|||
return !(a < b || a > b) |
|||
} |
|||
|
|||
HDWallet.getChecksum = function(buffer) { |
|||
assert.equal(buffer.length, HDWallet.LENGTH) |
|||
return Crypto.SHA256(Crypto.SHA256(buffer, { asBytes: true }), { asBytes: true }).slice(0, 4) |
|||
} |
|||
|
|||
HDWallet.fromMasterHex = function(hex) { |
|||
var bytes = convert.hexToBytes(hex) |
|||
return new HDWallet(convert.bytesToString(bytes)) |
|||
} |
|||
|
|||
HDWallet.fromBase58 = function(input) { |
|||
var buffer = base58.decode(input) |
|||
|
|||
if (buffer.length == HDWallet.LENGTH + 4) { |
|||
var expectedChecksum = buffer.slice(HDWallet.LENGTH, HDWallet.LENGTH + 4) |
|||
buffer = buffer.slice(0, HDWallet.LENGTH) |
|||
var actualChecksum = HDWallet.getChecksum(buffer) |
|||
|
|||
if (!arrayEqual(expectedChecksum, actualChecksum)) { |
|||
throw new Error('Checksum mismatch') |
|||
} |
|||
} |
|||
|
|||
return HDWallet.fromBytes(buffer) |
|||
} |
|||
|
|||
HDWallet.fromHex = function(input) { |
|||
return HDWallet.fromBytes(convert.hexToBytes(input)) |
|||
} |
|||
|
|||
HDWallet.fromBytes = function(input) { |
|||
// This 78 byte structure can be encoded like other Bitcoin data in Base58. (+32 bits checksum)
|
|||
if (input.length != HDWallet.LENGTH) { |
|||
throw new Error(format('Invalid input length, %s. Expected %s.', input.length, HDWallet.LENGTH)) |
|||
} |
|||
|
|||
var hd = new HDWallet() |
|||
|
|||
// 4 byte: version bytes (mainnet: 0x0488B21E public, 0x0488ADE4 private;
|
|||
// testnet: 0x043587CF public, 0x04358394 private)
|
|||
var versionBytes = input.slice(0, 4) |
|||
, versionWord = util.bytesToWords(versionBytes)[0] |
|||
, type |
|||
|
|||
Object.keys(HDWallet.VERSIONS).forEach(function(name) { |
|||
HDWallet.VERSIONS[name].forEach(function(word, i) { |
|||
if (versionWord != word) return |
|||
type = i ? 'private' : 'public' |
|||
hd.network = name |
|||
}) |
|||
}) |
|||
|
|||
if (!hd.network) { |
|||
throw new Error(format('Could not find version %s', convert.bytesToHex(versionBytes))) |
|||
} |
|||
|
|||
// 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ...
|
|||
hd.depth = input[4] |
|||
|
|||
// 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
|
|||
hd.parentFingerprint = input.slice(5, 9) |
|||
assert((hd.depth === 0) == arrayEqual(hd.parentFingerprint, [0, 0, 0, 0])) |
|||
|
|||
// 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
|
|||
// This is encoded in MSB order. (0x00000000 if master key)
|
|||
hd.index = util.bytesToNum(input.slice(9, 13).reverse()) |
|||
assert(hd.depth > 0 || hd.index === 0) |
|||
|
|||
// 32 bytes: the chain code
|
|||
hd.chaincode = input.slice(13, 45) |
|||
|
|||
// 33 bytes: the public key or private key data (0x02 + X or 0x03 + X for
|
|||
// public keys, 0x00 + k for private keys)
|
|||
if (type == 'private') { |
|||
hd.priv = new ECKey(input.slice(46, 78).concat([1]), true) |
|||
hd.pub = hd.priv.getPub() |
|||
} else { |
|||
hd.pub = new ECPubKey(input.slice(45, 78), true) |
|||
} |
|||
|
|||
return hd |
|||
} |
|||
|
|||
HDWallet.prototype.getIdentifier = function() { |
|||
return util.sha256ripe160(this.pub.toBytes()) |
|||
} |
|||
|
|||
HDWallet.prototype.getFingerprint = function() { |
|||
return this.getIdentifier().slice(0, 4) |
|||
} |
|||
|
|||
HDWallet.prototype.getBitcoinAddress = function() { |
|||
var test = this.network.match(/Test$/) |
|||
return new Address(util.sha256ripe160(this.pub.toBytes()), test ? 111 : 0) |
|||
} |
|||
|
|||
HDWallet.prototype.toBytes = function(priv) { |
|||
var buffer = [] |
|||
|
|||
// Version
|
|||
// 4 byte: version bytes (mainnet: 0x0488B21E public, 0x0488ADE4 private; testnet: 0x043587CF public,
|
|||
// 0x04358394 private)
|
|||
var vBytes = util.wordsToBytes([HDWallet.VERSIONS[this.network][priv ? 1 : 0]]) |
|||
|
|||
buffer = buffer.concat(vBytes) |
|||
assert.equal(buffer.length, 4) |
|||
|
|||
// Depth
|
|||
// 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ....
|
|||
buffer.push(this.depth) |
|||
assert.equal(buffer.length, 4 + 1) |
|||
|
|||
// 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
|
|||
buffer = buffer.concat(this.depth ? this.parentFingerprint : [0, 0, 0, 0]) |
|||
assert.equal(buffer.length, 4 + 1 + 4) |
|||
|
|||
// 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
|
|||
// This is encoded in MSB order. (0x00000000 if master key)
|
|||
buffer = buffer.concat(util.numToBytes(this.index, 4).reverse()) |
|||
assert.equal(buffer.length, 4 + 1 + 4 + 4) |
|||
|
|||
// 32 bytes: the chain code
|
|||
buffer = buffer.concat(this.chaincode) |
|||
assert.equal(buffer.length, 4 + 1 + 4 + 4 + 32) |
|||
|
|||
// 33 bytes: the public key or private key data
|
|||
// (0x02 + X or 0x03 + X for public keys, 0x00 + k for private keys)
|
|||
if (priv) { |
|||
assert(this.priv, 'Cannot serialize to private without private key') |
|||
buffer.push(0) |
|||
buffer = buffer.concat(this.priv.toBytes().slice(0, 32)) |
|||
} else { |
|||
buffer = buffer.concat(this.pub.toBytes(true)) |
|||
} |
|||
|
|||
return buffer |
|||
} |
|||
|
|||
HDWallet.prototype.toHex = function(priv) { |
|||
var bytes = this.toBytes(priv) |
|||
return convert.bytesToHex(bytes) |
|||
} |
|||
|
|||
HDWallet.prototype.toBase58 = function(priv) { |
|||
var buffer = this.toBytes(priv) |
|||
, checksum = HDWallet.getChecksum(buffer) |
|||
buffer = buffer.concat(checksum) |
|||
return base58.encode(buffer) |
|||
} |
|||
|
|||
HDWallet.prototype.derive = function(i) { |
|||
var I |
|||
, iBytes = util.numToBytes(i, 4).reverse() |
|||
, cPar = this.chaincode |
|||
, usePriv = i >= HDWallet.HIGHEST_BIT |
|||
|
|||
if (usePriv) { |
|||
assert(this.priv, 'Private derive on public key') |
|||
|
|||
// If 1, private derivation is used:
|
|||
// let I = HMAC-SHA512(Key = cpar, Data = 0x00 || kpar || i) [Note:]
|
|||
var kPar = this.priv.toBytes().slice(0, 32) |
|||
I = Crypto.HMAC(Crypto.SHA512, [0].concat(kPar, iBytes), cPar, { asBytes: true }) |
|||
} else { |
|||
// If 0, public derivation is used:
|
|||
// let I = HMAC-SHA512(Key = cpar, Data = χ(kpar*G) || i)
|
|||
var KPar = this.pub.toBytes(true) |
|||
I = Crypto.HMAC(Crypto.SHA512, KPar.concat(iBytes), cPar, { asBytes: true }) |
|||
} |
|||
|
|||
// Split I = IL || IR into two 32-byte sequences, IL and IR.
|
|||
var IL = I.slice(0, 32) |
|||
, IR = I.slice(32) |
|||
|
|||
var hd = new HDWallet() |
|||
hd.network = this.network |
|||
|
|||
if (this.priv) { |
|||
// ki = IL + kpar (mod n).
|
|||
hd.priv = this.priv.add(new ECKey(IL.concat([1]))) |
|||
hd.priv.compressed = true |
|||
hd.pub = hd.priv.getPub() |
|||
} else { |
|||
// Ki = (IL + kpar)*G = IL*G + Kpar
|
|||
hd.pub = this.pub.add(new ECKey(IL.concat([1])).getPub()) |
|||
} |
|||
|
|||
// ci = IR.
|
|||
hd.chaincode = IR |
|||
hd.parentFingerprint = this.getFingerprint() |
|||
hd.depth = this.depth + 1 |
|||
hd.index = i |
|||
hd.pub.compressed = true |
|||
return hd |
|||
} |
|||
|
|||
HDWallet.prototype.derivePrivate = function(index) { |
|||
return this.derive(index + HDWallet.HIGHEST_BIT) |
|||
} |
|||
|
|||
HDWallet.prototype.toString = HDWallet.prototype.toBase58 |
@ -0,0 +1,54 @@ |
|||
// Bit-wise rotate left
|
|||
var rotl = function (n, b) { |
|||
return (n << b) | (n >>> (32 - b)); |
|||
}; |
|||
|
|||
// Bit-wise rotate right
|
|||
var rotr = function (n, b) { |
|||
return (n << (32 - b)) | (n >>> b); |
|||
}; |
|||
|
|||
// Swap big-endian to little-endian and vice versa
|
|||
var endian = function (n) { |
|||
// If number given, swap endian
|
|||
if (n.constructor == Number) { |
|||
return rotl(n, 8) & 0x00FF00FF | rotl(n, 24) & 0xFF00FF00; |
|||
} |
|||
|
|||
// Else, assume array and swap all items
|
|||
for (var i = 0; i < n.length; i++) { |
|||
n[i] = endian(n[i]); |
|||
} |
|||
return n; |
|||
} |
|||
|
|||
var Key = require('./eckey'); |
|||
|
|||
module.exports = { |
|||
Address: require('./address'), |
|||
Key: Key.ECKey, |
|||
ECKey: Key.ECKey, |
|||
ECPubKey: Key.ECPubKey, |
|||
Message: require('./message'), |
|||
BigInteger: require('./jsbn/jsbn'), |
|||
Crypto: require('./crypto-js/crypto'), |
|||
Script: require('./script'), |
|||
Opcode: require('./opcode'), |
|||
Transaction: require('./transaction').Transaction, |
|||
Util: require('./util'), |
|||
TransactionIn: require('./transaction').TransactionIn, |
|||
TransactionOut: require('./transaction').TransactionOut, |
|||
ECPointFp: require('./jsbn/ec').ECPointFp, |
|||
Wallet: require('./wallet'), |
|||
|
|||
ecdsa: require('./ecdsa'), |
|||
HDWallet: require('./hdwallet.js'), |
|||
|
|||
// base58 encoding/decoding to bytes
|
|||
base58: require('./base58'), |
|||
|
|||
// conversions
|
|||
convert: require('./convert'), |
|||
|
|||
endian: endian |
|||
} |
File diff suppressed because it is too large
@ -1,656 +0,0 @@ |
|||
// Copyright (c) 2005-2009 Tom Wu
|
|||
// All Rights Reserved.
|
|||
// See "LICENSE" for details.
|
|||
|
|||
// Extended JavaScript BN functions, required for RSA private ops.
|
|||
|
|||
// Version 1.1: new BigInteger("0", 10) returns "proper" zero
|
|||
// Version 1.2: square() API, isProbablePrime fix
|
|||
|
|||
// (public)
|
|||
function bnClone() { var r = nbi(); this.copyTo(r); return r; } |
|||
|
|||
// (public) return value as integer
|
|||
function bnIntValue() { |
|||
if(this.s < 0) { |
|||
if(this.t == 1) return this[0]-this.DV; |
|||
else if(this.t == 0) return -1; |
|||
} |
|||
else if(this.t == 1) return this[0]; |
|||
else if(this.t == 0) return 0; |
|||
// assumes 16 < DB < 32
|
|||
return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0]; |
|||
} |
|||
|
|||
// (public) return value as byte
|
|||
function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; } |
|||
|
|||
// (public) return value as short (assumes DB>=16)
|
|||
function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; } |
|||
|
|||
// (protected) return x s.t. r^x < DV
|
|||
function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } |
|||
|
|||
// (public) 0 if this == 0, 1 if this > 0
|
|||
function bnSigNum() { |
|||
if(this.s < 0) return -1; |
|||
else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; |
|||
else return 1; |
|||
} |
|||
|
|||
// (protected) convert to radix string
|
|||
function bnpToRadix(b) { |
|||
if(b == null) b = 10; |
|||
if(this.signum() == 0 || b < 2 || b > 36) return "0"; |
|||
var cs = this.chunkSize(b); |
|||
var a = Math.pow(b,cs); |
|||
var d = nbv(a), y = nbi(), z = nbi(), r = ""; |
|||
this.divRemTo(d,y,z); |
|||
while(y.signum() > 0) { |
|||
r = (a+z.intValue()).toString(b).substr(1) + r; |
|||
y.divRemTo(d,y,z); |
|||
} |
|||
return z.intValue().toString(b) + r; |
|||
} |
|||
|
|||
// (protected) convert from radix string
|
|||
function bnpFromRadix(s,b) { |
|||
this.fromInt(0); |
|||
if(b == null) b = 10; |
|||
var cs = this.chunkSize(b); |
|||
var d = Math.pow(b,cs), mi = false, j = 0, w = 0; |
|||
for(var i = 0; i < s.length; ++i) { |
|||
var x = intAt(s,i); |
|||
if(x < 0) { |
|||
if(s.charAt(i) == "-" && this.signum() == 0) mi = true; |
|||
continue; |
|||
} |
|||
w = b*w+x; |
|||
if(++j >= cs) { |
|||
this.dMultiply(d); |
|||
this.dAddOffset(w,0); |
|||
j = 0; |
|||
w = 0; |
|||
} |
|||
} |
|||
if(j > 0) { |
|||
this.dMultiply(Math.pow(b,j)); |
|||
this.dAddOffset(w,0); |
|||
} |
|||
if(mi) BigInteger.ZERO.subTo(this,this); |
|||
} |
|||
|
|||
// (protected) alternate constructor
|
|||
function bnpFromNumber(a,b,c) { |
|||
if("number" == typeof b) { |
|||
// new BigInteger(int,int,RNG)
|
|||
if(a < 2) this.fromInt(1); |
|||
else { |
|||
this.fromNumber(a,c); |
|||
if(!this.testBit(a-1)) // force MSB set
|
|||
this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); |
|||
if(this.isEven()) this.dAddOffset(1,0); // force odd
|
|||
while(!this.isProbablePrime(b)) { |
|||
this.dAddOffset(2,0); |
|||
if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this); |
|||
} |
|||
} |
|||
} |
|||
else { |
|||
// new BigInteger(int,RNG)
|
|||
var x = new Array(), t = a&7; |
|||
x.length = (a>>3)+1; |
|||
b.nextBytes(x); |
|||
if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0; |
|||
this.fromString(x,256); |
|||
} |
|||
} |
|||
|
|||
// (public) convert to bigendian byte array
|
|||
function bnToByteArray() { |
|||
var i = this.t, r = new Array(); |
|||
r[0] = this.s; |
|||
var p = this.DB-(i*this.DB)%8, d, k = 0; |
|||
if(i-- > 0) { |
|||
if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p) |
|||
r[k++] = d|(this.s<<(this.DB-p)); |
|||
while(i >= 0) { |
|||
if(p < 8) { |
|||
d = (this[i]&((1<<p)-1))<<(8-p); |
|||
d |= this[--i]>>(p+=this.DB-8); |
|||
} |
|||
else { |
|||
d = (this[i]>>(p-=8))&0xff; |
|||
if(p <= 0) { p += this.DB; --i; } |
|||
} |
|||
if((d&0x80) != 0) d |= -256; |
|||
if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; |
|||
if(k > 0 || d != this.s) r[k++] = d; |
|||
} |
|||
} |
|||
return r; |
|||
} |
|||
|
|||
function bnEquals(a) { return(this.compareTo(a)==0); } |
|||
function bnMin(a) { return(this.compareTo(a)<0)?this:a; } |
|||
function bnMax(a) { return(this.compareTo(a)>0)?this:a; } |
|||
|
|||
// (protected) r = this op a (bitwise)
|
|||
function bnpBitwiseTo(a,op,r) { |
|||
var i, f, m = Math.min(a.t,this.t); |
|||
for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]); |
|||
if(a.t < this.t) { |
|||
f = a.s&this.DM; |
|||
for(i = m; i < this.t; ++i) r[i] = op(this[i],f); |
|||
r.t = this.t; |
|||
} |
|||
else { |
|||
f = this.s&this.DM; |
|||
for(i = m; i < a.t; ++i) r[i] = op(f,a[i]); |
|||
r.t = a.t; |
|||
} |
|||
r.s = op(this.s,a.s); |
|||
r.clamp(); |
|||
} |
|||
|
|||
// (public) this & a
|
|||
function op_and(x,y) { return x&y; } |
|||
function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } |
|||
|
|||
// (public) this | a
|
|||
function op_or(x,y) { return x|y; } |
|||
function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } |
|||
|
|||
// (public) this ^ a
|
|||
function op_xor(x,y) { return x^y; } |
|||
function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } |
|||
|
|||
// (public) this & ~a
|
|||
function op_andnot(x,y) { return x&~y; } |
|||
function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } |
|||
|
|||
// (public) ~this
|
|||
function bnNot() { |
|||
var r = nbi(); |
|||
for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i]; |
|||
r.t = this.t; |
|||
r.s = ~this.s; |
|||
return r; |
|||
} |
|||
|
|||
// (public) this << n
|
|||
function bnShiftLeft(n) { |
|||
var r = nbi(); |
|||
if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); |
|||
return r; |
|||
} |
|||
|
|||
// (public) this >> n
|
|||
function bnShiftRight(n) { |
|||
var r = nbi(); |
|||
if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); |
|||
return r; |
|||
} |
|||
|
|||
// return index of lowest 1-bit in x, x < 2^31
|
|||
function lbit(x) { |
|||
if(x == 0) return -1; |
|||
var r = 0; |
|||
if((x&0xffff) == 0) { x >>= 16; r += 16; } |
|||
if((x&0xff) == 0) { x >>= 8; r += 8; } |
|||
if((x&0xf) == 0) { x >>= 4; r += 4; } |
|||
if((x&3) == 0) { x >>= 2; r += 2; } |
|||
if((x&1) == 0) ++r; |
|||
return r; |
|||
} |
|||
|
|||
// (public) returns index of lowest 1-bit (or -1 if none)
|
|||
function bnGetLowestSetBit() { |
|||
for(var i = 0; i < this.t; ++i) |
|||
if(this[i] != 0) return i*this.DB+lbit(this[i]); |
|||
if(this.s < 0) return this.t*this.DB; |
|||
return -1; |
|||
} |
|||
|
|||
// return number of 1 bits in x
|
|||
function cbit(x) { |
|||
var r = 0; |
|||
while(x != 0) { x &= x-1; ++r; } |
|||
return r; |
|||
} |
|||
|
|||
// (public) return number of set bits
|
|||
function bnBitCount() { |
|||
var r = 0, x = this.s&this.DM; |
|||
for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x); |
|||
return r; |
|||
} |
|||
|
|||
// (public) true iff nth bit is set
|
|||
function bnTestBit(n) { |
|||
var j = Math.floor(n/this.DB); |
|||
if(j >= this.t) return(this.s!=0); |
|||
return((this[j]&(1<<(n%this.DB)))!=0); |
|||
} |
|||
|
|||
// (protected) this op (1<<n)
|
|||
function bnpChangeBit(n,op) { |
|||
var r = BigInteger.ONE.shiftLeft(n); |
|||
this.bitwiseTo(r,op,r); |
|||
return r; |
|||
} |
|||
|
|||
// (public) this | (1<<n)
|
|||
function bnSetBit(n) { return this.changeBit(n,op_or); } |
|||
|
|||
// (public) this & ~(1<<n)
|
|||
function bnClearBit(n) { return this.changeBit(n,op_andnot); } |
|||
|
|||
// (public) this ^ (1<<n)
|
|||
function bnFlipBit(n) { return this.changeBit(n,op_xor); } |
|||
|
|||
// (protected) r = this + a
|
|||
function bnpAddTo(a,r) { |
|||
var i = 0, c = 0, m = Math.min(a.t,this.t); |
|||
while(i < m) { |
|||
c += this[i]+a[i]; |
|||
r[i++] = c&this.DM; |
|||
c >>= this.DB; |
|||
} |
|||
if(a.t < this.t) { |
|||
c += a.s; |
|||
while(i < this.t) { |
|||
c += this[i]; |
|||
r[i++] = c&this.DM; |
|||
c >>= this.DB; |
|||
} |
|||
c += this.s; |
|||
} |
|||
else { |
|||
c += this.s; |
|||
while(i < a.t) { |
|||
c += a[i]; |
|||
r[i++] = c&this.DM; |
|||
c >>= this.DB; |
|||
} |
|||
c += a.s; |
|||
} |
|||
r.s = (c<0)?-1:0; |
|||
if(c > 0) r[i++] = c; |
|||
else if(c < -1) r[i++] = this.DV+c; |
|||
r.t = i; |
|||
r.clamp(); |
|||
} |
|||
|
|||
// (public) this + a
|
|||
function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } |
|||
|
|||
// (public) this - a
|
|||
function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } |
|||
|
|||
// (public) this * a
|
|||
function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } |
|||
|
|||
// (public) this^2
|
|||
function bnSquare() { var r = nbi(); this.squareTo(r); return r; } |
|||
|
|||
// (public) this / a
|
|||
function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } |
|||
|
|||
// (public) this % a
|
|||
function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } |
|||
|
|||
// (public) [this/a,this%a]
|
|||
function bnDivideAndRemainder(a) { |
|||
var q = nbi(), r = nbi(); |
|||
this.divRemTo(a,q,r); |
|||
return new Array(q,r); |
|||
} |
|||
|
|||
// (protected) this *= n, this >= 0, 1 < n < DV
|
|||
function bnpDMultiply(n) { |
|||
this[this.t] = this.am(0,n-1,this,0,0,this.t); |
|||
++this.t; |
|||
this.clamp(); |
|||
} |
|||
|
|||
// (protected) this += n << w words, this >= 0
|
|||
function bnpDAddOffset(n,w) { |
|||
if(n == 0) return; |
|||
while(this.t <= w) this[this.t++] = 0; |
|||
this[w] += n; |
|||
while(this[w] >= this.DV) { |
|||
this[w] -= this.DV; |
|||
if(++w >= this.t) this[this.t++] = 0; |
|||
++this[w]; |
|||
} |
|||
} |
|||
|
|||
// A "null" reducer
|
|||
function NullExp() {} |
|||
function nNop(x) { return x; } |
|||
function nMulTo(x,y,r) { x.multiplyTo(y,r); } |
|||
function nSqrTo(x,r) { x.squareTo(r); } |
|||
|
|||
NullExp.prototype.convert = nNop; |
|||
NullExp.prototype.revert = nNop; |
|||
NullExp.prototype.mulTo = nMulTo; |
|||
NullExp.prototype.sqrTo = nSqrTo; |
|||
|
|||
// (public) this^e
|
|||
function bnPow(e) { return this.exp(e,new NullExp()); } |
|||
|
|||
// (protected) r = lower n words of "this * a", a.t <= n
|
|||
// "this" should be the larger one if appropriate.
|
|||
function bnpMultiplyLowerTo(a,n,r) { |
|||
var i = Math.min(this.t+a.t,n); |
|||
r.s = 0; // assumes a,this >= 0
|
|||
r.t = i; |
|||
while(i > 0) r[--i] = 0; |
|||
var j; |
|||
for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t); |
|||
for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i); |
|||
r.clamp(); |
|||
} |
|||
|
|||
// (protected) r = "this * a" without lower n words, n > 0
|
|||
// "this" should be the larger one if appropriate.
|
|||
function bnpMultiplyUpperTo(a,n,r) { |
|||
--n; |
|||
var i = r.t = this.t+a.t-n; |
|||
r.s = 0; // assumes a,this >= 0
|
|||
while(--i >= 0) r[i] = 0; |
|||
for(i = Math.max(n-this.t,0); i < a.t; ++i) |
|||
r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n); |
|||
r.clamp(); |
|||
r.drShiftTo(1,r); |
|||
} |
|||
|
|||
// Barrett modular reduction
|
|||
function Barrett(m) { |
|||
// setup Barrett
|
|||
this.r2 = nbi(); |
|||
this.q3 = nbi(); |
|||
BigInteger.ONE.dlShiftTo(2*m.t,this.r2); |
|||
this.mu = this.r2.divide(m); |
|||
this.m = m; |
|||
} |
|||
|
|||
function barrettConvert(x) { |
|||
if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); |
|||
else if(x.compareTo(this.m) < 0) return x; |
|||
else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } |
|||
} |
|||
|
|||
function barrettRevert(x) { return x; } |
|||
|
|||
// x = x mod m (HAC 14.42)
|
|||
function barrettReduce(x) { |
|||
x.drShiftTo(this.m.t-1,this.r2); |
|||
if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } |
|||
this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); |
|||
this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); |
|||
while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); |
|||
x.subTo(this.r2,x); |
|||
while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); |
|||
} |
|||
|
|||
// r = x^2 mod m; x != r
|
|||
function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } |
|||
|
|||
// r = x*y mod m; x,y != r
|
|||
function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } |
|||
|
|||
Barrett.prototype.convert = barrettConvert; |
|||
Barrett.prototype.revert = barrettRevert; |
|||
Barrett.prototype.reduce = barrettReduce; |
|||
Barrett.prototype.mulTo = barrettMulTo; |
|||
Barrett.prototype.sqrTo = barrettSqrTo; |
|||
|
|||
// (public) this^e % m (HAC 14.85)
|
|||
function bnModPow(e,m) { |
|||
var i = e.bitLength(), k, r = nbv(1), z; |
|||
if(i <= 0) return r; |
|||
else if(i < 18) k = 1; |
|||
else if(i < 48) k = 3; |
|||
else if(i < 144) k = 4; |
|||
else if(i < 768) k = 5; |
|||
else k = 6; |
|||
if(i < 8) |
|||
z = new Classic(m); |
|||
else if(m.isEven()) |
|||
z = new Barrett(m); |
|||
else |
|||
z = new Montgomery(m); |
|||
|
|||
// precomputation
|
|||
var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1; |
|||
g[1] = z.convert(this); |
|||
if(k > 1) { |
|||
var g2 = nbi(); |
|||
z.sqrTo(g[1],g2); |
|||
while(n <= km) { |
|||
g[n] = nbi(); |
|||
z.mulTo(g2,g[n-2],g[n]); |
|||
n += 2; |
|||
} |
|||
} |
|||
|
|||
var j = e.t-1, w, is1 = true, r2 = nbi(), t; |
|||
i = nbits(e[j])-1; |
|||
while(j >= 0) { |
|||
if(i >= k1) w = (e[j]>>(i-k1))&km; |
|||
else { |
|||
w = (e[j]&((1<<(i+1))-1))<<(k1-i); |
|||
if(j > 0) w |= e[j-1]>>(this.DB+i-k1); |
|||
} |
|||
|
|||
n = k; |
|||
while((w&1) == 0) { w >>= 1; --n; } |
|||
if((i -= n) < 0) { i += this.DB; --j; } |
|||
if(is1) { // ret == 1, don't bother squaring or multiplying it
|
|||
g[w].copyTo(r); |
|||
is1 = false; |
|||
} |
|||
else { |
|||
while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } |
|||
if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } |
|||
z.mulTo(r2,g[w],r); |
|||
} |
|||
|
|||
while(j >= 0 && (e[j]&(1<<i)) == 0) { |
|||
z.sqrTo(r,r2); t = r; r = r2; r2 = t; |
|||
if(--i < 0) { i = this.DB-1; --j; } |
|||
} |
|||
} |
|||
return z.revert(r); |
|||
} |
|||
|
|||
// (public) gcd(this,a) (HAC 14.54)
|
|||
function bnGCD(a) { |
|||
var x = (this.s<0)?this.negate():this.clone(); |
|||
var y = (a.s<0)?a.negate():a.clone(); |
|||
if(x.compareTo(y) < 0) { var t = x; x = y; y = t; } |
|||
var i = x.getLowestSetBit(), g = y.getLowestSetBit(); |
|||
if(g < 0) return x; |
|||
if(i < g) g = i; |
|||
if(g > 0) { |
|||
x.rShiftTo(g,x); |
|||
y.rShiftTo(g,y); |
|||
} |
|||
while(x.signum() > 0) { |
|||
if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); |
|||
if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); |
|||
if(x.compareTo(y) >= 0) { |
|||
x.subTo(y,x); |
|||
x.rShiftTo(1,x); |
|||
} |
|||
else { |
|||
y.subTo(x,y); |
|||
y.rShiftTo(1,y); |
|||
} |
|||
} |
|||
if(g > 0) y.lShiftTo(g,y); |
|||
return y; |
|||
} |
|||
|
|||
// (protected) this % n, n < 2^26
|
|||
function bnpModInt(n) { |
|||
if(n <= 0) return 0; |
|||
var d = this.DV%n, r = (this.s<0)?n-1:0; |
|||
if(this.t > 0) |
|||
if(d == 0) r = this[0]%n; |
|||
else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n; |
|||
return r; |
|||
} |
|||
|
|||
// (public) 1/this % m (HAC 14.61)
|
|||
function bnModInverse(m) { |
|||
var ac = m.isEven(); |
|||
if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO; |
|||
var u = m.clone(), v = this.clone(); |
|||
var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); |
|||
while(u.signum() != 0) { |
|||
while(u.isEven()) { |
|||
u.rShiftTo(1,u); |
|||
if(ac) { |
|||
if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } |
|||
a.rShiftTo(1,a); |
|||
} |
|||
else if(!b.isEven()) b.subTo(m,b); |
|||
b.rShiftTo(1,b); |
|||
} |
|||
while(v.isEven()) { |
|||
v.rShiftTo(1,v); |
|||
if(ac) { |
|||
if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } |
|||
c.rShiftTo(1,c); |
|||
} |
|||
else if(!d.isEven()) d.subTo(m,d); |
|||
d.rShiftTo(1,d); |
|||
} |
|||
if(u.compareTo(v) >= 0) { |
|||
u.subTo(v,u); |
|||
if(ac) a.subTo(c,a); |
|||
b.subTo(d,b); |
|||
} |
|||
else { |
|||
v.subTo(u,v); |
|||
if(ac) c.subTo(a,c); |
|||
d.subTo(b,d); |
|||
} |
|||
} |
|||
if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; |
|||
if(d.compareTo(m) >= 0) return d.subtract(m); |
|||
if(d.signum() < 0) d.addTo(m,d); else return d; |
|||
if(d.signum() < 0) return d.add(m); else return d; |
|||
} |
|||
|
|||
var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; |
|||
var lplim = (1<<26)/lowprimes[lowprimes.length-1]; |
|||
|
|||
// (public) test primality with certainty >= 1-.5^t
|
|||
function bnIsProbablePrime(t) { |
|||
var i, x = this.abs(); |
|||
if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) { |
|||
for(i = 0; i < lowprimes.length; ++i) |
|||
if(x[0] == lowprimes[i]) return true; |
|||
return false; |
|||
} |
|||
if(x.isEven()) return false; |
|||
i = 1; |
|||
while(i < lowprimes.length) { |
|||
var m = lowprimes[i], j = i+1; |
|||
while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; |
|||
m = x.modInt(m); |
|||
while(i < j) if(m%lowprimes[i++] == 0) return false; |
|||
} |
|||
return x.millerRabin(t); |
|||
} |
|||
|
|||
// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
|
|||
function bnpMillerRabin(t) { |
|||
var n1 = this.subtract(BigInteger.ONE); |
|||
var k = n1.getLowestSetBit(); |
|||
if(k <= 0) return false; |
|||
var r = n1.shiftRight(k); |
|||
t = (t+1)>>1; |
|||
if(t > lowprimes.length) t = lowprimes.length; |
|||
var a = nbi(); |
|||
for(var i = 0; i < t; ++i) { |
|||
//Pick bases at random, instead of starting at 2
|
|||
a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]); |
|||
var y = a.modPow(r,this); |
|||
if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { |
|||
var j = 1; |
|||
while(j++ < k && y.compareTo(n1) != 0) { |
|||
y = y.modPowInt(2,this); |
|||
if(y.compareTo(BigInteger.ONE) == 0) return false; |
|||
} |
|||
if(y.compareTo(n1) != 0) return false; |
|||
} |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
// protected
|
|||
BigInteger.prototype.chunkSize = bnpChunkSize; |
|||
BigInteger.prototype.toRadix = bnpToRadix; |
|||
BigInteger.prototype.fromRadix = bnpFromRadix; |
|||
BigInteger.prototype.fromNumber = bnpFromNumber; |
|||
BigInteger.prototype.bitwiseTo = bnpBitwiseTo; |
|||
BigInteger.prototype.changeBit = bnpChangeBit; |
|||
BigInteger.prototype.addTo = bnpAddTo; |
|||
BigInteger.prototype.dMultiply = bnpDMultiply; |
|||
BigInteger.prototype.dAddOffset = bnpDAddOffset; |
|||
BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; |
|||
BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; |
|||
BigInteger.prototype.modInt = bnpModInt; |
|||
BigInteger.prototype.millerRabin = bnpMillerRabin; |
|||
|
|||
// public
|
|||
BigInteger.prototype.clone = bnClone; |
|||
BigInteger.prototype.intValue = bnIntValue; |
|||
BigInteger.prototype.byteValue = bnByteValue; |
|||
BigInteger.prototype.shortValue = bnShortValue; |
|||
BigInteger.prototype.signum = bnSigNum; |
|||
BigInteger.prototype.toByteArray = bnToByteArray; |
|||
BigInteger.prototype.equals = bnEquals; |
|||
BigInteger.prototype.min = bnMin; |
|||
BigInteger.prototype.max = bnMax; |
|||
BigInteger.prototype.and = bnAnd; |
|||
BigInteger.prototype.or = bnOr; |
|||
BigInteger.prototype.xor = bnXor; |
|||
BigInteger.prototype.andNot = bnAndNot; |
|||
BigInteger.prototype.not = bnNot; |
|||
BigInteger.prototype.shiftLeft = bnShiftLeft; |
|||
BigInteger.prototype.shiftRight = bnShiftRight; |
|||
BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; |
|||
BigInteger.prototype.bitCount = bnBitCount; |
|||
BigInteger.prototype.testBit = bnTestBit; |
|||
BigInteger.prototype.setBit = bnSetBit; |
|||
BigInteger.prototype.clearBit = bnClearBit; |
|||
BigInteger.prototype.flipBit = bnFlipBit; |
|||
BigInteger.prototype.add = bnAdd; |
|||
BigInteger.prototype.subtract = bnSubtract; |
|||
BigInteger.prototype.multiply = bnMultiply; |
|||
BigInteger.prototype.divide = bnDivide; |
|||
BigInteger.prototype.remainder = bnRemainder; |
|||
BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder; |
|||
BigInteger.prototype.modPow = bnModPow; |
|||
BigInteger.prototype.modInverse = bnModInverse; |
|||
BigInteger.prototype.pow = bnPow; |
|||
BigInteger.prototype.gcd = bnGCD; |
|||
BigInteger.prototype.isProbablePrime = bnIsProbablePrime; |
|||
|
|||
// JSBN-specific extension
|
|||
BigInteger.prototype.square = bnSquare; |
|||
|
|||
// BigInteger interfaces not implemented in jsbn:
|
|||
|
|||
// BigInteger(int signum, byte[] magnitude)
|
|||
// double doubleValue()
|
|||
// float floatValue()
|
|||
// int hashCode()
|
|||
// long longValue()
|
|||
// static BigInteger valueOf(long val)
|
@ -1,308 +1,182 @@ |
|||
Bitcoin.Wallet = (function () { |
|||
var Script = Bitcoin.Script, |
|||
TransactionIn = Bitcoin.TransactionIn, |
|||
TransactionOut = Bitcoin.TransactionOut; |
|||
var Script = require('./script'); |
|||
var ECKey = require('./eckey').ECKey; |
|||
var conv = require('./convert'); |
|||
var util = require('./util'); |
|||
|
|||
var Wallet = function () { |
|||
// Keychain
|
|||
//
|
|||
// The keychain is stored as a var in this closure to make accidental
|
|||
// serialization less likely.
|
|||
//
|
|||
// Any functions accessing this value therefore have to be defined in
|
|||
// the closure of this constructor.
|
|||
var keys = []; |
|||
|
|||
// Public hashes of our keys
|
|||
this.addressHashes = []; |
|||
|
|||
// Transaction data
|
|||
this.txIndex = {}; |
|||
this.unspentOuts = []; |
|||
|
|||
// Other fields
|
|||
this.addressPointer = 0; |
|||
|
|||
/** |
|||
* Add a key to the keychain. |
|||
* |
|||
* The corresponding public key can be provided as a second parameter. This |
|||
* adds it to the cache in the ECKey object and avoid the need to |
|||
* expensively calculate it later. |
|||
*/ |
|||
this.addKey = function (key, pub) { |
|||
if (!(key instanceof Bitcoin.ECKey)) { |
|||
key = new Bitcoin.ECKey(key); |
|||
} |
|||
keys.push(key); |
|||
|
|||
if (pub) { |
|||
if ("string" === typeof pub) { |
|||
pub = Crypto.util.base64ToBytes(pub); |
|||
} |
|||
key.setPub(pub); |
|||
} |
|||
|
|||
this.addressHashes.push(key.getBitcoinAddress().getHashBase64()); |
|||
}; |
|||
|
|||
/** |
|||
* Add multiple keys at once. |
|||
*/ |
|||
this.addKeys = function (keys, pubs) { |
|||
if ("string" === typeof keys) { |
|||
keys = keys.split(','); |
|||
} |
|||
if ("string" === typeof pubs) { |
|||
pubs = pubs.split(','); |
|||
} |
|||
var i; |
|||
if (Array.isArray(pubs) && keys.length == pubs.length) { |
|||
for (i = 0; i < keys.length; i++) { |
|||
this.addKey(keys[i], pubs[i]); |
|||
} |
|||
} else { |
|||
for (i = 0; i < keys.length; i++) { |
|||
this.addKey(keys[i]); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Get the key chain. |
|||
* |
|||
* Returns an array of base64-encoded private values. |
|||
*/ |
|||
this.getKeys = function () { |
|||
var serializedWallet = []; |
|||
|
|||
for (var i = 0; i < keys.length; i++) { |
|||
serializedWallet.push(keys[i].toString('base64')); |
|||
} |
|||
|
|||
return serializedWallet; |
|||
}; |
|||
|
|||
/** |
|||
* Get the public keys. |
|||
* |
|||
* Returns an array of base64-encoded public keys. |
|||
*/ |
|||
this.getPubKeys = function () { |
|||
var pubs = []; |
|||
|
|||
for (var i = 0; i < keys.length; i++) { |
|||
pubs.push(Crypto.util.bytesToBase64(keys[i].getPub())); |
|||
} |
|||
|
|||
return pubs; |
|||
}; |
|||
|
|||
/** |
|||
* Delete all keys. |
|||
*/ |
|||
this.clear = function () { |
|||
keys = []; |
|||
}; |
|||
|
|||
/** |
|||
* Return the number of keys in this wallet. |
|||
*/ |
|||
this.getLength = function () { |
|||
return keys.length; |
|||
}; |
|||
|
|||
/** |
|||
* Get the addresses for this wallet. |
|||
* |
|||
* Returns an array of Address objects. |
|||
*/ |
|||
this.getAllAddresses = function () { |
|||
var addresses = []; |
|||
for (var i = 0; i < keys.length; i++) { |
|||
addresses.push(keys[i].getBitcoinAddress()); |
|||
} |
|||
return addresses; |
|||
}; |
|||
|
|||
this.getCurAddress = function () { |
|||
if (keys[this.addressPointer]) { |
|||
return keys[this.addressPointer].getBitcoinAddress(); |
|||
} else { |
|||
return null; |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Go to the next address. |
|||
* |
|||
* If there are no more new addresses available, one will be generated |
|||
* automatically. |
|||
*/ |
|||
this.getNextAddress = function () { |
|||
this.addressPointer++; |
|||
if (!keys[this.addressPointer]) { |
|||
this.generateAddress(); |
|||
} |
|||
return keys[this.addressPointer].getBitcoinAddress(); |
|||
}; |
|||
|
|||
/** |
|||
* Sign a hash with a key. |
|||
* |
|||
* This method expects the pubKeyHash as the first parameter and the hash |
|||
* to be signed as the second parameter. |
|||
*/ |
|||
this.signWithKey = function (pubKeyHash, hash) { |
|||
pubKeyHash = Crypto.util.bytesToBase64(pubKeyHash); |
|||
for (var i = 0; i < this.addressHashes.length; i++) { |
|||
if (this.addressHashes[i] == pubKeyHash) { |
|||
return keys[i].sign(hash); |
|||
} |
|||
} |
|||
throw new Error("Missing key for signature"); |
|||
}; |
|||
var BigInteger = require('./jsbn/jsbn'); |
|||
|
|||
/** |
|||
* Retrieve the corresponding pubKey for a pubKeyHash. |
|||
* |
|||
* This function only works if the pubKey in question is part of this |
|||
* wallet. |
|||
*/ |
|||
this.getPubKeyFromHash = function (pubKeyHash) { |
|||
pubKeyHash = Crypto.util.bytesToBase64(pubKeyHash); |
|||
for (var i = 0; i < this.addressHashes.length; i++) { |
|||
if (this.addressHashes[i] == pubKeyHash) { |
|||
return keys[i].getPub(); |
|||
} |
|||
} |
|||
throw new Error("Hash unknown"); |
|||
}; |
|||
}; |
|||
|
|||
Wallet.prototype.generateAddress = function () { |
|||
this.addKey(new Bitcoin.ECKey()); |
|||
}; |
|||
var Transaction = require('./transaction').Transaction; |
|||
var TransactionIn = require('./transaction').TransactionIn; |
|||
var TransactionOut = require('./transaction').TransactionOut; |
|||
var HDWallet = require('./hdwallet.js') |
|||
|
|||
/** |
|||
* Add a transaction to the wallet's processed transaction. |
|||
* |
|||
* This will add a transaction to the wallet, updating its balance and |
|||
* available unspent outputs. |
|||
*/ |
|||
Wallet.prototype.process = function (tx) { |
|||
if (this.txIndex[tx.hash]) return; |
|||
var SecureRandom = require('./jsbn/rng'); |
|||
var rng = new SecureRandom(); |
|||
|
|||
var j; |
|||
var k; |
|||
var hash; |
|||
// Gather outputs
|
|||
for (j = 0; j < tx.outs.length; j++) { |
|||
var txout = new TransactionOut(tx.outs[j]); |
|||
hash = Crypto.util.bytesToBase64(txout.script.simpleOutPubKeyHash()); |
|||
for (k = 0; k < this.addressHashes.length; k++) { |
|||
if (this.addressHashes[k] === hash) { |
|||
this.unspentOuts.push({tx: tx, index: j, out: txout}); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Remove spent outputs
|
|||
for (j = 0; j < tx.ins.length; j++) { |
|||
var txin = new TransactionIn(tx.ins[j]); |
|||
var pubkey = txin.script.simpleInPubKey(); |
|||
hash = Crypto.util.bytesToBase64(Bitcoin.Util.sha256ripe160(pubkey)); |
|||
for (k = 0; k < this.addressHashes.length; k++) { |
|||
if (this.addressHashes[k] === hash) { |
|||
for (var l = 0; l < this.unspentOuts.length; l++) { |
|||
if (txin.outpoint.hash == this.unspentOuts[l].tx.hash && |
|||
txin.outpoint.index == this.unspentOuts[l].index) { |
|||
this.unspentOuts.splice(l, 1); |
|||
} |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Index transaction
|
|||
this.txIndex[tx.hash] = tx; |
|||
}; |
|||
|
|||
Wallet.prototype.getBalance = function () { |
|||
var balance = BigInteger.valueOf(0); |
|||
for (var i = 0; i < this.unspentOuts.length; i++) { |
|||
var txout = this.unspentOuts[i].out; |
|||
balance = balance.add(Bitcoin.Util.valueToBigInt(txout.value)); |
|||
} |
|||
return balance; |
|||
}; |
|||
|
|||
Wallet.prototype.createSend = function (address, sendValue, feeValue) { |
|||
var selectedOuts = []; |
|||
var txValue = sendValue.add(feeValue); |
|||
var availableValue = BigInteger.ZERO; |
|||
var i; |
|||
for (i = 0; i < this.unspentOuts.length; i++) { |
|||
selectedOuts.push(this.unspentOuts[i]); |
|||
availableValue = availableValue.add(Bitcoin.Util.valueToBigInt(this.unspentOuts[i].out.value)); |
|||
|
|||
if (availableValue.compareTo(txValue) >= 0) break; |
|||
} |
|||
var Wallet = function (seed) { |
|||
|
|||
if (availableValue.compareTo(txValue) < 0) { |
|||
throw new Error('Insufficient funds.'); |
|||
} |
|||
|
|||
|
|||
var changeValue = availableValue.subtract(txValue); |
|||
|
|||
var sendTx = new Bitcoin.Transaction(); |
|||
|
|||
for (i = 0; i < selectedOuts.length; i++) { |
|||
sendTx.addInput(selectedOuts[i].tx, selectedOuts[i].index); |
|||
} |
|||
|
|||
sendTx.addOutput(address, sendValue); |
|||
if (changeValue.compareTo(BigInteger.ZERO) > 0) { |
|||
sendTx.addOutput(this.getNextAddress(), changeValue); |
|||
} |
|||
|
|||
var hashType = 1; // SIGHASH_ALL
|
|||
|
|||
for (i = 0; i < sendTx.ins.length; i++) { |
|||
var hash = sendTx.hashTransactionForSignature(selectedOuts[i].out.script, i, hashType); |
|||
var pubKeyHash = selectedOuts[i].out.script.simpleOutPubKeyHash(); |
|||
var signature = this.signWithKey(pubKeyHash, hash); |
|||
|
|||
// Append hash type
|
|||
signature.push(parseInt(hashType, 10)); |
|||
|
|||
sendTx.ins[i].script = Script.createInputScript(signature, this.getPubKeyFromHash(pubKeyHash)); |
|||
} |
|||
|
|||
return sendTx; |
|||
}; |
|||
|
|||
Wallet.prototype.clearTransactions = function () { |
|||
this.txIndex = {}; |
|||
this.unspentOuts = []; |
|||
}; |
|||
|
|||
/** |
|||
* Check to see if a pubKeyHash belongs to this wallet. |
|||
*/ |
|||
Wallet.prototype.hasHash = function (hash) { |
|||
if (Bitcoin.Util.isArray(hash)) hash = Crypto.util.bytesToBase64(hash); |
|||
|
|||
// TODO: Just create an object with base64 hashes as keys for faster lookup
|
|||
for (var k = 0; k < this.addressHashes.length; k++) { |
|||
if (this.addressHashes[k] === hash) return true; |
|||
// Stored in a closure to make accidental serialization less likely
|
|||
var keys = []; |
|||
var masterkey = null; |
|||
var me = this; |
|||
|
|||
// Addresses
|
|||
this.addresses = []; |
|||
|
|||
// Transaction output data
|
|||
this.outputs = {}; |
|||
|
|||
// Make a new master key
|
|||
this.newMasterKey = function(seed) { |
|||
if (!seed) { |
|||
var seedBytes = new Array(32); |
|||
rng.nextBytes(seedBytes); |
|||
seed = conv.bytesToString(seedBytes) |
|||
} |
|||
masterkey = new HDWallet(seed); |
|||
keys = [] |
|||
} |
|||
this.newMasterKey(seed) |
|||
|
|||
// Add a new address
|
|||
this.generateAddress = function() { |
|||
keys.push(masterkey.ckd(keys.length).key) |
|||
this.addresses.push(keys[keys.length-1].getBitcoinAddress().toString()) |
|||
return this.addresses[this.addresses.length - 1] |
|||
} |
|||
|
|||
// Processes a transaction object
|
|||
// If "verified" is true, then we trust the transaction as "final"
|
|||
this.processTx = function(tx, verified) { |
|||
var txhash = conv.bytesToHex(tx.getHash()) |
|||
for (var i = 0; i < tx.outs.length; i++) { |
|||
if (this.addresses.indexOf(tx.outs[i].address.toString()) >= 0) { |
|||
me.outputs[txhash+':'+i] = { |
|||
output: txhash+':'+i, |
|||
value: tx.outs[i].value, |
|||
address: tx.outs[i].address.toString(), |
|||
timestamp: new Date().getTime() / 1000, |
|||
pending: true |
|||
} |
|||
} |
|||
} |
|||
for (var i = 0; i < tx.ins.length; i++) { |
|||
var op = tx.ins[i].outpoint |
|||
var o = me.outputs[op.hash+':'+op.index] |
|||
if (o) { |
|||
o.spend = txhash+':'+i |
|||
o.spendpending = true |
|||
o.timestamp = new Date().getTime() / 1000 |
|||
} |
|||
} |
|||
} |
|||
// Processes an output from an external source of the form
|
|||
// { output: txhash:index, value: integer, address: address }
|
|||
// Excellent compatibility with SX and pybitcointools
|
|||
this.processOutput = function(o) { |
|||
if (!this.outputs[o.output] || this.outputs[o.output].pending) |
|||
this.outputs[o.output] = o; |
|||
} |
|||
|
|||
this.processExistingOutputs = function() { |
|||
var t = new Date().getTime() / 1000 |
|||
for (var o in this.outputs) { |
|||
if (o.pending && t > o.timestamp + 1200) |
|||
delete this.outputs[o] |
|||
if (o.spendpending && t > o.timestamp + 1200) { |
|||
o.spendpending = false |
|||
o.spend = false |
|||
delete o.timestamp |
|||
} |
|||
} |
|||
} |
|||
var peoInterval = setInterval(this.processExistingOutputs, 10000) |
|||
|
|||
this.getUtxoToPay = function(value) { |
|||
var h = [] |
|||
for (var out in this.outputs) h.push(this.outputs[out]) |
|||
var utxo = h.filter(function(x) { return !x.spend }); |
|||
var valuecompare = function(a,b) { return a.value > b.value; } |
|||
var high = utxo.filter(function(o) { return o.value >= value; }) |
|||
.sort(valuecompare); |
|||
if (high.length > 0) return [high[0]]; |
|||
utxo.sort(valuecompare); |
|||
var totalval = 0; |
|||
for (var i = 0; i < utxo.length; i++) { |
|||
totalval += utxo[i].value; |
|||
if (totalval >= value) return utxo.slice(0,i+1); |
|||
} |
|||
throw ("Not enough money to send funds including transaction fee. Have: " |
|||
+ (totalval / 100000000) + ", needed: " + (value / 100000000)); |
|||
} |
|||
|
|||
this.mkSend = function(to, value, fee) { |
|||
var utxo = this.getUtxoToPay(value + fee) |
|||
var sum = utxo.reduce(function(t,o) { return t + o.value },0), |
|||
remainder = sum - value - fee |
|||
if (value < 5430) throw new Error("Amount below dust threshold!") |
|||
var unspentOuts = 0; |
|||
for (var o in this.outputs) { |
|||
if (!this.outputs[o].spend) unspentOuts += 1 |
|||
if (unspentOuts >= 5) return |
|||
} |
|||
var change = this.addresses[this.addresses.length - 1] |
|||
var toOut = { address: to, value: value }, |
|||
changeOut = { address: change, value: remainder } |
|||
halfChangeOut = { address: change, value: Math.floor(remainder/2) }; |
|||
|
|||
var outs = |
|||
remainder < 5430 ? [toOut] |
|||
: remainder < 10860 ? [toOut, changeOut] |
|||
: unspentOuts == 5 ? [toOut, changeOut] |
|||
: [toOut, halfChangeOut, halfChangeOut] |
|||
|
|||
var tx = new Bitcoin.Transaction({ |
|||
ins: utxo.map(function(x) { return x.output }), |
|||
outs: outs |
|||
}) |
|||
this.sign(tx) |
|||
return tx |
|||
} |
|||
|
|||
this.mkSendToOutputs = function(outputs, changeIndex, fee) { |
|||
var value = outputs.reduce(function(t,o) { return t + o.value },0), |
|||
utxo = this.getUtxoToPay(value + fee), |
|||
sum = utxo.reduce(function(t,p) { return t + o.value },0); |
|||
utxo[changeIndex].value += sum - value - fee; |
|||
var tx = new Bitcoin.Transaction({ |
|||
ins: utxo.map(function(x) { return x.output }), |
|||
outs: outputs |
|||
}) |
|||
this.sign(tx) |
|||
return tx |
|||
} |
|||
|
|||
this.sign = function(tx) { |
|||
tx.ins.map(function(inp,i) { |
|||
var inp = inp.outpoint.hash+':'+inp.outpoint.index; |
|||
if (me.outputs[inp]) { |
|||
var address = me.outputs[inp].address, |
|||
ind = me.addresses.indexOf(address); |
|||
if (ind >= 0) { |
|||
var key = keys[ind] |
|||
tx.sign(ind,key) |
|||
} |
|||
} |
|||
}) |
|||
return tx; |
|||
} |
|||
return false; |
|||
}; |
|||
|
|||
return Wallet; |
|||
})(); |
|||
|
|||
this.getMasterKey = function() { return masterkey } |
|||
|
|||
this.getPrivateKey = function(index) { |
|||
if (typeof index == "string") |
|||
return keys.filter(function(i,k){ return addresses[i] == index })[0] |
|||
else |
|||
return keys[index] |
|||
} |
|||
|
|||
this.getPrivateKeys = function() { return keys } |
|||
}; |
|||
|
|||
module.exports = Wallet; |
|||
|
@ -0,0 +1,52 @@ |
|||
/* global describe, it */ |
|||
var assert = require('assert'); |
|||
var Address = require('../src/address.js'); |
|||
|
|||
describe('Address', function() { |
|||
describe('toString', function() { |
|||
it('defaults to base58', function() { |
|||
var addr = '18fN1QTGWmHWCA9r2dyDH6FbMEyc7XHmQQ'; |
|||
assert.equal((new Address(addr)).toString(), addr); |
|||
}) |
|||
}) |
|||
|
|||
describe('validate', function() { |
|||
it('validates known good addresses', function() { |
|||
function validate(addr) { |
|||
assert.ok(Address.validate(addr)); |
|||
} |
|||
|
|||
validate('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'); |
|||
// validate('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', 'prod');
|
|||
validate('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef'); |
|||
// validate('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'testnet');
|
|||
|
|||
validate('12KYrjTdVGjFMtaxERSk3gphreJ5US8aUP'); |
|||
validate('12QeMLzSrB8XH8FvEzPMVoRxVAzTr5XM2y'); |
|||
validate('1oNLrsHnBcR6dpaBpwz3LSwutbUNkNSjs'); |
|||
validate('1SQHtwR5oJRKLfiWQ2APsAd9miUc4k2ez'); |
|||
validate('116CGDLddrZhMrTwhCVJXtXQpxygTT1kHd'); |
|||
|
|||
// p2sh addresses
|
|||
validate('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt'); |
|||
// validate('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'prod');
|
|||
validate('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7'); |
|||
// validate('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'testnet');
|
|||
}) |
|||
|
|||
it('does not validate illegal examples', function() { |
|||
function invalid(addr) { |
|||
assert.ok(!Address.validate(addr)); |
|||
} |
|||
|
|||
invalid(''); |
|||
invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhe'); |
|||
|
|||
// invalid('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', 'testnet');
|
|||
// invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'prod');
|
|||
|
|||
// invalid base58 string
|
|||
invalid('%%@'); |
|||
}) |
|||
}) |
|||
}) |
@ -0,0 +1,22 @@ |
|||
/* global describe, it */ |
|||
var assert = require('assert'); |
|||
var base58 = require('../').base58; |
|||
var conv = require('../').convert; |
|||
|
|||
describe('base58', function() { |
|||
describe('decode', function() { |
|||
it('validates known examples', function() { |
|||
var enc = '5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ'; |
|||
var hex = '800c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d507a5b8d'; |
|||
assert.deepEqual(base58.decode(enc), conv.hexToBytes(hex)); |
|||
}) |
|||
}) |
|||
|
|||
describe('encode', function() { |
|||
it('handles known examples', function() { |
|||
var enc = '5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ'; |
|||
var hex = '800c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d507a5b8d'; |
|||
assert.equal(base58.encode(conv.hexToBytes(hex)), enc); |
|||
}) |
|||
}) |
|||
}) |
@ -0,0 +1,28 @@ |
|||
/* global describe, it */ |
|||
var assert = require('assert'); |
|||
var convert = require('../src/convert.js'); |
|||
|
|||
describe('convert', function() { |
|||
describe('bytesToHex', function() { |
|||
it('handles example 1', function() { |
|||
assert.equal(convert.bytesToHex([0, 1, 2, 255]), '000102ff'); |
|||
}) |
|||
}) |
|||
|
|||
describe('hexToBytes', function() { |
|||
it('handles example 1', function() { |
|||
assert.deepEqual(convert.hexToBytes('000102ff'), [0, 1, 2, 255]); |
|||
}) |
|||
}) |
|||
|
|||
it('converts from bytes to hex and back', function() { |
|||
var bytes = []; |
|||
for (var i=0 ; i<256 ; ++i) { |
|||
bytes.push(i); |
|||
} |
|||
|
|||
var hex = convert.bytesToHex(bytes); |
|||
assert.equal(hex.length, 512); |
|||
assert.deepEqual(convert.hexToBytes(hex), bytes); |
|||
}) |
|||
}) |
@ -0,0 +1,23 @@ |
|||
/* global describe, it */ |
|||
var assert = require('assert'); |
|||
var sec = require('../src/jsbn/sec'); |
|||
var ecdsa = require('../').ecdsa; |
|||
|
|||
var ecparams = sec('secp256k1'); |
|||
|
|||
describe('ecdsa', function() { |
|||
it('handles point ultiplication', function() { |
|||
var G = ecparams.getG(); |
|||
var n = ecparams.getN(); |
|||
|
|||
assert.ok(G.multiply(n).isInfinity(), "Gn is infinite"); |
|||
|
|||
var k = ecdsa.getBigRandom(n); |
|||
var P = G.multiply(k); |
|||
assert.ok(!P.isInfinity(), "kG is not infinite"); |
|||
assert.ok(P.isOnCurve(), "kG on curve"); |
|||
assert.ok(P.multiply(n).isInfinity(), "kGn is infinite"); |
|||
|
|||
assert.ok(P.validate(), "kG validates as a public key"); |
|||
}) |
|||
}) |
@ -0,0 +1,43 @@ |
|||
/* global describe, it */ |
|||
var assert = require('assert'); |
|||
var ECKey = require('../src/eckey.js').ECKey; |
|||
var convert = require('../src/convert.js'); |
|||
var bytesToHex = convert.bytesToHex; |
|||
var hexToBytes = convert.hexToBytes; |
|||
|
|||
describe('ECKey', function() { |
|||
describe('constructor (base58 private)', function() { |
|||
it('parses case 1', function() { |
|||
var priv = '18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725'; |
|||
var pub = '0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b235' + |
|||
'22cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6'; |
|||
var key = new ECKey(hexToBytes(priv)); |
|||
|
|||
assert.equal(bytesToHex(key.getPub()['export']('bytes')), pub); |
|||
assert.equal(key.compressed, false); |
|||
}) |
|||
|
|||
it('parses case 2', function() { |
|||
var priv = '5HwoXVkHoRM8sL2KmNRS217n1g8mPPBomrY7yehCuXC1115WWsh'; |
|||
var pub = '044f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0' + |
|||
'f0b704075871aa385b6b1b8ead809ca67454d9683fcf2ba03456d6fe2c4abe2b07f0fbdbb2f1c1'; |
|||
var addr = '1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a'; |
|||
var key = new ECKey(priv); |
|||
|
|||
assert.equal(key.compressed, false); |
|||
assert.equal(bytesToHex(key.getPub()['export']('bytes')), pub); |
|||
assert.equal(key.getBitcoinAddress().toString(), addr); |
|||
}) |
|||
|
|||
it('parses case 3', function() { |
|||
var priv = 'KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp'; |
|||
var pub = '034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa' |
|||
var addr = '1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9'; |
|||
var key = new ECKey(priv); |
|||
|
|||
assert.equal(key.compressed, true); |
|||
assert.equal(bytesToHex(key.getPub()['export']('bytes')), pub); |
|||
assert.equal(key.getBitcoinAddress().toString(), addr); |
|||
}) |
|||
}) |
|||
}) |
@ -0,0 +1,217 @@ |
|||
/* global describe, it */ |
|||
var HDWallet = require('../src/hdwallet.js') |
|||
, assert = require('assert') |
|||
, convert = require('../src/convert.js') |
|||
|
|||
var b2h = convert.bytesToHex |
|||
|
|||
describe('HDWallet', function() { |
|||
describe('toBase58', function() { |
|||
it('reproduces input', function() { |
|||
var input = 'xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5' |
|||
, output = HDWallet.fromBase58(input).toBase58(false) |
|||
assert.equal(output, input) |
|||
|
|||
input = 'xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334' |
|||
output = HDWallet.fromBase58(input).toBase58(true) |
|||
assert.equal(output, input) |
|||
}) |
|||
|
|||
it('fails with priv=true when theres no private key', function() { |
|||
var hd = HDWallet.fromBase58('xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon') |
|||
try { |
|||
hd.toBase58(true) |
|||
} catch(e) { |
|||
assert(e.message.match(/private key/i)) |
|||
return |
|||
} |
|||
assert.fail() |
|||
}) |
|||
}) |
|||
|
|||
describe('ctor', function() { |
|||
it('creates from seed', function() { |
|||
var seed = 'crazy horse battery staple' |
|||
, hd = new HDWallet(seed) |
|||
|
|||
assert(hd.priv) |
|||
assert(hd.pub) |
|||
}) |
|||
}) |
|||
|
|||
describe('Test vectors', function() { |
|||
it('Test vector 1', function() { |
|||
var hd = HDWallet.fromMasterHex('000102030405060708090a0b0c0d0e0f') |
|||
|
|||
// m
|
|||
assert.equal(b2h(hd.getIdentifier()), '3442193e1bb70916e914552172cd4e2dbc9df811') |
|||
assert.equal(b2h(hd.getFingerprint()), '3442193e') |
|||
assert.equal(hd.getBitcoinAddress().toString(), '15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma') |
|||
assert.equal(hd.priv.toHex(), 'e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b3501') |
|||
assert.equal(hd.priv.toWif(), 'L52XzL2cMkHxqxBXRyEpnPQZGUs3uKiL3R11XbAdHigRzDozKZeW') |
|||
assert.equal(hd.pub.toHex(), '0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2') |
|||
assert.equal(b2h(hd.chaincode), '873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508') |
|||
assert.equal(hd.toHex(false), '0488b21e000000000000000000873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d5080339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2') |
|||
assert.equal(hd.toHex(true), '0488ade4000000000000000000873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d50800e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35') |
|||
assert.equal(hd.toBase58(false), 'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8') |
|||
assert.equal(hd.toBase58(true), 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi') |
|||
|
|||
// m/0'
|
|||
hd = hd.derivePrivate(0) |
|||
assert.equal(b2h(hd.getIdentifier()), '5c1bd648ed23aa5fd50ba52b2457c11e9e80a6a7') |
|||
assert.equal(b2h(hd.getFingerprint()), '5c1bd648') |
|||
assert.equal(hd.getBitcoinAddress().toString(), '19Q2WoS5hSS6T8GjhK8KZLMgmWaq4neXrh') |
|||
assert.equal(hd.priv.toHex().slice(0, 64), 'edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea') |
|||
assert.equal(hd.priv.toWif(), 'L5BmPijJjrKbiUfG4zbiFKNqkvuJ8usooJmzuD7Z8dkRoTThYnAT') |
|||
assert.equal(hd.pub.toHex(), '035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56') |
|||
assert.equal(b2h(hd.chaincode), '47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141') |
|||
assert.equal(hd.toHex(false), '0488b21e013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56') |
|||
assert.equal(hd.toHex(true), '0488ade4013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae623614100edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea') |
|||
assert.equal(hd.toBase58(false), 'xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw') |
|||
assert.equal(hd.toBase58(true), 'xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7') |
|||
|
|||
// m/0'/1
|
|||
hd = hd.derive(1) |
|||
assert.equal(b2h(hd.getIdentifier()), 'bef5a2f9a56a94aab12459f72ad9cf8cf19c7bbe') |
|||
assert.equal(b2h(hd.getFingerprint()), 'bef5a2f9') |
|||
assert.equal(hd.getBitcoinAddress().toString(), '1JQheacLPdM5ySCkrZkV66G2ApAXe1mqLj') |
|||
assert.equal(hd.priv.toHex().slice(0, 64), '3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368') |
|||
assert.equal(hd.priv.toWif(), 'KyFAjQ5rgrKvhXvNMtFB5PCSKUYD1yyPEe3xr3T34TZSUHycXtMM') |
|||
assert.equal(hd.pub.toHex(), '03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c') |
|||
assert.equal(b2h(hd.chaincode), '2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19') |
|||
assert.equal(hd.toHex(false), '0488b21e025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c1903501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c') |
|||
assert.equal(hd.toHex(true), '0488ade4025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19003c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368') |
|||
assert.equal(hd.toBase58(false), 'xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ') |
|||
assert.equal(hd.toBase58(true), 'xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs') |
|||
|
|||
// m/0'/1/2'
|
|||
hd = hd.derivePrivate(2) |
|||
assert.equal(b2h(hd.getIdentifier()), 'ee7ab90cde56a8c0e2bb086ac49748b8db9dce72') |
|||
assert.equal(b2h(hd.getFingerprint()), 'ee7ab90c') |
|||
assert.equal(hd.getBitcoinAddress().toString(), '1NjxqbA9aZWnh17q1UW3rB4EPu79wDXj7x') |
|||
assert.equal(hd.priv.toHex().slice(0, 64), 'cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca') |
|||
assert.equal(hd.priv.toWif(), 'L43t3od1Gh7Lj55Bzjj1xDAgJDcL7YFo2nEcNaMGiyRZS1CidBVU') |
|||
assert.equal(hd.pub.toHex(), '0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2') |
|||
assert.equal(b2h(hd.chaincode), '04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f') |
|||
assert.equal(hd.toHex(false), '0488b21e03bef5a2f98000000204466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2') |
|||
assert.equal(hd.toHex(true), '0488ade403bef5a2f98000000204466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f00cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca') |
|||
assert.equal(hd.toBase58(false), 'xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5') |
|||
assert.equal(hd.toBase58(true), 'xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM') |
|||
|
|||
// m/0'/1/2'/2
|
|||
hd = hd.derive(2) |
|||
assert.equal(b2h(hd.getIdentifier()), 'd880d7d893848509a62d8fb74e32148dac68412f') |
|||
assert.equal(b2h(hd.getFingerprint()), 'd880d7d8') |
|||
assert.equal(hd.getBitcoinAddress().toString(), '1LjmJcdPnDHhNTUgrWyhLGnRDKxQjoxAgt') |
|||
assert.equal(hd.priv.toHex().slice(0, 64), '0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4') |
|||
assert.equal(hd.priv.toWif(), 'KwjQsVuMjbCP2Zmr3VaFaStav7NvevwjvvkqrWd5Qmh1XVnCteBR') |
|||
assert.equal(hd.pub.toHex(), '02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29') |
|||
assert.equal(b2h(hd.chaincode), 'cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd') |
|||
assert.equal(hd.toHex(false), '0488b21e04ee7ab90c00000002cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29') |
|||
assert.equal(hd.toHex(true), '0488ade404ee7ab90c00000002cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd000f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4') |
|||
assert.equal(hd.toBase58(false), 'xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV') |
|||
assert.equal(hd.toBase58(true), 'xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334') |
|||
|
|||
// m/0'/1/2'/2/1000000000
|
|||
hd = hd.derive(1000000000) |
|||
assert.equal(b2h(hd.getIdentifier()), 'd69aa102255fed74378278c7812701ea641fdf32') |
|||
assert.equal(b2h(hd.getFingerprint()), 'd69aa102') |
|||
assert.equal(hd.getBitcoinAddress().toString(), '1LZiqrop2HGR4qrH1ULZPyBpU6AUP49Uam') |
|||
assert.equal(hd.priv.toHex().slice(0, 64), '471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8') |
|||
assert.equal(hd.priv.toWif(), 'Kybw8izYevo5xMh1TK7aUr7jHFCxXS1zv8p3oqFz3o2zFbhRXHYs') |
|||
assert.equal(hd.pub.toHex(), '022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011') |
|||
assert.equal(b2h(hd.chaincode), 'c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e') |
|||
assert.equal(hd.toHex(false), '0488b21e05d880d7d83b9aca00c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011') |
|||
assert.equal(hd.toHex(true), '0488ade405d880d7d83b9aca00c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e00471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8') |
|||
assert.equal(hd.toBase58(false), 'xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy') |
|||
assert.equal(hd.toBase58(true), 'xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76') |
|||
}) |
|||
|
|||
it('Test vector 2', function() { |
|||
var hd = HDWallet.fromMasterHex('fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542') |
|||
|
|||
// m
|
|||
assert.equal(b2h(hd.getIdentifier()), 'bd16bee53961a47d6ad888e29545434a89bdfe95') |
|||
assert.equal(b2h(hd.getFingerprint()), 'bd16bee5') |
|||
assert.equal(hd.getBitcoinAddress().toString(), '1JEoxevbLLG8cVqeoGKQiAwoWbNYSUyYjg') |
|||
assert.equal(hd.priv.toHex().slice(0, 64), '4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e') |
|||
assert.equal(hd.priv.toWif(), 'KyjXhyHF9wTphBkfpxjL8hkDXDUSbE3tKANT94kXSyh6vn6nKaoy') |
|||
assert.equal(hd.pub.toHex(), '03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7') |
|||
assert.equal(b2h(hd.chaincode), '60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689') |
|||
assert.equal(hd.toHex(false), '0488b21e00000000000000000060499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd968903cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7') |
|||
assert.equal(hd.toHex(true), '0488ade400000000000000000060499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689004b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e') |
|||
assert.equal(hd.toBase58(false), 'xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB') |
|||
assert.equal(hd.toBase58(true), 'xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U') |
|||
|
|||
// m/0
|
|||
hd = hd.derive(0) |
|||
assert.equal(b2h(hd.getIdentifier()), '5a61ff8eb7aaca3010db97ebda76121610b78096') |
|||
assert.equal(b2h(hd.getFingerprint()), '5a61ff8e') |
|||
assert.equal(hd.getBitcoinAddress().toString(), '19EuDJdgfRkwCmRzbzVBHZWQG9QNWhftbZ') |
|||
assert.equal(hd.priv.toHex().slice(0, 64), 'abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e') |
|||
assert.equal(hd.priv.toWif(), 'L2ysLrR6KMSAtx7uPqmYpoTeiRzydXBattRXjXz5GDFPrdfPzKbj') |
|||
assert.equal(hd.pub.toHex(), '02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea') |
|||
assert.equal(b2h(hd.chaincode), 'f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c') |
|||
assert.equal(hd.toHex(false), '0488b21e01bd16bee500000000f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea') |
|||
assert.equal(hd.toHex(true), '0488ade401bd16bee500000000f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c00abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e') |
|||
assert.equal(hd.toBase58(false), 'xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH') |
|||
assert.equal(hd.toBase58(true), 'xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt') |
|||
|
|||
// m/0/2147483647'
|
|||
hd = hd.derivePrivate(2147483647) |
|||
assert.equal(b2h(hd.getIdentifier()), 'd8ab493736da02f11ed682f88339e720fb0379d1') |
|||
assert.equal(b2h(hd.getFingerprint()), 'd8ab4937') |
|||
assert.equal(hd.getBitcoinAddress().toString(), '1Lke9bXGhn5VPrBuXgN12uGUphrttUErmk') |
|||
assert.equal(hd.priv.toHex().slice(0, 64), '877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93') |
|||
assert.equal(hd.priv.toWif(), 'L1m5VpbXmMp57P3knskwhoMTLdhAAaXiHvnGLMribbfwzVRpz2Sr') |
|||
assert.equal(hd.pub.toHex(), '03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b') |
|||
assert.equal(b2h(hd.chaincode), 'be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9') |
|||
assert.equal(hd.toHex(false), '0488b21e025a61ff8effffffffbe17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d903c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b') |
|||
assert.equal(hd.toHex(true), '0488ade4025a61ff8effffffffbe17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d900877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93') |
|||
assert.equal(hd.toBase58(false), 'xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a') |
|||
assert.equal(hd.toBase58(true), 'xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9') |
|||
|
|||
// m/0/2147483647'/1
|
|||
hd = hd.derive(1) |
|||
assert.equal(b2h(hd.getIdentifier()), '78412e3a2296a40de124307b6485bd19833e2e34') |
|||
assert.equal(b2h(hd.getFingerprint()), '78412e3a') |
|||
assert.equal(hd.getBitcoinAddress().toString(), '1BxrAr2pHpeBheusmd6fHDP2tSLAUa3qsW') |
|||
assert.equal(hd.priv.toHex().slice(0, 64), '704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7') |
|||
assert.equal(hd.priv.toWif(), 'KzyzXnznxSv249b4KuNkBwowaN3akiNeEHy5FWoPCJpStZbEKXN2') |
|||
assert.equal(hd.pub.toHex(), '03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9') |
|||
assert.equal(b2h(hd.chaincode), 'f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb') |
|||
assert.equal(hd.toHex(false), '0488b21e03d8ab493700000001f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9') |
|||
assert.equal(hd.toHex(true), '0488ade403d8ab493700000001f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb00704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7') |
|||
assert.equal(hd.toBase58(false), 'xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon') |
|||
assert.equal(hd.toBase58(true), 'xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef') |
|||
|
|||
// m/0/2147483647'/1/2147483646'
|
|||
hd = hd.derivePrivate(2147483646) |
|||
assert.equal(b2h(hd.getIdentifier()), '31a507b815593dfc51ffc7245ae7e5aee304246e') |
|||
assert.equal(b2h(hd.getFingerprint()), '31a507b8') |
|||
assert.equal(hd.getBitcoinAddress().toString(), '15XVotxCAV7sRx1PSCkQNsGw3W9jT9A94R') |
|||
assert.equal(hd.priv.toHex().slice(0, 64), 'f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d') |
|||
assert.equal(hd.priv.toWif(), 'L5KhaMvPYRW1ZoFmRjUtxxPypQ94m6BcDrPhqArhggdaTbbAFJEF') |
|||
assert.equal(hd.pub.toHex(), '02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0') |
|||
assert.equal(b2h(hd.chaincode), '637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29') |
|||
assert.equal(hd.toHex(false), '0488b21e0478412e3afffffffe637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e2902d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0') |
|||
assert.equal(hd.toHex(true), '0488ade40478412e3afffffffe637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e2900f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d') |
|||
assert.equal(hd.toBase58(false), 'xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL') |
|||
assert.equal(hd.toBase58(true), 'xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc') |
|||
|
|||
// Chain m/0/2147483647'/1/2147483646'/2
|
|||
hd = hd.derive(2) |
|||
assert.equal(b2h(hd.getIdentifier()), '26132fdbe7bf89cbc64cf8dafa3f9f88b8666220') |
|||
assert.equal(b2h(hd.getFingerprint()), '26132fdb') |
|||
assert.equal(hd.getBitcoinAddress().toString(), '14UKfRV9ZPUp6ZC9PLhqbRtxdihW9em3xt') |
|||
assert.equal(hd.priv.toHex().slice(0, 64), 'bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23') |
|||
assert.equal(hd.priv.toWif(), 'L3WAYNAZPxx1fr7KCz7GN9nD5qMBnNiqEJNJMU1z9MMaannAt4aK') |
|||
assert.equal(hd.pub.toHex(), '024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c') |
|||
assert.equal(b2h(hd.chaincode), '9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271') |
|||
assert.equal(hd.toHex(false), '0488b21e0531a507b8000000029452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c') |
|||
assert.equal(hd.toHex(true), '0488ade40531a507b8000000029452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed27100bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23') |
|||
assert.equal(hd.toBase58(false), 'xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt') |
|||
assert.equal(hd.toBase58(true), 'xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j') |
|||
}) |
|||
}) |
|||
}) |
@ -1,36 +0,0 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<title>BitcoinJS-lib Test Suite</title> |
|||
<link rel="stylesheet" href="../vendor/qunit/qunit.css" type="text/css" media="screen"> |
|||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script> |
|||
<script type="text/javascript" src="../vendor/qunit/qunit.js"></script> |
|||
<script type="text/javascript" src="../src/crypto-js/crypto.js"></script> |
|||
<script type="text/javascript" src="../src/crypto-js/sha256.js"></script> |
|||
<script type="text/javascript" src="../src/jsbn/prng4.js"></script> |
|||
<script type="text/javascript" src="../src/jsbn/rng.js"></script> |
|||
<script type="text/javascript" src="../src/jsbn/jsbn.js"></script> |
|||
<script type="text/javascript" src="../src/jsbn/jsbn2.js"></script> |
|||
|
|||
<script type="text/javascript" src="../src/jsbn/ec.js"></script> |
|||
<script type="text/javascript" src="../src/jsbn/sec.js"></script> |
|||
<script type="text/javascript" src="../src/events/eventemitter.js"></script> |
|||
<script type="text/javascript" src="../src/bitcoin.js"></script> |
|||
<script type="text/javascript" src="../src/util.js"></script> |
|||
<script type="text/javascript" src="../src/base58.js"></script> |
|||
|
|||
<script type="text/javascript" src="../src/address.js"></script> |
|||
<script type="text/javascript" src="../src/ecdsa.js"></script> |
|||
<script type="text/javascript" src="../src/eckey.js"></script> |
|||
<script type="text/javascript" src="../src/paillier.js"></script> |
|||
<script type="text/javascript" src="test.js"></script> |
|||
</head> |
|||
<body> |
|||
<h1 id="qunit-header">BitcoinJS-lib Test Suite</h1> |
|||
<h2 id="qunit-banner"></h2> |
|||
<div id="qunit-testrunner-toolbar"></div> |
|||
<h2 id="qunit-userAgent"></h2> |
|||
<ol id="qunit-tests"></ol> |
|||
<div id="qunit-fixture"></div> |
|||
</body> |
|||
</html> |
@ -0,0 +1,28 @@ |
|||
/* global describe, it */ |
|||
var assert = require('assert'); |
|||
var BigInteger = require('../src/jsbn/jsbn.js') |
|||
var bytesToHex = require('../src/convert.js').bytesToHex; |
|||
|
|||
describe('BigInteger', function() { |
|||
describe('toByteArraySigned', function() { |
|||
it('handles examples', function() { |
|||
function hex(num) { |
|||
var bytes = BigInteger.valueOf(num).toByteArraySigned(); |
|||
var h = bytesToHex(bytes); |
|||
return '0x' + h; |
|||
} |
|||
|
|||
assert.equal(hex( 0), '0x'); |
|||
assert.equal(hex( 1), '0x01'); |
|||
assert.equal(hex(-1), '0x81'); |
|||
assert.equal(hex( 127), '0x7f'); |
|||
assert.equal(hex(-127), '0xff'); |
|||
assert.equal(hex( 255), '0x00ff'); |
|||
assert.equal(hex(-255), '0x80ff'); |
|||
assert.equal(hex( 16300), '0x3fac'); |
|||
assert.equal(hex(-16300), '0xbfac'); |
|||
assert.equal(hex( 62300), '0x00f35c'); |
|||
assert.equal(hex(-62300), '0x80f35c'); |
|||
}) |
|||
}) |
|||
}) |
@ -0,0 +1,34 @@ |
|||
/* global describe, it */ |
|||
var assert = require('assert'); |
|||
var Message = require('../src/message.js'); |
|||
var ECKey = require('../src/eckey.js').ECKey; |
|||
var hexToBytes = require('../src/convert.js').hexToBytes; |
|||
|
|||
var priv = '18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725'; |
|||
var addr = '16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM'; |
|||
var msg = 'foobar'; |
|||
|
|||
describe('Message', function() { |
|||
describe('verify', function() { |
|||
it('passes case 1', function() { |
|||
var key = new ECKey(hexToBytes(priv)); |
|||
assert.equal(key.getBitcoinAddress().toString(), addr); |
|||
|
|||
var sig = Message.signMessage(key, msg); |
|||
assert.ok(Message.verifyMessage(addr, sig, msg)); |
|||
|
|||
// wrong message
|
|||
assert.ok(!Message.verifyMessage(addr, sig, 'not foobar')); |
|||
|
|||
// wrong address
|
|||
assert.ok(!Message.verifyMessage('1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a', sig, msg)); |
|||
}) |
|||
|
|||
it('passes case 2', function() { |
|||
var priv = '5HwoXVkHoRM8sL2KmNRS217n1g8mPPBomrY7yehCuXC1115WWsh'; |
|||
var key = new ECKey(hexToBytes(priv)); |
|||
var sig = Message.signMessage(key, msg); |
|||
assert.ok(!Message.verifyMessage(addr, sig, msg)); |
|||
}) |
|||
}) |
|||
}) |
@ -0,0 +1,68 @@ |
|||
/* global it */ |
|||
var assert = require('assert'); |
|||
var bitcoinjs = require('../'); |
|||
var sec = require('../src/jsbn/sec'); |
|||
var BigInteger = require('../src/jsbn/jsbn.js'); |
|||
var Crypto = require('../src/crypto-js/crypto.js'); |
|||
|
|||
var SecureRandom = require('../src/jsbn/rng'); |
|||
var rng = new SecureRandom(); |
|||
|
|||
var ecparams = sec('secp256k1'); |
|||
var ECPointFp = bitcoinjs.ECPointFp; |
|||
|
|||
it('Keys & Key Management', function () { |
|||
var p1 = bitcoinjs.Key().getPub()['export']('bytes'); |
|||
assert.equal(p1.length, 65); |
|||
|
|||
var p1_q = ECPointFp.decodeFrom(ecparams.getCurve(), p1); |
|||
assert.ok(p1_q); |
|||
assert.ok(p1_q.validate()); |
|||
|
|||
var p2 = bitcoinjs.convert.hexToBytes( |
|||
'0486f356006a38b847bedec1bf47013776925d939d5a35a97a4d1263e550c7f1a' + |
|||
'b5aba44ab74d22892097a0e851addf07ba97e33416df5affaceeb35d5607cd23c'); |
|||
|
|||
var p2_q = ECPointFp.decodeFrom(ecparams.getCurve(), p2); |
|||
assert.ok(p2_q); |
|||
assert.ok(p2_q.validate()); |
|||
}); |
|||
|
|||
it('Signing and Verifying', function () { |
|||
var s1 = bitcoinjs.Key(); |
|||
var sig_a = s1.sign(BigInteger.ZERO); |
|||
assert.ok(sig_a, 'Sign null'); |
|||
|
|||
assert.ok(s1.verify(BigInteger.ZERO, sig_a)); |
|||
|
|||
var message = new BigInteger(1024, rng).toByteArrayUnsigned(); |
|||
var hash = Crypto.SHA256(message, { |
|||
asBytes: true |
|||
}); |
|||
var sig_b = s1.sign(hash); |
|||
assert.ok(sig_b, 'Sign random string'); |
|||
assert.ok(s1.verify(hash, sig_b)); |
|||
|
|||
var message2 = bitcoinjs.convert.hexToBytes( |
|||
'12dce2c169986b3346827ffb2305cf393984627f5f9722a1b1368e933c8d' + |
|||
'd296653fbe5d7ac031c4962ad0eb1c4298c3b91d244e1116b4a76a130c13' + |
|||
'1e7aec7fa70184a71a2e66797052831511b93c6e8d72ae58a1980eaacb66' + |
|||
'8a33f50d7cefb96a5dab897b5efcb99cbafb0d777cb83fc9b2115b69c0fa' + |
|||
'3d82507b932b84e4'); |
|||
|
|||
var hash2 = Crypto.SHA256(message2, { |
|||
asBytes: true |
|||
}); |
|||
|
|||
var sig_c = bitcoinjs.convert.hexToBytes( |
|||
'3044022038d9b8dd5c9fbf330565c1f51d72a59ba869aeb2c2001be959d3' + |
|||
'79e861ec71960220a73945f32cf90d03127d2c3410d16cee120fa1a4b4c3' + |
|||
'f273ab082801a95506c4'); |
|||
|
|||
var s2 = bitcoinjs.convert.hexToBytes( |
|||
'045a1594316e433fb91f35ef4874610d22177c3f1a1060f6c1e70a609d51' + |
|||
'b20be5795cd2a5eae0d6b872ba42db95e9afaeea3fbb89e98099575b6828' + |
|||
'609a978528'); |
|||
|
|||
assert.ok(bitcoinjs.ecdsa.verify(hash2, sig_c, s2), 'Verify constant signature'); |
|||
}); |
@ -0,0 +1 @@ |
|||
--ui qunit |
@ -1,112 +0,0 @@ |
|||
//
|
|||
// Testing elliptic curve math
|
|||
// -----------------------------------------------------------------------------
|
|||
module("ec"); |
|||
|
|||
var ecparams = getSECCurveByName("secp256k1"); |
|||
var rng = new SecureRandom(); |
|||
|
|||
test("Classes", function () { |
|||
expect(3); |
|||
ok(ECPointFp, "ECPointFp"); |
|||
ok(ECFieldElementFp, "ECFieldElementFp"); |
|||
ok(ECCurveFp, "ECCurveFp"); |
|||
}); |
|||
|
|||
test("Point multiplication", function () { |
|||
expect(5); |
|||
|
|||
var G = ecparams.getG(); |
|||
var n = ecparams.getN(); |
|||
|
|||
ok(G.multiply(n).isInfinity(), "Gn is infinite"); |
|||
|
|||
var k = Bitcoin.ECDSA.getBigRandom(n); |
|||
var P = G.multiply(k); |
|||
ok(!P.isInfinity(), "kG is not infinite"); |
|||
ok(P.isOnCurve(), "kG on curve"); |
|||
ok(P.multiply(n).isInfinity(), "kGn is infinite"); |
|||
|
|||
ok(P.validate(), "kG validates as a public key"); |
|||
}); |
|||
|
|||
|
|||
//
|
|||
// Testing ECDSA
|
|||
// -----------------------------------------------------------------------------
|
|||
module("ecdsa"); |
|||
|
|||
test("Classes", function () { |
|||
expect(2); |
|||
ok(Bitcoin.ECDSA, "Bitcoin.ECDSA"); |
|||
ok(Bitcoin.ECKey, "Bitcoin.ECKey"); |
|||
}); |
|||
|
|||
test("Keys & Key Management", function () { |
|||
expect(5); |
|||
|
|||
var s1 = new Bitcoin.ECKey(); |
|||
var p1 = s1.getPub(); |
|||
equals(p1.length, 65, "Public key is correct length"); |
|||
|
|||
var p1_q = ECPointFp.decodeFrom(ecparams.getCurve(), p1); |
|||
ok(p1_q, "Decode point from generated bytestring"); |
|||
ok(p1_q.validate(), "Is a valid public point"); |
|||
|
|||
var p2 = Crypto.util.hexToBytes( |
|||
"0486f356006a38b847bedec1bf47013776925d939d5a35a97a4d1263e550c7f1a" + |
|||
"b5aba44ab74d22892097a0e851addf07ba97e33416df5affaceeb35d5607cd23c" |
|||
); |
|||
var p2_q = ECPointFp.decodeFrom(ecparams.getCurve(), p2); |
|||
ok(p2_q, "Decode point from constant"); |
|||
ok(p2_q.validate(), "Is a valid public point"); |
|||
}); |
|||
|
|||
test("Signing and Verifying", function () { |
|||
expect(7); |
|||
|
|||
var s1 = new Bitcoin.ECKey(); |
|||
var sig_a = s1.sign(BigInteger.ZERO); |
|||
ok(sig_a, "Sign null"); |
|||
equals(sig_a.length, 70, "Signature is correct length"); |
|||
ok(s1.verify(BigInteger.ZERO, sig_a)); |
|||
|
|||
var message = new BigInteger(1024, rng).toByteArrayUnsigned(); |
|||
var hash = Crypto.SHA256(message, {asBytes: true}); |
|||
var sig_b = s1.sign(hash); |
|||
ok(sig_b, "Sign random string"); |
|||
equals(sig_b.length, 70, "Signature is correct length"); |
|||
ok(s1.verify(hash, sig_b)); |
|||
|
|||
var message2 = Crypto.util.hexToBytes( |
|||
"12dce2c169986b3346827ffb2305cf393984627f5f9722a1b1368e933c8d" + |
|||
"d296653fbe5d7ac031c4962ad0eb1c4298c3b91d244e1116b4a76a130c13" + |
|||
"1e7aec7fa70184a71a2e66797052831511b93c6e8d72ae58a1980eaacb66" + |
|||
"8a33f50d7cefb96a5dab897b5efcb99cbafb0d777cb83fc9b2115b69c0fa" + |
|||
"3d82507b932b84e4" |
|||
); |
|||
var hash2 = Crypto.SHA256(message2, {asBytes: true}); |
|||
var sig_c = Crypto.util.hexToBytes( |
|||
"3044022038d9b8dd5c9fbf330565c1f51d72a59ba869aeb2c2001be959d3" + |
|||
"79e861ec71960220a73945f32cf90d03127d2c3410d16cee120fa1a4b4c3" + |
|||
"f273ab082801a95506c4" |
|||
); |
|||
var s2 = Crypto.util.hexToBytes( |
|||
"045a1594316e433fb91f35ef4874610d22177c3f1a1060f6c1e70a609d51" + |
|||
"b20be5795cd2a5eae0d6b872ba42db95e9afaeea3fbb89e98099575b6828" + |
|||
"609a978528" |
|||
); |
|||
ok(Bitcoin.ECDSA.verify(hash2, sig_c, s2), "Verify constant signature"); |
|||
}); |
|||
|
|||
//
|
|||
// Testing Paillier
|
|||
// -----------------------------------------------------------------------------
|
|||
module("paillier"); |
|||
|
|||
test("Classes", function () { |
|||
expect(3); |
|||
ok(Bitcoin.Paillier, "Bitcoin.Paillier"); |
|||
ok(Bitcoin.Paillier.PublicKey, "Bitcoin.Paillier.PublicKey"); |
|||
ok(Bitcoin.Paillier.PrivateKey, "Bitcoin.Paillier.PrivateKey"); |
|||
}); |
@ -1,226 +0,0 @@ |
|||
/** |
|||
* QUnit - A JavaScript Unit Testing Framework |
|||
* |
|||
* http://docs.jquery.com/QUnit |
|||
* |
|||
* Copyright (c) 2011 John Resig, Jörn Zaefferer |
|||
* Dual licensed under the MIT (MIT-LICENSE.txt) |
|||
* or GPL (GPL-LICENSE.txt) licenses. |
|||
*/ |
|||
|
|||
/** Font Family and Sizes */ |
|||
|
|||
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { |
|||
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; |
|||
} |
|||
|
|||
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } |
|||
#qunit-tests { font-size: smaller; } |
|||
|
|||
|
|||
/** Resets */ |
|||
|
|||
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { |
|||
margin: 0; |
|||
padding: 0; |
|||
} |
|||
|
|||
|
|||
/** Header */ |
|||
|
|||
#qunit-header { |
|||
padding: 0.5em 0 0.5em 1em; |
|||
|
|||
color: #8699a4; |
|||
background-color: #0d3349; |
|||
|
|||
font-size: 1.5em; |
|||
line-height: 1em; |
|||
font-weight: normal; |
|||
|
|||
border-radius: 15px 15px 0 0; |
|||
-moz-border-radius: 15px 15px 0 0; |
|||
-webkit-border-top-right-radius: 15px; |
|||
-webkit-border-top-left-radius: 15px; |
|||
} |
|||
|
|||
#qunit-header a { |
|||
text-decoration: none; |
|||
color: #c2ccd1; |
|||
} |
|||
|
|||
#qunit-header a:hover, |
|||
#qunit-header a:focus { |
|||
color: #fff; |
|||
} |
|||
|
|||
#qunit-banner { |
|||
height: 5px; |
|||
} |
|||
|
|||
#qunit-testrunner-toolbar { |
|||
padding: 0.5em 0 0.5em 2em; |
|||
color: #5E740B; |
|||
background-color: #eee; |
|||
} |
|||
|
|||
#qunit-userAgent { |
|||
padding: 0.5em 0 0.5em 2.5em; |
|||
background-color: #2b81af; |
|||
color: #fff; |
|||
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; |
|||
} |
|||
|
|||
|
|||
/** Tests: Pass/Fail */ |
|||
|
|||
#qunit-tests { |
|||
list-style-position: inside; |
|||
} |
|||
|
|||
#qunit-tests li { |
|||
padding: 0.4em 0.5em 0.4em 2.5em; |
|||
border-bottom: 1px solid #fff; |
|||
list-style-position: inside; |
|||
} |
|||
|
|||
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { |
|||
display: none; |
|||
} |
|||
|
|||
#qunit-tests li strong { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
#qunit-tests li a { |
|||
padding: 0.5em; |
|||
color: #c2ccd1; |
|||
text-decoration: none; |
|||
} |
|||
#qunit-tests li a:hover, |
|||
#qunit-tests li a:focus { |
|||
color: #000; |
|||
} |
|||
|
|||
#qunit-tests ol { |
|||
margin-top: 0.5em; |
|||
padding: 0.5em; |
|||
|
|||
background-color: #fff; |
|||
|
|||
border-radius: 15px; |
|||
-moz-border-radius: 15px; |
|||
-webkit-border-radius: 15px; |
|||
|
|||
box-shadow: inset 0px 2px 13px #999; |
|||
-moz-box-shadow: inset 0px 2px 13px #999; |
|||
-webkit-box-shadow: inset 0px 2px 13px #999; |
|||
} |
|||
|
|||
#qunit-tests table { |
|||
border-collapse: collapse; |
|||
margin-top: .2em; |
|||
} |
|||
|
|||
#qunit-tests th { |
|||
text-align: right; |
|||
vertical-align: top; |
|||
padding: 0 .5em 0 0; |
|||
} |
|||
|
|||
#qunit-tests td { |
|||
vertical-align: top; |
|||
} |
|||
|
|||
#qunit-tests pre { |
|||
margin: 0; |
|||
white-space: pre-wrap; |
|||
word-wrap: break-word; |
|||
} |
|||
|
|||
#qunit-tests del { |
|||
background-color: #e0f2be; |
|||
color: #374e0c; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
#qunit-tests ins { |
|||
background-color: #ffcaca; |
|||
color: #500; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
/*** Test Counts */ |
|||
|
|||
#qunit-tests b.counts { color: black; } |
|||
#qunit-tests b.passed { color: #5E740B; } |
|||
#qunit-tests b.failed { color: #710909; } |
|||
|
|||
#qunit-tests li li { |
|||
margin: 0.5em; |
|||
padding: 0.4em 0.5em 0.4em 0.5em; |
|||
background-color: #fff; |
|||
border-bottom: none; |
|||
list-style-position: inside; |
|||
} |
|||
|
|||
/*** Passing Styles */ |
|||
|
|||
#qunit-tests li li.pass { |
|||
color: #5E740B; |
|||
background-color: #fff; |
|||
border-left: 26px solid #C6E746; |
|||
} |
|||
|
|||
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } |
|||
#qunit-tests .pass .test-name { color: #366097; } |
|||
|
|||
#qunit-tests .pass .test-actual, |
|||
#qunit-tests .pass .test-expected { color: #999999; } |
|||
|
|||
#qunit-banner.qunit-pass { background-color: #C6E746; } |
|||
|
|||
/*** Failing Styles */ |
|||
|
|||
#qunit-tests li li.fail { |
|||
color: #710909; |
|||
background-color: #fff; |
|||
border-left: 26px solid #EE5757; |
|||
white-space: pre; |
|||
} |
|||
|
|||
#qunit-tests > li:last-child { |
|||
border-radius: 0 0 15px 15px; |
|||
-moz-border-radius: 0 0 15px 15px; |
|||
-webkit-border-bottom-right-radius: 15px; |
|||
-webkit-border-bottom-left-radius: 15px; |
|||
} |
|||
|
|||
#qunit-tests .fail { color: #000000; background-color: #EE5757; } |
|||
#qunit-tests .fail .test-name, |
|||
#qunit-tests .fail .module-name { color: #000000; } |
|||
|
|||
#qunit-tests .fail .test-actual { color: #EE5757; } |
|||
#qunit-tests .fail .test-expected { color: green; } |
|||
|
|||
#qunit-banner.qunit-fail { background-color: #EE5757; } |
|||
|
|||
|
|||
/** Result */ |
|||
|
|||
#qunit-testresult { |
|||
padding: 0.5em 0.5em 0.5em 2.5em; |
|||
|
|||
color: #2b81af; |
|||
background-color: #D2E0E6; |
|||
|
|||
border-bottom: 1px solid white; |
|||
} |
|||
|
|||
/** Fixture */ |
|||
|
|||
#qunit-fixture { |
|||
position: absolute; |
|||
top: -10000px; |
|||
left: -10000px; |
|||
} |
File diff suppressed because it is too large
Loading…
Reference in new issue