├── .gitignore ├── package.json ├── demo ├── demo.css ├── split-key.html └── split-key.js ├── README.md ├── LICENSE ├── src ├── jsbn │ ├── prng4.js │ ├── rng.js │ ├── sec.js │ ├── ec.js │ ├── jsbn.js │ └── jsbn2.js ├── address.js ├── txdb.js ├── crypto-js │ ├── sha256-min.js │ ├── crypto-min.js │ ├── sha256.js │ ├── crypto.js │ └── ripemd160.js ├── message.js ├── base58.js ├── events │ └── eventemitter.js ├── paillier.js ├── eckey.js ├── opcode.js ├── exit │ └── client.js ├── util.js ├── bitcoin.js ├── wallet.js ├── script.js ├── ecdsa.js └── transaction.js ├── Jakefile.js ├── test ├── index.html └── test.js └── vendor └── qunit └── qunit.css /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bitcoinjs-lib", 3 | "version": "0.1.3", 4 | "description": "Client-side Bitcoin JavaScript library", 5 | 6 | "keywords": [ 7 | "bitcoin", 8 | "browser", 9 | "client", 10 | "library" 11 | ], 12 | 13 | "author": "Stefan Thomas (http://www.justmoon.net)", 14 | 15 | "repository" : { 16 | "type" : "git", 17 | "url" : "https://github.com/bitcoinjs/bitcoinjs-lib.git" 18 | }, 19 | 20 | "devDependencies" : { 21 | "pkginfo" : ">=0.2.1", 22 | "jake-uglify" : ">=1.0.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /demo/demo.css: -------------------------------------------------------------------------------- 1 | p { 2 | margin: 0.4em 0 0.2em; 3 | } 4 | 5 | input[type=text] { 6 | width: 500px; 7 | } 8 | 9 | .alice, .bob { 10 | margin: 1em; 11 | width: 550px; 12 | padding: 10px; 13 | } 14 | 15 | .alice { 16 | border: 2px solid grey; 17 | border-left-width: 20px; 18 | } 19 | 20 | .bob { 21 | border: 2px solid grey; 22 | border-right-width: 20px; 23 | } 24 | 25 | .messageleft, .messageright { 26 | margin: 1em; 27 | background-color: grey; 28 | height: 30px; 29 | text-align: center; 30 | color: #fff; 31 | line-height: 30px; 32 | width: 590px; 33 | } 34 | 35 | .messageleft .arrow, .messageright .arrow { 36 | border-top: 15px solid #fff; 37 | border-bottom: 15px solid #fff; 38 | width: 0; 39 | height: 0; 40 | } 41 | 42 | .messageright .arrow { 43 | float: right; 44 | border-left: 15px solid grey; 45 | } 46 | 47 | .messageleft .arrow { 48 | float: left; 49 | border-right: 15px solid grey; 50 | } 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bitcoinjs-lib 2 | 3 | A library containing Bitcoin client-side functionality in JavaScript, 4 | most notably ECDSA signing and verification. 5 | 6 | [Website](http://bitcoinjs.org/) • [Mailing List](https://groups.google.com/group/bitcoinjs) • [Twitter](https://twitter.com/bitcoinjs) 7 | 8 | # Status 9 | 10 | This is currently pretty raw code. We're planning to clean it up, 11 | convert everything into CommonJS modules and put a flexible build 12 | system in place. 13 | 14 | Prototype software, use at your own peril. 15 | 16 | # License 17 | 18 | This library is free and open-source software released under the MIT 19 | license. 20 | 21 | # Copyright 22 | 23 | BitcoinJS (c) 2011-2012 Stefan Thomas 24 | Released under MIT license 25 | http://bitcoinjs.org/ 26 | 27 | JSBN (c) 2003-2005 Tom Wu 28 | Released under BSD license 29 | http://www-cs-students.stanford.edu/~tjw/jsbn/ 30 | 31 | CryptoJS (c) 2009–2012 by Jeff Mott 32 | Released under New BSD license 33 | http://code.google.com/p/crypto-js/ 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Stefan Thomas 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /src/jsbn/prng4.js: -------------------------------------------------------------------------------- 1 | // prng4.js - uses Arcfour as a PRNG 2 | 3 | function Arcfour() { 4 | this.i = 0; 5 | this.j = 0; 6 | this.S = new Array(); 7 | } 8 | 9 | // Initialize arcfour context from key, an array of ints, each from [0..255] 10 | function ARC4init(key) { 11 | var i, j, t; 12 | for(i = 0; i < 256; ++i) 13 | this.S[i] = i; 14 | j = 0; 15 | for(i = 0; i < 256; ++i) { 16 | j = (j + this.S[i] + key[i % key.length]) & 255; 17 | t = this.S[i]; 18 | this.S[i] = this.S[j]; 19 | this.S[j] = t; 20 | } 21 | this.i = 0; 22 | this.j = 0; 23 | } 24 | 25 | function ARC4next() { 26 | var t; 27 | this.i = (this.i + 1) & 255; 28 | this.j = (this.j + this.S[this.i]) & 255; 29 | t = this.S[this.i]; 30 | this.S[this.i] = this.S[this.j]; 31 | this.S[this.j] = t; 32 | return this.S[(t + this.S[this.i]) & 255]; 33 | } 34 | 35 | Arcfour.prototype.init = ARC4init; 36 | Arcfour.prototype.next = ARC4next; 37 | 38 | // Plug in your RNG constructor here 39 | function prng_newstate() { 40 | return new Arcfour(); 41 | } 42 | 43 | // Pool size must be a multiple of 4 and greater than 32. 44 | // An array of bytes the size of the pool will be passed to init() 45 | var rng_psize = 256; 46 | -------------------------------------------------------------------------------- /Jakefile.js: -------------------------------------------------------------------------------- 1 | var pkginfo = require('pkginfo')(module); 2 | var minify = require('jake-uglify').minify; 3 | 4 | var headerJS = "\ 5 | /**\n\ 6 | * BitcoinJS-lib v"+exports.version+"-default\n\ 7 | * Copyright (c) 2011 BitcoinJS Project\n\ 8 | * \n\ 9 | * This program is free software; you can redistribute it and/or modify\n\ 10 | * it under the terms of the MIT license.\n\ 11 | */"; 12 | 13 | task({'default': [ 14 | 'build/bitcoinjs-min.js', 15 | 'build/bitcoinjs-exit-min.js' 16 | ]}); 17 | 18 | desc('General-purpose build containing most features'); 19 | minify({'build/bitcoinjs-min.js': [ 20 | 'src/crypto-js/crypto.js', 21 | 'src/crypto-js/sha256.js', 22 | 'src/crypto-js/ripemd160.js', 23 | 'src/jsbn/prng4.js', 24 | 'src/jsbn/rng.js', 25 | 'src/jsbn/jsbn.js', 26 | 'src/jsbn/jsbn2.js', 27 | 28 | 'src/jsbn/ec.js', 29 | 'src/jsbn/sec.js', 30 | 'src/events/eventemitter.js', 31 | 'src/bitcoin.js', 32 | 'src/util.js', 33 | 'src/base58.js', 34 | 35 | 'src/address.js', 36 | 'src/ecdsa.js', 37 | 'src/eckey.js', 38 | 'src/opcode.js', 39 | 'src/script.js', 40 | 'src/transaction.js', 41 | 42 | 'src/wallet.js', 43 | 'src/txdb.js' 44 | ]}, { 45 | header: headerJS 46 | }); 47 | 48 | desc('Exit node client implementation'); 49 | minify({'build/bitcoinjs-exit-min.js': [ 50 | 'src/exit/client.js' 51 | ]}, { 52 | header: headerJS 53 | }); 54 | -------------------------------------------------------------------------------- /src/address.js: -------------------------------------------------------------------------------- 1 | Bitcoin.Address = function (bytes) { 2 | if ("string" == typeof bytes) { 3 | bytes = Bitcoin.Address.decodeString(bytes); 4 | } 5 | this.hash = bytes; 6 | 7 | this.version = 0x00; 8 | }; 9 | 10 | /** 11 | * Serialize this object as a standard Bitcoin address. 12 | * 13 | * Returns the address as a base58-encoded string in the standardized format. 14 | */ 15 | Bitcoin.Address.prototype.toString = function () { 16 | // Get a copy of the hash 17 | var hash = this.hash.slice(0); 18 | 19 | // Version 20 | hash.unshift(this.version); 21 | 22 | var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); 23 | 24 | var bytes = hash.concat(checksum.slice(0,4)); 25 | 26 | return Bitcoin.Base58.encode(bytes); 27 | }; 28 | 29 | Bitcoin.Address.prototype.getHashBase64 = function () { 30 | return Crypto.util.bytesToBase64(this.hash); 31 | }; 32 | 33 | /** 34 | * Parse a Bitcoin address contained in a string. 35 | */ 36 | Bitcoin.Address.decodeString = function (string) { 37 | var bytes = Bitcoin.Base58.decode(string); 38 | 39 | var hash = bytes.slice(0, 21); 40 | 41 | var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); 42 | 43 | if (checksum[0] != bytes[21] || 44 | checksum[1] != bytes[22] || 45 | checksum[2] != bytes[23] || 46 | checksum[3] != bytes[24]) { 47 | throw "Checksum validation failed!"; 48 | } 49 | 50 | var version = hash.shift(); 51 | 52 | if (version != 0) { 53 | throw "Version "+version+" not supported!"; 54 | } 55 | 56 | return hash; 57 | }; 58 | -------------------------------------------------------------------------------- /src/txdb.js: -------------------------------------------------------------------------------- 1 | var TransactionDatabase = function () { 2 | this.txs = []; 3 | this.txIndex = {}; 4 | }; 5 | 6 | EventEmitter.augment(TransactionDatabase.prototype); 7 | 8 | TransactionDatabase.prototype.addTransaction = function (tx) { 9 | this.addTransactionNoUpdate(tx); 10 | $(this).trigger('update'); 11 | }; 12 | 13 | TransactionDatabase.prototype.addTransactionNoUpdate = function (tx) { 14 | // Return if transaction is already known 15 | if (this.txIndex[tx.hash]) { 16 | return; 17 | } 18 | 19 | this.txs.push(new Bitcoin.Transaction(tx)); 20 | this.txIndex[tx.hash] = tx; 21 | }; 22 | 23 | TransactionDatabase.prototype.removeTransaction = function (hash) { 24 | this.removeTransactionNoUpdate(hash); 25 | $(this).trigger('update'); 26 | }; 27 | 28 | TransactionDatabase.prototype.removeTransactionNoUpdate = function (hash) { 29 | var tx = this.txIndex[hash]; 30 | 31 | if (!tx) { 32 | // If the tx is not in the index, we don't actually waste our 33 | // time looping through the array. 34 | return; 35 | } 36 | 37 | for (var i = 0, l = this.txs.length; i < l; i++) { 38 | if (this.txs[i].hash == hash) { 39 | this.txs.splice(i, 1); 40 | break; 41 | } 42 | } 43 | 44 | delete this.txIndex[hash]; 45 | }; 46 | 47 | TransactionDatabase.prototype.loadTransactions = function (txs) { 48 | for (var i = 0; i < txs.length; i++) { 49 | this.addTransactionNoUpdate(txs[i]); 50 | } 51 | $(this).trigger('update'); 52 | }; 53 | 54 | TransactionDatabase.prototype.getTransactions = function () { 55 | return this.txs; 56 | }; 57 | 58 | TransactionDatabase.prototype.clear = function () { 59 | this.txs = []; 60 | this.txIndex = {}; 61 | $(this).trigger('update'); 62 | }; 63 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BitcoinJS-lib Test Suite 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |

BitcoinJS-lib Test Suite

30 |

31 |
32 |

33 |
    34 |
    35 | 36 | 37 | -------------------------------------------------------------------------------- /src/crypto-js/sha256-min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Crypto-JS v2.0.0 3 | * http://code.google.com/p/crypto-js/ 4 | * Copyright (c) 2009, Jeff Mott. All rights reserved. 5 | * http://code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (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>>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})(); -------------------------------------------------------------------------------- /src/crypto-js/crypto-min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Crypto-JS v2.0.0 3 | * http://code.google.com/p/crypto-js/ 4 | * Copyright (c) 2009, Jeff Mott. All rights reserved. 5 | * http://code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function(){var c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var d=window.Crypto={};var a=d.util={rotl:function(h,g){return(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;g0;h--){g.push(Math.floor(Math.random()*256))}return g},bytesToWords:function(h){for(var k=[],j=0,g=0;j>>5]|=h[j]<<(24-g%32)}return k},wordsToBytes:function(i){for(var h=[],g=0;g>>5]>>>(24-g%32))&255)}return h},bytesToHex:function(g){for(var j=[],h=0;h>>4).toString(16));j.push((g[h]&15).toString(16))}return j.join("")},hexToBytes:function(h){for(var g=[],i=0;i>>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>>(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 5 | // in your main HTML document. 6 | 7 | var rng_state; 8 | var rng_pool; 9 | var rng_pptr; 10 | 11 | // Mix in a 32-bit integer into the pool 12 | function rng_seed_int(x) { 13 | rng_pool[rng_pptr++] ^= x & 255; 14 | rng_pool[rng_pptr++] ^= (x >> 8) & 255; 15 | rng_pool[rng_pptr++] ^= (x >> 16) & 255; 16 | rng_pool[rng_pptr++] ^= (x >> 24) & 255; 17 | if(rng_pptr >= rng_psize) rng_pptr -= rng_psize; 18 | } 19 | 20 | // Mix in the current time (w/milliseconds) into the pool 21 | function rng_seed_time() { 22 | rng_seed_int(new Date().getTime()); 23 | } 24 | 25 | // Initialize the pool with junk if needed. 26 | if(rng_pool == null) { 27 | rng_pool = new Array(); 28 | rng_pptr = 0; 29 | var t; 30 | if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) { 31 | // Extract entropy (256 bits) from NS4 RNG if available 32 | var z = window.crypto.random(32); 33 | for(t = 0; t < z.length; ++t) 34 | rng_pool[rng_pptr++] = z.charCodeAt(t) & 255; 35 | } 36 | while(rng_pptr < rng_psize) { // extract some randomness from Math.random() 37 | t = Math.floor(65536 * Math.random()); 38 | rng_pool[rng_pptr++] = t >>> 8; 39 | rng_pool[rng_pptr++] = t & 255; 40 | } 41 | rng_pptr = 0; 42 | rng_seed_time(); 43 | //rng_seed_int(window.screenX); 44 | //rng_seed_int(window.screenY); 45 | } 46 | 47 | function rng_get_byte() { 48 | if(rng_state == null) { 49 | rng_seed_time(); 50 | rng_state = prng_newstate(); 51 | rng_state.init(rng_pool); 52 | for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) 53 | rng_pool[rng_pptr] = 0; 54 | rng_pptr = 0; 55 | //rng_pool = null; 56 | } 57 | // TODO: allow reseeding after first request 58 | return rng_state.next(); 59 | } 60 | 61 | function rng_get_bytes(ba) { 62 | var i; 63 | for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte(); 64 | } 65 | 66 | function SecureRandom() {} 67 | 68 | SecureRandom.prototype.nextBytes = rng_get_bytes; 69 | -------------------------------------------------------------------------------- /src/message.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implements Bitcoin's feature for signing arbitrary messages. 3 | */ 4 | Bitcoin.Message = (function () { 5 | var Message = {}; 6 | 7 | Message.magicPrefix = "Bitcoin Signed Message:\n"; 8 | 9 | Message.makeMagicMessage = function (message) { 10 | var magicBytes = Crypto.charenc.UTF8.stringToBytes(Message.magicPrefix); 11 | var messageBytes = Crypto.charenc.UTF8.stringToBytes(message); 12 | 13 | var buffer = []; 14 | buffer = buffer.concat(Bitcoin.Util.numToVarInt(magicBytes.length)); 15 | buffer = buffer.concat(magicBytes); 16 | buffer = buffer.concat(Bitcoin.Util.numToVarInt(messageBytes.length)); 17 | buffer = buffer.concat(messageBytes); 18 | 19 | return buffer; 20 | }; 21 | 22 | Message.getHash = function (message) { 23 | var buffer = Message.makeMagicMessage(message); 24 | return Crypto.SHA256(Crypto.SHA256(buffer, {asBytes: true}), {asBytes: true}); 25 | }; 26 | 27 | Message.signMessage = function (key, message, compressed) { 28 | var hash = Message.getHash(message); 29 | 30 | var sig = key.sign(hash); 31 | 32 | var obj = Bitcoin.ECDSA.parseSig(sig); 33 | 34 | var address = key.getBitcoinAddress().toString(); 35 | var i = Bitcoin.ECDSA.calcPubkeyRecoveryParam(address, obj.r, obj.s, hash); 36 | 37 | i += 27; 38 | if (compressed) i += 4; 39 | 40 | var rBa = obj.r.toByteArrayUnsigned(); 41 | var sBa = obj.s.toByteArrayUnsigned(); 42 | 43 | // Pad to 32 bytes per value 44 | while (rBa.length < 32) rBa.unshift(0); 45 | while (sBa.length < 32) sBa.unshift(0); 46 | 47 | sig = [i].concat(rBa).concat(sBa); 48 | 49 | return Crypto.util.bytesToBase64(sig); 50 | }; 51 | 52 | Message.verifyMessage = function (address, sig, message) { 53 | sig = Crypto.util.base64ToBytes(sig); 54 | sig = Bitcoin.ECDSA.parseSigCompact(sig); 55 | 56 | var hash = Message.getHash(message); 57 | 58 | var isCompressed = !!(sig.i & 4); 59 | var pubKey = Bitcoin.ECDSA.recoverPubKey(sig.r, sig.s, hash, sig.i); 60 | 61 | pubKey.setCompressed(isCompressed); 62 | 63 | var expectedAddress = pubKey.getBitcoinAddress().toString(); 64 | 65 | return (address === expectedAddress); 66 | }; 67 | 68 | return Message; 69 | })(); 70 | -------------------------------------------------------------------------------- /src/base58.js: -------------------------------------------------------------------------------- 1 | (function (Bitcoin) { 2 | Bitcoin.Base58 = { 3 | alphabet: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz", 4 | validRegex: /^[1-9A-HJ-NP-Za-km-z]+$/, 5 | base: BigInteger.valueOf(58), 6 | 7 | /** 8 | * Convert a byte array to a base58-encoded string. 9 | * 10 | * Written by Mike Hearn for BitcoinJ. 11 | * Copyright (c) 2011 Google Inc. 12 | * 13 | * Ported to JavaScript by Stefan Thomas. 14 | */ 15 | encode: function (input) { 16 | var bi = BigInteger.fromByteArrayUnsigned(input); 17 | var chars = []; 18 | 19 | while (bi.compareTo(B58.base) >= 0) { 20 | var mod = bi.mod(B58.base); 21 | chars.unshift(B58.alphabet[mod.intValue()]); 22 | bi = bi.subtract(mod).divide(B58.base); 23 | } 24 | chars.unshift(B58.alphabet[bi.intValue()]); 25 | 26 | // Convert leading zeros too. 27 | for (var i = 0; i < input.length; i++) { 28 | if (input[i] == 0x00) { 29 | chars.unshift(B58.alphabet[0]); 30 | } else break; 31 | } 32 | 33 | return chars.join(''); 34 | }, 35 | 36 | /** 37 | * Convert a base58-encoded string to a byte array. 38 | * 39 | * Written by Mike Hearn for BitcoinJ. 40 | * Copyright (c) 2011 Google Inc. 41 | * 42 | * Ported to JavaScript by Stefan Thomas. 43 | */ 44 | decode: function (input) { 45 | var bi = BigInteger.valueOf(0); 46 | var leadingZerosNum = 0; 47 | for (var i = input.length - 1; i >= 0; i--) { 48 | var alphaIndex = B58.alphabet.indexOf(input[i]); 49 | if (alphaIndex < 0) { 50 | throw "Invalid character"; 51 | } 52 | bi = bi.add(BigInteger.valueOf(alphaIndex) 53 | .multiply(B58.base.pow(input.length - 1 -i))); 54 | 55 | // This counts leading zero bytes 56 | if (input[i] == "1") leadingZerosNum++; 57 | else leadingZerosNum = 0; 58 | } 59 | var bytes = bi.toByteArrayUnsigned(); 60 | 61 | // Add leading zeros 62 | while (leadingZerosNum-- > 0) bytes.unshift(0); 63 | 64 | return bytes; 65 | } 66 | }; 67 | 68 | var B58 = Bitcoin.Base58; 69 | })( 70 | 'undefined' != typeof Bitcoin ? Bitcoin : module.exports 71 | ); 72 | -------------------------------------------------------------------------------- /src/events/eventemitter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * EventEmitter Mixin 3 | * 4 | * Designed to be used in conjunction with a mixin "augment" function, 5 | * such as http://chamnapchhorn.blogspot.com/2009/05/javascript-mixins.html 6 | * 7 | * @usage augment(MyClass, EventEmitter); 8 | * my_inst = new MyClass(); 9 | * my_inst.on('someEvent', function(e){ console.dir(e); }); 10 | * my_inst.trigger('someEvent', {eventProp:'value'}); 11 | * 12 | * @example 13 | * // create a 'class' 14 | * MyClass = function() {} 15 | * // augment it with EventEmitter 16 | * EventEmitter.augment(MyClass.prototype); 17 | * // create a method, which triggers an event 18 | * MyClass.prototype.scrollComplete = function() { 19 | * this.trigger('scrolled', {baz:'eck'}); 20 | * }; 21 | * 22 | * // this callback is pulled out into a named function so that we can unbind it 23 | * var callback = function(e) { 24 | * console.log('the scrolled event was fired! this.foo='+this.foo+', e.baz='+e.baz); 25 | * }; 26 | * // create an instance of th class 27 | * var myinstance = new MyClass(); 28 | * // set a property on the instance 29 | * myinstance.foo = 'bar'; 30 | * // bind to the scrollComplete event 31 | * myinstance.on('scrolled', callback, myinstance); 32 | * // fire the method, which should trigger the event and therefore our callback 33 | * myinstance.scrollComplete(); 34 | * // unbind the event, so that our callback should not get called 35 | * myinstance.removeListener('scrolled', callback); 36 | * // this should now not fire the callback 37 | * myinstance.scrollComplete(); 38 | */ 39 | var EventEmitter = function() {}; 40 | /** 41 | * Bind a callback to an event, with an option scope context 42 | * 43 | * @param {string} name the name of the event 44 | * @param {function} callback the callback function to fire when the event is triggered 45 | * @param {object} context the scope to use for the callback (which will become 'this' inside the callback) 46 | */ 47 | EventEmitter.prototype.on = function(name, callback, context) { 48 | if (!context) context = this; 49 | if (!this._listeners) this._listeners = {}; 50 | if (!this._listeners[name]) this._listeners[name] = []; 51 | if (!this._unbinders) this._unbinders = {}; 52 | if (!this._unbinders[name]) this._unbinders[name] = []; 53 | var f = function(e) { 54 | callback.apply(context, [e]); 55 | }; 56 | this._unbinders[name].push(callback); 57 | this._listeners[name].push(f); 58 | }; 59 | /** 60 | * Trigger an event, firing all bound callbacks 61 | * 62 | * @param {string} name the name of the event 63 | * @param {object} event the event object to be passed through to the callback 64 | */ 65 | EventEmitter.prototype.trigger = function(name, event) { 66 | if (event === undefined) event = {} 67 | if (!this._listeners) this._listeners = {}; 68 | if (!this._listeners[name]) return; 69 | var i = this._listeners[name].length; 70 | while (i--) this._listeners[name][i](event); 71 | }; 72 | /** 73 | * Remove a bound listener 74 | * 75 | * @param {string} name the name of the event 76 | * @param {object} event the event object to be passed through to the callback 77 | */ 78 | EventEmitter.prototype.removeListener = function(name, callback) { 79 | if (!this._unbinders) this._unbinders = {}; 80 | if (!this._unbinders[name]) return; 81 | var i = this._unbinders[name].length; 82 | while (i--) { 83 | if (this._unbinders[name][i] === callback) { 84 | this._unbinders[name].splice(i, 1); 85 | this._listeners[name].splice(i, 1); 86 | } 87 | } 88 | }; 89 | /** 90 | * Augment an object with the EventEmitter mixin 91 | * 92 | * @param {object} obj The object to be augmented (often an object's protoype) 93 | */ 94 | EventEmitter.augment = function(obj) { 95 | for (var method in EventEmitter.prototype) { 96 | if (!obj[method]) obj[method] = EventEmitter.prototype[method]; 97 | } 98 | }; 99 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | // 2 | // Testing elliptic curve math 3 | // ----------------------------------------------------------------------------- 4 | module("ec"); 5 | 6 | var ecparams = getSECCurveByName("secp256k1"); 7 | var rng = new SecureRandom(); 8 | 9 | test("Classes", function () { 10 | expect(3); 11 | ok(ECPointFp, "ECPointFp"); 12 | ok(ECFieldElementFp, "ECFieldElementFp"); 13 | ok(ECCurveFp, "ECCurveFp"); 14 | }); 15 | 16 | test("Point multiplication", function () { 17 | expect(5); 18 | 19 | var G = ecparams.getG(); 20 | var n = ecparams.getN(); 21 | 22 | ok(G.multiply(n).isInfinity(), "Gn is infinite"); 23 | 24 | var k = Bitcoin.ECDSA.getBigRandom(n); 25 | var P = G.multiply(k); 26 | ok(!P.isInfinity(), "kG is not infinite"); 27 | ok(P.isOnCurve(), "kG on curve"); 28 | ok(P.multiply(n).isInfinity(), "kGn is infinite"); 29 | 30 | ok(P.validate(), "kG validates as a public key"); 31 | }); 32 | 33 | 34 | // 35 | // Testing ECDSA 36 | // ----------------------------------------------------------------------------- 37 | module("ecdsa"); 38 | 39 | test("Classes", function () { 40 | expect(2); 41 | ok(Bitcoin.ECDSA, "Bitcoin.ECDSA"); 42 | ok(Bitcoin.ECKey, "Bitcoin.ECKey"); 43 | }); 44 | 45 | test("Keys & Key Management", function () { 46 | expect(5); 47 | 48 | var s1 = new Bitcoin.ECKey(); 49 | var p1 = s1.getPub(); 50 | equals(p1.length, 65, "Public key is correct length"); 51 | 52 | var p1_q = ECPointFp.decodeFrom(ecparams.getCurve(), p1); 53 | ok(p1_q, "Decode point from generated bytestring"); 54 | ok(p1_q.validate(), "Is a valid public point"); 55 | 56 | var p2 = Crypto.util.hexToBytes( 57 | "0486f356006a38b847bedec1bf47013776925d939d5a35a97a4d1263e550c7f1a" + 58 | "b5aba44ab74d22892097a0e851addf07ba97e33416df5affaceeb35d5607cd23c" 59 | ); 60 | var p2_q = ECPointFp.decodeFrom(ecparams.getCurve(), p2); 61 | ok(p2_q, "Decode point from constant"); 62 | ok(p2_q.validate(), "Is a valid public point"); 63 | }); 64 | 65 | test("Signing and Verifying", function () { 66 | expect(7); 67 | 68 | var s1 = new Bitcoin.ECKey(); 69 | var sig_a = s1.sign(BigInteger.ZERO); 70 | ok(sig_a, "Sign null"); 71 | equals(sig_a.length, 70, "Signature is correct length"); 72 | ok(s1.verify(BigInteger.ZERO, sig_a)); 73 | 74 | var message = new BigInteger(1024, rng).toByteArrayUnsigned(); 75 | var hash = Crypto.SHA256(message, {asBytes: true}); 76 | var sig_b = s1.sign(hash); 77 | ok(sig_b, "Sign random string"); 78 | equals(sig_b.length, 70, "Signature is correct length"); 79 | ok(s1.verify(hash, sig_b)); 80 | 81 | var message2 = Crypto.util.hexToBytes( 82 | "12dce2c169986b3346827ffb2305cf393984627f5f9722a1b1368e933c8d" + 83 | "d296653fbe5d7ac031c4962ad0eb1c4298c3b91d244e1116b4a76a130c13" + 84 | "1e7aec7fa70184a71a2e66797052831511b93c6e8d72ae58a1980eaacb66" + 85 | "8a33f50d7cefb96a5dab897b5efcb99cbafb0d777cb83fc9b2115b69c0fa" + 86 | "3d82507b932b84e4" 87 | ); 88 | var hash2 = Crypto.SHA256(message2, {asBytes: true}); 89 | var sig_c = Crypto.util.hexToBytes( 90 | "3044022038d9b8dd5c9fbf330565c1f51d72a59ba869aeb2c2001be959d3" + 91 | "79e861ec71960220a73945f32cf90d03127d2c3410d16cee120fa1a4b4c3" + 92 | "f273ab082801a95506c4" 93 | ); 94 | var s2 = Crypto.util.hexToBytes( 95 | "045a1594316e433fb91f35ef4874610d22177c3f1a1060f6c1e70a609d51" + 96 | "b20be5795cd2a5eae0d6b872ba42db95e9afaeea3fbb89e98099575b6828" + 97 | "609a978528" 98 | ); 99 | ok(Bitcoin.ECDSA.verify(hash2, sig_c, s2), "Verify constant signature"); 100 | }); 101 | 102 | // 103 | // Testing Paillier 104 | // ----------------------------------------------------------------------------- 105 | module("paillier"); 106 | 107 | test("Classes", function () { 108 | expect(3); 109 | ok(Bitcoin.Paillier, "Bitcoin.Paillier"); 110 | ok(Bitcoin.Paillier.PublicKey, "Bitcoin.Paillier.PublicKey"); 111 | ok(Bitcoin.Paillier.PrivateKey, "Bitcoin.Paillier.PrivateKey"); 112 | }); 113 | -------------------------------------------------------------------------------- /src/paillier.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement the Paillier cryptosystem in JavaScript. 3 | * 4 | * Paillier is useful for multiparty calculation. It is not currently part of any 5 | * BitcoinJS-lib distribution, but it is included here for experimental use. 6 | */ 7 | Bitcoin.Paillier = (function () { 8 | var rng = new SecureRandom(); 9 | var TWO = BigInteger.valueOf(2); 10 | 11 | var Paillier = { 12 | generate: function (bitLength) { 13 | var p, q; 14 | do { 15 | p = new BigInteger(bitLength, 1, rng); 16 | q = new BigInteger(bitLength, 1, rng); 17 | } while (p.equals(q)); 18 | 19 | var n = p.multiply(q); 20 | 21 | // p - 1 22 | var p1 = p.subtract(BigInteger.ONE); 23 | // q - 1 24 | var q1 = q.subtract(BigInteger.ONE); 25 | 26 | var nSq = n.multiply(n); 27 | 28 | // lambda 29 | var l = p1.multiply(q1).divide(p1.gcd(q1)); 30 | 31 | var coprimeBitLength = n.bitLength() - Math.floor(Math.random()*10); 32 | 33 | var alpha = new BigInteger(coprimeBitLength, 1, rng); 34 | var beta = new BigInteger(coprimeBitLength, 1, rng); 35 | 36 | var g = alpha.multiply(n).add(BigInteger.ONE) 37 | .multiply(beta.modPow(n,nSq)).mod(nSq); 38 | 39 | // mu 40 | var m = g.modPow(l,nSq).mod(nSq) 41 | .subtract(BigInteger.ONE).divide(n).modInverse(n); 42 | 43 | return new Paillier.PrivateKey(n,g,l,m,nSq); 44 | } 45 | }; 46 | 47 | Paillier.PublicKey = function (n,g,nSq) { 48 | this.n = n; 49 | this.g = g; 50 | this.nSq = nSq || n.multiply(n); 51 | }; 52 | 53 | Paillier.PublicKey.prototype.encrypt = function (i, r) { 54 | if (!r) { 55 | var coprimeBitLength = this.n.bitLength() - Math.floor(Math.random()*10); 56 | r = new BigInteger(coprimeBitLength, 1, rng); 57 | } 58 | return this.g.modPow(i,this.nSq).multiply(r.modPow(this.n,this.nSq)) 59 | .mod(this.nSq); 60 | }; 61 | 62 | Paillier.PublicKey.prototype.add = function (c, f) { 63 | return c.multiply(this.encrypt(f)).mod(this.nSq); 64 | }; 65 | 66 | Paillier.PublicKey.prototype.addCrypt = function (c, f) { 67 | return c.multiply(f).mod(this.nSq); 68 | }; 69 | 70 | Paillier.PublicKey.prototype.multiply = function (c, f) { 71 | return c.modPow(f, this.nSq); 72 | }; 73 | 74 | Paillier.PublicKey.prototype.rerandomize = function (c, r) { 75 | if (!r) { 76 | var coprimeBitLength = this.n.bitLength() - Math.floor(Math.random()*10); 77 | r = new BigInteger(coprimeBitLength, 1, rng); 78 | } 79 | return c.multiply(r.modPow(this.n, this.nSq)).mod(this.nSq); 80 | }; 81 | 82 | Paillier.PrivateKey = function (n,g,l,m,nSq) { 83 | this.l = l; 84 | this.m = m; 85 | this.n = n; 86 | this.nSq = nSq || n.multiply(n); 87 | this.pub = new Paillier.PublicKey(n,g,this.nSq); 88 | }; 89 | 90 | Paillier.PrivateKey.prototype.decrypt = function (c) { 91 | return c.modPow(this.l, this.nSq).subtract(BigInteger.ONE) 92 | .divide(this.n).multiply(this.m).mod(this.n); 93 | }; 94 | 95 | Paillier.PrivateKey.prototype.decryptR = function (c, i) { 96 | if (!i) { 97 | i = this.decrypt(c); 98 | } 99 | var rn = c.multiply(this.pub.g.modPow(i, this.nSq).modInverse(this.nSq)) 100 | .mod(this.nSq); 101 | var a = this.l.modInverse(this.n).multiply(this.n.subtract(BigInteger.ONE)); 102 | var e = a.multiply(this.l).add(BigInteger.ONE).divide(this.n); 103 | return rn.modPow(e, this.n); 104 | }; 105 | 106 | function createProxyMethod(name) { 107 | return function () { 108 | return this.pub[name].apply(this.pub, 109 | Array.prototype.slice.apply(arguments)); 110 | }; 111 | }; 112 | var a = ["add", "addCrypt", "multiply", "rerandomize", "encrypt"]; 113 | for (var i = 0, l = a.length; i < l; i++) { 114 | Paillier.PrivateKey.prototype[a[i]] = createProxyMethod(a[i]); 115 | } 116 | 117 | return Paillier; 118 | })(); 119 | -------------------------------------------------------------------------------- /src/crypto-js/sha256.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Crypto-JS v2.0.0 3 | * http://code.google.com/p/crypto-js/ 4 | * Copyright (c) 2009, Jeff Mott. All rights reserved. 5 | * http://code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function(){ 8 | 9 | // Shortcuts 10 | var C = Crypto, 11 | util = C.util, 12 | charenc = C.charenc, 13 | UTF8 = charenc.UTF8, 14 | Binary = charenc.Binary; 15 | 16 | // Constants 17 | var K = [ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 18 | 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 19 | 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 20 | 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 21 | 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 22 | 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 23 | 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 24 | 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 25 | 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 26 | 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 27 | 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 28 | 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 29 | 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 30 | 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 31 | 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 32 | 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 ]; 33 | 34 | // Public API 35 | var SHA256 = C.SHA256 = function (message, options) { 36 | var digestbytes = util.wordsToBytes(SHA256._sha256(message)); 37 | return options && options.asBytes ? digestbytes : 38 | options && options.asString ? Binary.bytesToString(digestbytes) : 39 | util.bytesToHex(digestbytes); 40 | }; 41 | 42 | // The core 43 | SHA256._sha256 = function (message) { 44 | 45 | // Convert to byte array 46 | if (message.constructor == String) message = UTF8.stringToBytes(message); 47 | /* else, assume byte array already */ 48 | 49 | var m = util.bytesToWords(message), 50 | l = message.length * 8, 51 | H = [ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 52 | 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 ], 53 | w = [], 54 | a, b, c, d, e, f, g, h, i, j, 55 | t1, t2; 56 | 57 | // Padding 58 | m[l >> 5] |= 0x80 << (24 - l % 32); 59 | m[((l + 64 >> 9) << 4) + 15] = l; 60 | 61 | for (var i = 0; i < m.length; i += 16) { 62 | 63 | a = H[0]; 64 | b = H[1]; 65 | c = H[2]; 66 | d = H[3]; 67 | e = H[4]; 68 | f = H[5]; 69 | g = H[6]; 70 | h = H[7]; 71 | 72 | for (var j = 0; j < 64; j++) { 73 | 74 | if (j < 16) w[j] = m[j + i]; 75 | else { 76 | 77 | var gamma0x = w[j - 15], 78 | gamma1x = w[j - 2], 79 | gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ 80 | ((gamma0x << 14) | (gamma0x >>> 18)) ^ 81 | (gamma0x >>> 3), 82 | gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ 83 | ((gamma1x << 13) | (gamma1x >>> 19)) ^ 84 | (gamma1x >>> 10); 85 | 86 | w[j] = gamma0 + (w[j - 7] >>> 0) + 87 | gamma1 + (w[j - 16] >>> 0); 88 | 89 | } 90 | 91 | var ch = e & f ^ ~e & g, 92 | maj = a & b ^ a & c ^ b & c, 93 | sigma0 = ((a << 30) | (a >>> 2)) ^ 94 | ((a << 19) | (a >>> 13)) ^ 95 | ((a << 10) | (a >>> 22)), 96 | sigma1 = ((e << 26) | (e >>> 6)) ^ 97 | ((e << 21) | (e >>> 11)) ^ 98 | ((e << 7) | (e >>> 25)); 99 | 100 | 101 | t1 = (h >>> 0) + sigma1 + ch + (K[j]) + (w[j] >>> 0); 102 | t2 = sigma0 + maj; 103 | 104 | h = g; 105 | g = f; 106 | f = e; 107 | e = d + t1; 108 | d = c; 109 | c = b; 110 | b = a; 111 | a = t1 + t2; 112 | 113 | } 114 | 115 | H[0] += a; 116 | H[1] += b; 117 | H[2] += c; 118 | H[3] += d; 119 | H[4] += e; 120 | H[5] += f; 121 | H[6] += g; 122 | H[7] += h; 123 | 124 | } 125 | 126 | return H; 127 | 128 | }; 129 | 130 | // Package private blocksize 131 | SHA256._blocksize = 16; 132 | 133 | })(); 134 | -------------------------------------------------------------------------------- /src/eckey.js: -------------------------------------------------------------------------------- 1 | Bitcoin.ECKey = (function () { 2 | var ECDSA = Bitcoin.ECDSA; 3 | var ecparams = getSECCurveByName("secp256k1"); 4 | var rng = new SecureRandom(); 5 | 6 | var ECKey = function (input) { 7 | if (!input) { 8 | // Generate new key 9 | var n = ecparams.getN(); 10 | this.priv = ECDSA.getBigRandom(n); 11 | } else if (input instanceof BigInteger) { 12 | // Input is a private key value 13 | this.priv = input; 14 | } else if (Bitcoin.Util.isArray(input)) { 15 | // Prepend zero byte to prevent interpretation as negative integer 16 | this.priv = BigInteger.fromByteArrayUnsigned(input); 17 | } else if ("string" == typeof input) { 18 | if (input.length == 51 && input[0] == '5') { 19 | // Base58 encoded private key 20 | this.priv = BigInteger.fromByteArrayUnsigned(ECKey.decodeString(input)); 21 | } else { 22 | // Prepend zero byte to prevent interpretation as negative integer 23 | this.priv = BigInteger.fromByteArrayUnsigned(Crypto.util.base64ToBytes(input)); 24 | } 25 | } 26 | this.compressed = !!ECKey.compressByDefault; 27 | }; 28 | 29 | /** 30 | * Whether public keys should be returned compressed by default. 31 | */ 32 | ECKey.compressByDefault = false; 33 | 34 | /** 35 | * Set whether the public key should be returned compressed or not. 36 | */ 37 | ECKey.prototype.setCompressed = function (v) { 38 | this.compressed = !!v; 39 | }; 40 | 41 | /** 42 | * Return public key in DER encoding. 43 | */ 44 | ECKey.prototype.getPub = function () { 45 | return this.getPubPoint().getEncoded(this.compressed); 46 | }; 47 | 48 | /** 49 | * Return public point as ECPoint object. 50 | */ 51 | ECKey.prototype.getPubPoint = function () { 52 | if (!this.pub) this.pub = ecparams.getG().multiply(this.priv); 53 | 54 | return this.pub; 55 | }; 56 | 57 | /** 58 | * Get the pubKeyHash for this key. 59 | * 60 | * This is calculated as RIPE160(SHA256([encoded pubkey])) and returned as 61 | * a byte array. 62 | */ 63 | ECKey.prototype.getPubKeyHash = function () { 64 | if (this.pubKeyHash) return this.pubKeyHash; 65 | 66 | return this.pubKeyHash = Bitcoin.Util.sha256ripe160(this.getPub()); 67 | }; 68 | 69 | ECKey.prototype.getBitcoinAddress = function () { 70 | var hash = this.getPubKeyHash(); 71 | var addr = new Bitcoin.Address(hash); 72 | return addr; 73 | }; 74 | 75 | ECKey.prototype.getExportedPrivateKey = function () { 76 | var hash = this.priv.toByteArrayUnsigned(); 77 | while (hash.length < 32) hash.unshift(0); 78 | hash.unshift(0x80); 79 | var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); 80 | var bytes = hash.concat(checksum.slice(0,4)); 81 | return Bitcoin.Base58.encode(bytes); 82 | }; 83 | 84 | ECKey.prototype.setPub = function (pub) { 85 | this.pub = ECPointFp.decodeFrom(ecparams.getCurve(), pub); 86 | }; 87 | 88 | ECKey.prototype.toString = function (format) { 89 | if (format === "base64") { 90 | return Crypto.util.bytesToBase64(this.priv.toByteArrayUnsigned()); 91 | } else { 92 | return Crypto.util.bytesToHex(this.priv.toByteArrayUnsigned()); 93 | } 94 | }; 95 | 96 | ECKey.prototype.sign = function (hash) { 97 | return ECDSA.sign(hash, this.priv); 98 | }; 99 | 100 | ECKey.prototype.verify = function (hash, sig) { 101 | return ECDSA.verify(hash, sig, this.getPub()); 102 | }; 103 | 104 | /** 105 | * Parse an exported private key contained in a string. 106 | */ 107 | ECKey.decodeString = function (string) { 108 | var bytes = Bitcoin.Base58.decode(string); 109 | 110 | var hash = bytes.slice(0, 33); 111 | 112 | var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true}); 113 | 114 | if (checksum[0] != bytes[33] || 115 | checksum[1] != bytes[34] || 116 | checksum[2] != bytes[35] || 117 | checksum[3] != bytes[36]) { 118 | throw "Checksum validation failed!"; 119 | } 120 | 121 | var version = hash.shift(); 122 | 123 | if (version != 0x80) { 124 | throw "Version "+version+" not supported!"; 125 | } 126 | 127 | return hash; 128 | }; 129 | 130 | return ECKey; 131 | })(); 132 | -------------------------------------------------------------------------------- /src/opcode.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | var Opcode = Bitcoin.Opcode = function (num) { 3 | this.code = num; 4 | }; 5 | 6 | Opcode.prototype.toString = function () { 7 | return Opcode.reverseMap[this.code]; 8 | }; 9 | 10 | Opcode.map = { 11 | // push value 12 | OP_0 : 0, 13 | OP_FALSE : 0, 14 | OP_PUSHDATA1 : 76, 15 | OP_PUSHDATA2 : 77, 16 | OP_PUSHDATA4 : 78, 17 | OP_1NEGATE : 79, 18 | OP_RESERVED : 80, 19 | OP_1 : 81, 20 | OP_TRUE : 81, 21 | OP_2 : 82, 22 | OP_3 : 83, 23 | OP_4 : 84, 24 | OP_5 : 85, 25 | OP_6 : 86, 26 | OP_7 : 87, 27 | OP_8 : 88, 28 | OP_9 : 89, 29 | OP_10 : 90, 30 | OP_11 : 91, 31 | OP_12 : 92, 32 | OP_13 : 93, 33 | OP_14 : 94, 34 | OP_15 : 95, 35 | OP_16 : 96, 36 | 37 | // control 38 | OP_NOP : 97, 39 | OP_VER : 98, 40 | OP_IF : 99, 41 | OP_NOTIF : 100, 42 | OP_VERIF : 101, 43 | OP_VERNOTIF : 102, 44 | OP_ELSE : 103, 45 | OP_ENDIF : 104, 46 | OP_VERIFY : 105, 47 | OP_RETURN : 106, 48 | 49 | // stack ops 50 | OP_TOALTSTACK : 107, 51 | OP_FROMALTSTACK : 108, 52 | OP_2DROP : 109, 53 | OP_2DUP : 110, 54 | OP_3DUP : 111, 55 | OP_2OVER : 112, 56 | OP_2ROT : 113, 57 | OP_2SWAP : 114, 58 | OP_IFDUP : 115, 59 | OP_DEPTH : 116, 60 | OP_DROP : 117, 61 | OP_DUP : 118, 62 | OP_NIP : 119, 63 | OP_OVER : 120, 64 | OP_PICK : 121, 65 | OP_ROLL : 122, 66 | OP_ROT : 123, 67 | OP_SWAP : 124, 68 | OP_TUCK : 125, 69 | 70 | // splice ops 71 | OP_CAT : 126, 72 | OP_SUBSTR : 127, 73 | OP_LEFT : 128, 74 | OP_RIGHT : 129, 75 | OP_SIZE : 130, 76 | 77 | // bit logic 78 | OP_INVERT : 131, 79 | OP_AND : 132, 80 | OP_OR : 133, 81 | OP_XOR : 134, 82 | OP_EQUAL : 135, 83 | OP_EQUALVERIFY : 136, 84 | OP_RESERVED1 : 137, 85 | OP_RESERVED2 : 138, 86 | 87 | // numeric 88 | OP_1ADD : 139, 89 | OP_1SUB : 140, 90 | OP_2MUL : 141, 91 | OP_2DIV : 142, 92 | OP_NEGATE : 143, 93 | OP_ABS : 144, 94 | OP_NOT : 145, 95 | OP_0NOTEQUAL : 146, 96 | 97 | OP_ADD : 147, 98 | OP_SUB : 148, 99 | OP_MUL : 149, 100 | OP_DIV : 150, 101 | OP_MOD : 151, 102 | OP_LSHIFT : 152, 103 | OP_RSHIFT : 153, 104 | 105 | OP_BOOLAND : 154, 106 | OP_BOOLOR : 155, 107 | OP_NUMEQUAL : 156, 108 | OP_NUMEQUALVERIFY : 157, 109 | OP_NUMNOTEQUAL : 158, 110 | OP_LESSTHAN : 159, 111 | OP_GREATERTHAN : 160, 112 | OP_LESSTHANOREQUAL : 161, 113 | OP_GREATERTHANOREQUAL : 162, 114 | OP_MIN : 163, 115 | OP_MAX : 164, 116 | 117 | OP_WITHIN : 165, 118 | 119 | // crypto 120 | OP_RIPEMD160 : 166, 121 | OP_SHA1 : 167, 122 | OP_SHA256 : 168, 123 | OP_HASH160 : 169, 124 | OP_HASH256 : 170, 125 | OP_CODESEPARATOR : 171, 126 | OP_CHECKSIG : 172, 127 | OP_CHECKSIGVERIFY : 173, 128 | OP_CHECKMULTISIG : 174, 129 | OP_CHECKMULTISIGVERIFY : 175, 130 | 131 | // expansion 132 | OP_NOP1 : 176, 133 | OP_NOP2 : 177, 134 | OP_NOP3 : 178, 135 | OP_NOP4 : 179, 136 | OP_NOP5 : 180, 137 | OP_NOP6 : 181, 138 | OP_NOP7 : 182, 139 | OP_NOP8 : 183, 140 | OP_NOP9 : 184, 141 | OP_NOP10 : 185, 142 | 143 | // template matching params 144 | OP_PUBKEYHASH : 253, 145 | OP_PUBKEY : 254, 146 | OP_INVALIDOPCODE : 255 147 | }; 148 | 149 | Opcode.reverseMap = []; 150 | 151 | for (var i in Opcode.map) { 152 | Opcode.reverseMap[Opcode.map[i]] = i; 153 | } 154 | })(); 155 | -------------------------------------------------------------------------------- /src/exit/client.js: -------------------------------------------------------------------------------- 1 | (function (exports, Bitcoin, io, $, global) { 2 | 3 | /** 4 | * Expose constructor. 5 | */ 6 | 7 | exports.ExitNode = ExitNode; 8 | 9 | function ExitNode(host, port, secure) { 10 | this.setUri(host, port, secure); 11 | 12 | this.unique = 1; 13 | this.connected = false; 14 | 15 | this.callbacks = []; 16 | }; 17 | 18 | Bitcoin.EventEmitter.augment(ExitNode); 19 | 20 | ExitNode.prototype.setUri = function (host, port, secure) { 21 | this.uri = (secure ? "https://" : "http://")+host+":"+port; 22 | }; 23 | 24 | ExitNode.prototype.connect = function (wallet) { 25 | this.wallet = wallet; 26 | 27 | // Workaround for socket.io not properly allowing disconnecting and reconnecting 28 | delete io.sockets[this.uri]; 29 | io.j = []; 30 | 31 | this.socket = io.connect(this.uri); 32 | this.socket.on('connect', $.proxy(this.handleConnect, this)); 33 | this.socket.on('error', function () { 34 | console.log('error, test'); 35 | }); 36 | this.socket.on('message', $.proxy(this.handleMessage, this)); 37 | this.socket.on('disconnect', $.proxy(this.handleDisconnect, this)); 38 | }; 39 | 40 | ExitNode.prototype.disconnect = function () { 41 | if (this.socket) { 42 | this.socket.disconnect(); 43 | this.socket = null; 44 | this.connected = false; 45 | } 46 | 47 | this.trigger('connectStatus', {status: 'unknown'}); 48 | }; 49 | 50 | /** 51 | * Make RPC call. 52 | */ 53 | ExitNode.prototype.call = function (method, argObj, callback) { 54 | this.socket.send($.toJSON({ 55 | "method": method, 56 | "params": [argObj], 57 | "id": this.unique 58 | })); 59 | if (callback) this.callbacks[this.unique] = callback; 60 | this.unique++; 61 | }; 62 | 63 | ExitNode.prototype.handleConnect = function () { 64 | var self = this; 65 | 66 | this.connected = true; 67 | }; 68 | 69 | ExitNode.prototype.listen = function (addrs) { 70 | self.call("pubkeysRegister", { 71 | keys: addrs.join(',') 72 | }, function (err, result) { 73 | if (err) { 74 | console.error("Could not register public keys"); 75 | return; 76 | } 77 | 78 | self.call("pubkeysListen", { 79 | handle: result.handle 80 | }, function (err, result) { 81 | // Communicate the block height 82 | self.trigger('blockInit', {height: result.height}); 83 | 84 | // Pass on the newly downloaded transactions 85 | self.trigger('txData', { 86 | confirmed: true, 87 | txs: result.txs 88 | }); 89 | 90 | // TODO: Download more transactions 91 | 92 | self.trigger('connectStatus', {status: 'ok'}); 93 | }); 94 | 95 | self.call("pubkeysUnconfirmed", { 96 | handle: result.handle 97 | }, function (err, result) { 98 | // Pass on the newly downloaded transactions 99 | self.trigger('txData', { 100 | confirmed: false, 101 | txs: result.txs 102 | }); 103 | }); 104 | }); 105 | }; 106 | 107 | 108 | ExitNode.prototype.handleMessage = function (data) { 109 | // Handle JSON-RPC result messages 110 | if ("undefined" !== typeof data.result && 111 | "function" == typeof this.callbacks[data.id]) { 112 | this.callbacks[data.id](data.error, data.result); 113 | 114 | // Handle JSON-RPC request messages 115 | } else if ("undefined" !== typeof data.method) { 116 | // Create an event 117 | this.trigger(data.method, data.params[0]); 118 | } 119 | }; 120 | 121 | 122 | ExitNode.prototype.handleDisconnect = function () { 123 | // TODO: Attempt reconnect (unless disconnect was intended) 124 | }; 125 | 126 | ExitNode.prototype.query = function (api, params, jsonp, callback) { 127 | if ("function" === typeof jsonp) { 128 | callback = jsonp; 129 | jsonp = false; 130 | } 131 | 132 | params = params || {}; 133 | callback = "function" === typeof callback ? callback : function () {}; 134 | 135 | var url = this.uri + '/' + api; 136 | if (jsonp) { 137 | url += "?callback=?"; 138 | } 139 | 140 | $.getJSON(url, params, callback); 141 | }; 142 | })( 143 | 'undefined' != typeof Bitcoin ? Bitcoin : module.exports, 144 | 'undefined' != typeof Bitcoin ? Bitcoin : require('bitcoinjs-lib'), 145 | 'undefined' != typeof io ? io : require('io'), 146 | jQuery, // TODO: Add Node.js equivalent 147 | this 148 | ); 149 | -------------------------------------------------------------------------------- /src/crypto-js/crypto.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Crypto-JS v2.0.0 3 | * http://code.google.com/p/crypto-js/ 4 | * Copyright (c) 2009, Jeff Mott. All rights reserved. 5 | * http://code.google.com/p/crypto-js/wiki/License 6 | */ 7 | (function(){ 8 | 9 | var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 10 | 11 | // Global Crypto object 12 | var Crypto = window.Crypto = {}; 13 | 14 | // Crypto utilities 15 | var util = Crypto.util = { 16 | 17 | // Bit-wise rotate left 18 | rotl: function (n, b) { 19 | return (n << b) | (n >>> (32 - b)); 20 | }, 21 | 22 | // Bit-wise rotate right 23 | rotr: function (n, b) { 24 | return (n << (32 - b)) | (n >>> b); 25 | }, 26 | 27 | // Swap big-endian to little-endian and vice versa 28 | endian: function (n) { 29 | 30 | // If number given, swap endian 31 | if (n.constructor == Number) { 32 | return util.rotl(n, 8) & 0x00FF00FF | 33 | util.rotl(n, 24) & 0xFF00FF00; 34 | } 35 | 36 | // Else, assume array and swap all items 37 | for (var i = 0; i < n.length; i++) 38 | n[i] = util.endian(n[i]); 39 | return n; 40 | 41 | }, 42 | 43 | // Generate an array of any length of random bytes 44 | randomBytes: function (n) { 45 | for (var bytes = []; n > 0; n--) 46 | bytes.push(Math.floor(Math.random() * 256)); 47 | return bytes; 48 | }, 49 | 50 | // Convert a byte array to big-endian 32-bit words 51 | bytesToWords: function (bytes) { 52 | for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8) 53 | words[b >>> 5] |= bytes[i] << (24 - b % 32); 54 | return words; 55 | }, 56 | 57 | // Convert big-endian 32-bit words to a byte array 58 | wordsToBytes: function (words) { 59 | for (var bytes = [], b = 0; b < words.length * 32; b += 8) 60 | bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); 61 | return bytes; 62 | }, 63 | 64 | // Convert a byte array to a hex string 65 | bytesToHex: function (bytes) { 66 | for (var hex = [], i = 0; i < bytes.length; i++) { 67 | hex.push((bytes[i] >>> 4).toString(16)); 68 | hex.push((bytes[i] & 0xF).toString(16)); 69 | } 70 | return hex.join(""); 71 | }, 72 | 73 | // Convert a hex string to a byte array 74 | hexToBytes: function (hex) { 75 | for (var bytes = [], c = 0; c < hex.length; c += 2) 76 | bytes.push(parseInt(hex.substr(c, 2), 16)); 77 | return bytes; 78 | }, 79 | 80 | // Convert a byte array to a base-64 string 81 | bytesToBase64: function (bytes) { 82 | 83 | // Use browser-native function if it exists 84 | if (typeof btoa == "function") return btoa(Binary.bytesToString(bytes)); 85 | 86 | for(var base64 = [], i = 0; i < bytes.length; i += 3) { 87 | var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; 88 | for (var j = 0; j < 4; j++) { 89 | if (i * 8 + j * 6 <= bytes.length * 8) 90 | base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F)); 91 | else base64.push("="); 92 | } 93 | } 94 | 95 | return base64.join(""); 96 | 97 | }, 98 | 99 | // Convert a base-64 string to a byte array 100 | base64ToBytes: function (base64) { 101 | 102 | // Use browser-native function if it exists 103 | if (typeof atob == "function") return Binary.stringToBytes(atob(base64)); 104 | 105 | // Remove non-base-64 characters 106 | base64 = base64.replace(/[^A-Z0-9+\/]/ig, ""); 107 | 108 | for (var bytes = [], i = 0, imod4 = 0; i < base64.length; imod4 = ++i % 4) { 109 | if (imod4 == 0) continue; 110 | bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) | 111 | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2))); 112 | } 113 | 114 | return bytes; 115 | 116 | } 117 | 118 | }; 119 | 120 | // Crypto mode namespace 121 | Crypto.mode = {}; 122 | 123 | // Crypto character encodings 124 | var charenc = Crypto.charenc = {}; 125 | 126 | // UTF-8 encoding 127 | var UTF8 = charenc.UTF8 = { 128 | 129 | // Convert a string to a byte array 130 | stringToBytes: function (str) { 131 | return Binary.stringToBytes(unescape(encodeURIComponent(str))); 132 | }, 133 | 134 | // Convert a byte array to a string 135 | bytesToString: function (bytes) { 136 | return decodeURIComponent(escape(Binary.bytesToString(bytes))); 137 | } 138 | 139 | }; 140 | 141 | // Binary encoding 142 | var Binary = charenc.Binary = { 143 | 144 | // Convert a string to a byte array 145 | stringToBytes: function (str) { 146 | for (var bytes = [], i = 0; i < str.length; i++) 147 | bytes.push(str.charCodeAt(i)); 148 | return bytes; 149 | }, 150 | 151 | // Convert a byte array to a string 152 | bytesToString: function (bytes) { 153 | for (var str = [], i = 0; i < bytes.length; i++) 154 | str.push(String.fromCharCode(bytes[i])); 155 | return str.join(""); 156 | } 157 | 158 | }; 159 | 160 | })(); 161 | -------------------------------------------------------------------------------- /vendor/qunit/qunit.css: -------------------------------------------------------------------------------- 1 | /** 2 | * QUnit - A JavaScript Unit Testing Framework 3 | * 4 | * http://docs.jquery.com/QUnit 5 | * 6 | * Copyright (c) 2011 John Resig, Jörn Zaefferer 7 | * Dual licensed under the MIT (MIT-LICENSE.txt) 8 | * or GPL (GPL-LICENSE.txt) licenses. 9 | */ 10 | 11 | /** Font Family and Sizes */ 12 | 13 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 14 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 15 | } 16 | 17 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 18 | #qunit-tests { font-size: smaller; } 19 | 20 | 21 | /** Resets */ 22 | 23 | #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { 24 | margin: 0; 25 | padding: 0; 26 | } 27 | 28 | 29 | /** Header */ 30 | 31 | #qunit-header { 32 | padding: 0.5em 0 0.5em 1em; 33 | 34 | color: #8699a4; 35 | background-color: #0d3349; 36 | 37 | font-size: 1.5em; 38 | line-height: 1em; 39 | font-weight: normal; 40 | 41 | border-radius: 15px 15px 0 0; 42 | -moz-border-radius: 15px 15px 0 0; 43 | -webkit-border-top-right-radius: 15px; 44 | -webkit-border-top-left-radius: 15px; 45 | } 46 | 47 | #qunit-header a { 48 | text-decoration: none; 49 | color: #c2ccd1; 50 | } 51 | 52 | #qunit-header a:hover, 53 | #qunit-header a:focus { 54 | color: #fff; 55 | } 56 | 57 | #qunit-banner { 58 | height: 5px; 59 | } 60 | 61 | #qunit-testrunner-toolbar { 62 | padding: 0.5em 0 0.5em 2em; 63 | color: #5E740B; 64 | background-color: #eee; 65 | } 66 | 67 | #qunit-userAgent { 68 | padding: 0.5em 0 0.5em 2.5em; 69 | background-color: #2b81af; 70 | color: #fff; 71 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 72 | } 73 | 74 | 75 | /** Tests: Pass/Fail */ 76 | 77 | #qunit-tests { 78 | list-style-position: inside; 79 | } 80 | 81 | #qunit-tests li { 82 | padding: 0.4em 0.5em 0.4em 2.5em; 83 | border-bottom: 1px solid #fff; 84 | list-style-position: inside; 85 | } 86 | 87 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { 88 | display: none; 89 | } 90 | 91 | #qunit-tests li strong { 92 | cursor: pointer; 93 | } 94 | 95 | #qunit-tests li a { 96 | padding: 0.5em; 97 | color: #c2ccd1; 98 | text-decoration: none; 99 | } 100 | #qunit-tests li a:hover, 101 | #qunit-tests li a:focus { 102 | color: #000; 103 | } 104 | 105 | #qunit-tests ol { 106 | margin-top: 0.5em; 107 | padding: 0.5em; 108 | 109 | background-color: #fff; 110 | 111 | border-radius: 15px; 112 | -moz-border-radius: 15px; 113 | -webkit-border-radius: 15px; 114 | 115 | box-shadow: inset 0px 2px 13px #999; 116 | -moz-box-shadow: inset 0px 2px 13px #999; 117 | -webkit-box-shadow: inset 0px 2px 13px #999; 118 | } 119 | 120 | #qunit-tests table { 121 | border-collapse: collapse; 122 | margin-top: .2em; 123 | } 124 | 125 | #qunit-tests th { 126 | text-align: right; 127 | vertical-align: top; 128 | padding: 0 .5em 0 0; 129 | } 130 | 131 | #qunit-tests td { 132 | vertical-align: top; 133 | } 134 | 135 | #qunit-tests pre { 136 | margin: 0; 137 | white-space: pre-wrap; 138 | word-wrap: break-word; 139 | } 140 | 141 | #qunit-tests del { 142 | background-color: #e0f2be; 143 | color: #374e0c; 144 | text-decoration: none; 145 | } 146 | 147 | #qunit-tests ins { 148 | background-color: #ffcaca; 149 | color: #500; 150 | text-decoration: none; 151 | } 152 | 153 | /*** Test Counts */ 154 | 155 | #qunit-tests b.counts { color: black; } 156 | #qunit-tests b.passed { color: #5E740B; } 157 | #qunit-tests b.failed { color: #710909; } 158 | 159 | #qunit-tests li li { 160 | margin: 0.5em; 161 | padding: 0.4em 0.5em 0.4em 0.5em; 162 | background-color: #fff; 163 | border-bottom: none; 164 | list-style-position: inside; 165 | } 166 | 167 | /*** Passing Styles */ 168 | 169 | #qunit-tests li li.pass { 170 | color: #5E740B; 171 | background-color: #fff; 172 | border-left: 26px solid #C6E746; 173 | } 174 | 175 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 176 | #qunit-tests .pass .test-name { color: #366097; } 177 | 178 | #qunit-tests .pass .test-actual, 179 | #qunit-tests .pass .test-expected { color: #999999; } 180 | 181 | #qunit-banner.qunit-pass { background-color: #C6E746; } 182 | 183 | /*** Failing Styles */ 184 | 185 | #qunit-tests li li.fail { 186 | color: #710909; 187 | background-color: #fff; 188 | border-left: 26px solid #EE5757; 189 | white-space: pre; 190 | } 191 | 192 | #qunit-tests > li:last-child { 193 | border-radius: 0 0 15px 15px; 194 | -moz-border-radius: 0 0 15px 15px; 195 | -webkit-border-bottom-right-radius: 15px; 196 | -webkit-border-bottom-left-radius: 15px; 197 | } 198 | 199 | #qunit-tests .fail { color: #000000; background-color: #EE5757; } 200 | #qunit-tests .fail .test-name, 201 | #qunit-tests .fail .module-name { color: #000000; } 202 | 203 | #qunit-tests .fail .test-actual { color: #EE5757; } 204 | #qunit-tests .fail .test-expected { color: green; } 205 | 206 | #qunit-banner.qunit-fail { background-color: #EE5757; } 207 | 208 | 209 | /** Result */ 210 | 211 | #qunit-testresult { 212 | padding: 0.5em 0.5em 0.5em 2.5em; 213 | 214 | color: #2b81af; 215 | background-color: #D2E0E6; 216 | 217 | border-bottom: 1px solid white; 218 | } 219 | 220 | /** Fixture */ 221 | 222 | #qunit-fixture { 223 | position: absolute; 224 | top: -10000px; 225 | left: -10000px; 226 | } 227 | -------------------------------------------------------------------------------- /src/crypto-js/ripemd160.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Crypto-JS v2.0.0 3 | * http://code.google.com/p/crypto-js/ 4 | * Copyright (c) 2009, Jeff Mott. All rights reserved. 5 | * http://code.google.com/p/crypto-js/wiki/License 6 | * 7 | * A JavaScript implementation of the RIPEMD-160 Algorithm 8 | * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009. 9 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet 10 | * Distributed under the BSD License 11 | * See http://pajhome.org.uk/crypt/md5 for details. 12 | * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/ 13 | * Ported to Crypto-JS by Stefan Thomas. 14 | */ 15 | 16 | (function () { 17 | // Shortcuts 18 | var C = Crypto, 19 | util = C.util, 20 | charenc = C.charenc, 21 | UTF8 = charenc.UTF8, 22 | Binary = charenc.Binary; 23 | 24 | // Convert a byte array to little-endian 32-bit words 25 | util.bytesToLWords = function (bytes) { 26 | 27 | var output = Array(bytes.length >> 2); 28 | for (var i = 0; i < output.length; i++) 29 | output[i] = 0; 30 | for (var i = 0; i < bytes.length * 8; i += 8) 31 | output[i>>5] |= (bytes[i / 8] & 0xFF) << (i%32); 32 | return output; 33 | }; 34 | 35 | // Convert little-endian 32-bit words to a byte array 36 | util.lWordsToBytes = function (words) { 37 | var output = []; 38 | for (var i = 0; i < words.length * 32; i += 8) 39 | output.push((words[i>>5] >>> (i % 32)) & 0xff); 40 | return output; 41 | }; 42 | 43 | // Public API 44 | var RIPEMD160 = C.RIPEMD160 = function (message, options) { 45 | var digestbytes = util.lWordsToBytes(RIPEMD160._rmd160(message)); 46 | return options && options.asBytes ? digestbytes : 47 | options && options.asString ? Binary.bytesToString(digestbytes) : 48 | util.bytesToHex(digestbytes); 49 | }; 50 | 51 | // The core 52 | RIPEMD160._rmd160 = function (message) 53 | { 54 | // Convert to byte array 55 | if (message.constructor == String) message = UTF8.stringToBytes(message); 56 | 57 | var x = util.bytesToLWords(message), 58 | len = message.length * 8; 59 | 60 | /* append padding */ 61 | x[len >> 5] |= 0x80 << (len % 32); 62 | x[(((len + 64) >>> 9) << 4) + 14] = len; 63 | 64 | var h0 = 0x67452301; 65 | var h1 = 0xefcdab89; 66 | var h2 = 0x98badcfe; 67 | var h3 = 0x10325476; 68 | var h4 = 0xc3d2e1f0; 69 | 70 | for (var i = 0; i < x.length; i += 16) { 71 | var T; 72 | var A1 = h0, B1 = h1, C1 = h2, D1 = h3, E1 = h4; 73 | var A2 = h0, B2 = h1, C2 = h2, D2 = h3, E2 = h4; 74 | for (var j = 0; j <= 79; ++j) { 75 | T = safe_add(A1, rmd160_f(j, B1, C1, D1)); 76 | T = safe_add(T, x[i + rmd160_r1[j]]); 77 | T = safe_add(T, rmd160_K1(j)); 78 | T = safe_add(bit_rol(T, rmd160_s1[j]), E1); 79 | A1 = E1; E1 = D1; D1 = bit_rol(C1, 10); C1 = B1; B1 = T; 80 | T = safe_add(A2, rmd160_f(79-j, B2, C2, D2)); 81 | T = safe_add(T, x[i + rmd160_r2[j]]); 82 | T = safe_add(T, rmd160_K2(j)); 83 | T = safe_add(bit_rol(T, rmd160_s2[j]), E2); 84 | A2 = E2; E2 = D2; D2 = bit_rol(C2, 10); C2 = B2; B2 = T; 85 | } 86 | T = safe_add(h1, safe_add(C1, D2)); 87 | h1 = safe_add(h2, safe_add(D1, E2)); 88 | h2 = safe_add(h3, safe_add(E1, A2)); 89 | h3 = safe_add(h4, safe_add(A1, B2)); 90 | h4 = safe_add(h0, safe_add(B1, C2)); 91 | h0 = T; 92 | } 93 | return [h0, h1, h2, h3, h4]; 94 | } 95 | 96 | function rmd160_f(j, x, y, z) 97 | { 98 | return ( 0 <= j && j <= 15) ? (x ^ y ^ z) : 99 | (16 <= j && j <= 31) ? (x & y) | (~x & z) : 100 | (32 <= j && j <= 47) ? (x | ~y) ^ z : 101 | (48 <= j && j <= 63) ? (x & z) | (y & ~z) : 102 | (64 <= j && j <= 79) ? x ^ (y | ~z) : 103 | "rmd160_f: j out of range"; 104 | } 105 | function rmd160_K1(j) 106 | { 107 | return ( 0 <= j && j <= 15) ? 0x00000000 : 108 | (16 <= j && j <= 31) ? 0x5a827999 : 109 | (32 <= j && j <= 47) ? 0x6ed9eba1 : 110 | (48 <= j && j <= 63) ? 0x8f1bbcdc : 111 | (64 <= j && j <= 79) ? 0xa953fd4e : 112 | "rmd160_K1: j out of range"; 113 | } 114 | function rmd160_K2(j) 115 | { 116 | return ( 0 <= j && j <= 15) ? 0x50a28be6 : 117 | (16 <= j && j <= 31) ? 0x5c4dd124 : 118 | (32 <= j && j <= 47) ? 0x6d703ef3 : 119 | (48 <= j && j <= 63) ? 0x7a6d76e9 : 120 | (64 <= j && j <= 79) ? 0x00000000 : 121 | "rmd160_K2: j out of range"; 122 | } 123 | var rmd160_r1 = [ 124 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 125 | 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 126 | 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 127 | 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 128 | 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 129 | ]; 130 | var rmd160_r2 = [ 131 | 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 132 | 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 133 | 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 134 | 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 135 | 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 136 | ]; 137 | var rmd160_s1 = [ 138 | 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 139 | 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 140 | 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 141 | 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 142 | 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 143 | ]; 144 | var rmd160_s2 = [ 145 | 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 146 | 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 147 | 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 148 | 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 149 | 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 150 | ]; 151 | 152 | /* 153 | * Add integers, wrapping at 2^32. This uses 16-bit operations internally 154 | * to work around bugs in some JS interpreters. 155 | */ 156 | function safe_add(x, y) 157 | { 158 | var lsw = (x & 0xFFFF) + (y & 0xFFFF); 159 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16); 160 | return (msw << 16) | (lsw & 0xFFFF); 161 | } 162 | 163 | /* 164 | * Bitwise rotate a 32-bit number to the left. 165 | */ 166 | function bit_rol(num, cnt) 167 | { 168 | return (num << cnt) | (num >>> (32 - cnt)); 169 | } 170 | })(); 171 | -------------------------------------------------------------------------------- /src/util.js: -------------------------------------------------------------------------------- 1 | // BigInteger monkey patching 2 | BigInteger.valueOf = nbv; 3 | 4 | /** 5 | * Returns a byte array representation of the big integer. 6 | * 7 | * This returns the absolute of the contained value in big endian 8 | * form. A value of zero results in an empty array. 9 | */ 10 | BigInteger.prototype.toByteArrayUnsigned = function () { 11 | var ba = this.abs().toByteArray(); 12 | if (ba.length) { 13 | if (ba[0] == 0) { 14 | ba = ba.slice(1); 15 | } 16 | return ba.map(function (v) { 17 | return (v < 0) ? v + 256 : v; 18 | }); 19 | } else { 20 | // Empty array, nothing to do 21 | return ba; 22 | } 23 | }; 24 | 25 | /** 26 | * Turns a byte array into a big integer. 27 | * 28 | * This function will interpret a byte array as a big integer in big 29 | * endian notation and ignore leading zeros. 30 | */ 31 | BigInteger.fromByteArrayUnsigned = function (ba) { 32 | if (!ba.length) { 33 | return ba.valueOf(0); 34 | } else if (ba[0] & 0x80) { 35 | // Prepend a zero so the BigInteger class doesn't mistake this 36 | // for a negative integer. 37 | return new BigInteger([0].concat(ba)); 38 | } else { 39 | return new BigInteger(ba); 40 | } 41 | }; 42 | 43 | /** 44 | * Converts big integer to signed byte representation. 45 | * 46 | * The format for this value uses a the most significant bit as a sign 47 | * bit. If the most significant bit is already occupied by the 48 | * absolute value, an extra byte is prepended and the sign bit is set 49 | * there. 50 | * 51 | * Examples: 52 | * 53 | * 0 => 0x00 54 | * 1 => 0x01 55 | * -1 => 0x81 56 | * 127 => 0x7f 57 | * -127 => 0xff 58 | * 128 => 0x0080 59 | * -128 => 0x8080 60 | * 255 => 0x00ff 61 | * -255 => 0x80ff 62 | * 16300 => 0x3fac 63 | * -16300 => 0xbfac 64 | * 62300 => 0x00f35c 65 | * -62300 => 0x80f35c 66 | */ 67 | BigInteger.prototype.toByteArraySigned = function () { 68 | var val = this.abs().toByteArrayUnsigned(); 69 | var neg = this.compareTo(BigInteger.ZERO) < 0; 70 | 71 | if (neg) { 72 | if (val[0] & 0x80) { 73 | val.unshift(0x80); 74 | } else { 75 | val[0] |= 0x80; 76 | } 77 | } else { 78 | if (val[0] & 0x80) { 79 | val.unshift(0x00); 80 | } 81 | } 82 | 83 | return val; 84 | }; 85 | 86 | /** 87 | * Parse a signed big integer byte representation. 88 | * 89 | * For details on the format please see BigInteger.toByteArraySigned. 90 | */ 91 | BigInteger.fromByteArraySigned = function (ba) { 92 | // Check for negative value 93 | if (ba[0] & 0x80) { 94 | // Remove sign bit 95 | ba[0] &= 0x7f; 96 | 97 | return BigInteger.fromByteArrayUnsigned(ba).negate(); 98 | } else { 99 | return BigInteger.fromByteArrayUnsigned(ba); 100 | } 101 | }; 102 | 103 | // Console ignore 104 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 105 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", 106 | "trace", "profile", "profileEnd"]; 107 | 108 | if ("undefined" == typeof window.console) window.console = {}; 109 | for (var i = 0; i < names.length; ++i) 110 | if ("undefined" == typeof window.console[names[i]]) 111 | window.console[names[i]] = function() {}; 112 | 113 | // Bitcoin utility functions 114 | Bitcoin.Util = { 115 | /** 116 | * Cross-browser compatibility version of Array.isArray. 117 | */ 118 | isArray: Array.isArray || function(o) 119 | { 120 | return Object.prototype.toString.call(o) === '[object Array]'; 121 | }, 122 | 123 | /** 124 | * Create an array of a certain length filled with a specific value. 125 | */ 126 | makeFilledArray: function (len, val) 127 | { 128 | var array = []; 129 | var i = 0; 130 | while (i < len) { 131 | array[i++] = val; 132 | } 133 | return array; 134 | }, 135 | 136 | /** 137 | * Turn an integer into a "var_int". 138 | * 139 | * "var_int" is a variable length integer used by Bitcoin's binary format. 140 | * 141 | * Returns a byte array. 142 | */ 143 | numToVarInt: function (i) 144 | { 145 | if (i < 0xfd) { 146 | // unsigned char 147 | return [i]; 148 | } else if (i <= 1<<16) { 149 | // unsigned short (LE) 150 | return [0xfd, i >>> 8, i & 255]; 151 | } else if (i <= 1<<32) { 152 | // unsigned int (LE) 153 | return [0xfe].concat(Crypto.util.wordsToBytes([i])); 154 | } else { 155 | // unsigned long long (LE) 156 | return [0xff].concat(Crypto.util.wordsToBytes([i >>> 32, i])); 157 | } 158 | }, 159 | 160 | /** 161 | * Parse a Bitcoin value byte array, returning a BigInteger. 162 | */ 163 | valueToBigInt: function (valueBuffer) 164 | { 165 | if (valueBuffer instanceof BigInteger) return valueBuffer; 166 | 167 | // Prepend zero byte to prevent interpretation as negative integer 168 | return BigInteger.fromByteArrayUnsigned(valueBuffer); 169 | }, 170 | 171 | /** 172 | * Format a Bitcoin value as a string. 173 | * 174 | * Takes a BigInteger or byte-array and returns that amount of Bitcoins in a 175 | * nice standard formatting. 176 | * 177 | * Examples: 178 | * 12.3555 179 | * 0.1234 180 | * 900.99998888 181 | * 34.00 182 | */ 183 | formatValue: function (valueBuffer) { 184 | var value = this.valueToBigInt(valueBuffer).toString(); 185 | var integerPart = value.length > 8 ? value.substr(0, value.length-8) : '0'; 186 | var decimalPart = value.length > 8 ? value.substr(value.length-8) : value; 187 | while (decimalPart.length < 8) decimalPart = "0"+decimalPart; 188 | decimalPart = decimalPart.replace(/0*$/, ''); 189 | while (decimalPart.length < 2) decimalPart += "0"; 190 | return integerPart+"."+decimalPart; 191 | }, 192 | 193 | /** 194 | * Parse a floating point string as a Bitcoin value. 195 | * 196 | * Keep in mind that parsing user input is messy. You should always display 197 | * the parsed value back to the user to make sure we understood his input 198 | * correctly. 199 | */ 200 | parseValue: function (valueString) { 201 | // TODO: Detect other number formats (e.g. comma as decimal separator) 202 | var valueComp = valueString.split('.'); 203 | var integralPart = valueComp[0]; 204 | var fractionalPart = valueComp[1] || "0"; 205 | while (fractionalPart.length < 8) fractionalPart += "0"; 206 | fractionalPart = fractionalPart.replace(/^0+/g, ''); 207 | var value = BigInteger.valueOf(parseInt(integralPart)); 208 | value = value.multiply(BigInteger.valueOf(100000000)); 209 | value = value.add(BigInteger.valueOf(parseInt(fractionalPart))); 210 | return value; 211 | }, 212 | 213 | /** 214 | * Calculate RIPEMD160(SHA256(data)). 215 | * 216 | * Takes an arbitrary byte array as inputs and returns the hash as a byte 217 | * array. 218 | */ 219 | sha256ripe160: function (data) { 220 | return Crypto.RIPEMD160(Crypto.SHA256(data, {asBytes: true}), {asBytes: true}); 221 | } 222 | }; 223 | 224 | for (var i in Crypto.util) { 225 | if (Crypto.util.hasOwnProperty(i)) { 226 | Bitcoin.Util[i] = Crypto.util[i]; 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /src/jsbn/sec.js: -------------------------------------------------------------------------------- 1 | // Named EC curves 2 | 3 | // Requires ec.js, jsbn.js, and jsbn2.js 4 | 5 | // ---------------- 6 | // X9ECParameters 7 | 8 | // constructor 9 | function X9ECParameters(curve,g,n,h) { 10 | this.curve = curve; 11 | this.g = g; 12 | this.n = n; 13 | this.h = h; 14 | } 15 | 16 | function x9getCurve() { 17 | return this.curve; 18 | } 19 | 20 | function x9getG() { 21 | return this.g; 22 | } 23 | 24 | function x9getN() { 25 | return this.n; 26 | } 27 | 28 | function x9getH() { 29 | return this.h; 30 | } 31 | 32 | X9ECParameters.prototype.getCurve = x9getCurve; 33 | X9ECParameters.prototype.getG = x9getG; 34 | X9ECParameters.prototype.getN = x9getN; 35 | X9ECParameters.prototype.getH = x9getH; 36 | 37 | // ---------------- 38 | // SECNamedCurves 39 | 40 | function fromHex(s) { return new BigInteger(s, 16); } 41 | 42 | function secp128r1() { 43 | // p = 2^128 - 2^97 - 1 44 | var p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF"); 45 | var a = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC"); 46 | var b = fromHex("E87579C11079F43DD824993C2CEE5ED3"); 47 | //byte[] S = Hex.decode("000E0D4D696E6768756151750CC03A4473D03679"); 48 | var n = fromHex("FFFFFFFE0000000075A30D1B9038A115"); 49 | var h = BigInteger.ONE; 50 | var curve = new ECCurveFp(p, a, b); 51 | var G = curve.decodePointHex("04" 52 | + "161FF7528B899B2D0C28607CA52C5B86" 53 | + "CF5AC8395BAFEB13C02DA292DDED7A83"); 54 | return new X9ECParameters(curve, G, n, h); 55 | } 56 | 57 | function secp160k1() { 58 | // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1 59 | var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73"); 60 | var a = BigInteger.ZERO; 61 | var b = fromHex("7"); 62 | //byte[] S = null; 63 | var n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3"); 64 | var h = BigInteger.ONE; 65 | var curve = new ECCurveFp(p, a, b); 66 | var G = curve.decodePointHex("04" 67 | + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB" 68 | + "938CF935318FDCED6BC28286531733C3F03C4FEE"); 69 | return new X9ECParameters(curve, G, n, h); 70 | } 71 | 72 | function secp160r1() { 73 | // p = 2^160 - 2^31 - 1 74 | var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF"); 75 | var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC"); 76 | var b = fromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45"); 77 | //byte[] S = Hex.decode("1053CDE42C14D696E67687561517533BF3F83345"); 78 | var n = fromHex("0100000000000000000001F4C8F927AED3CA752257"); 79 | var h = BigInteger.ONE; 80 | var curve = new ECCurveFp(p, a, b); 81 | var G = curve.decodePointHex("04" 82 | + "4A96B5688EF573284664698968C38BB913CBFC82" 83 | + "23A628553168947D59DCC912042351377AC5FB32"); 84 | return new X9ECParameters(curve, G, n, h); 85 | } 86 | 87 | function secp192k1() { 88 | // p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1 89 | var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"); 90 | var a = BigInteger.ZERO; 91 | var b = fromHex("3"); 92 | //byte[] S = null; 93 | var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"); 94 | var h = BigInteger.ONE; 95 | var curve = new ECCurveFp(p, a, b); 96 | var G = curve.decodePointHex("04" 97 | + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D" 98 | + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"); 99 | return new X9ECParameters(curve, G, n, h); 100 | } 101 | 102 | function secp192r1() { 103 | // p = 2^192 - 2^64 - 1 104 | var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"); 105 | var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"); 106 | var b = fromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"); 107 | //byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5"); 108 | var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"); 109 | var h = BigInteger.ONE; 110 | var curve = new ECCurveFp(p, a, b); 111 | var G = curve.decodePointHex("04" 112 | + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012" 113 | + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"); 114 | return new X9ECParameters(curve, G, n, h); 115 | } 116 | 117 | function secp224r1() { 118 | // p = 2^224 - 2^96 + 1 119 | var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"); 120 | var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"); 121 | var b = fromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4"); 122 | //byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5"); 123 | var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"); 124 | var h = BigInteger.ONE; 125 | var curve = new ECCurveFp(p, a, b); 126 | var G = curve.decodePointHex("04" 127 | + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21" 128 | + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"); 129 | return new X9ECParameters(curve, G, n, h); 130 | } 131 | 132 | function secp256k1() { 133 | // p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 134 | var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"); 135 | var a = BigInteger.ZERO; 136 | var b = fromHex("7"); 137 | //byte[] S = null; 138 | var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"); 139 | var h = BigInteger.ONE; 140 | var curve = new ECCurveFp(p, a, b); 141 | var G = curve.decodePointHex("04" 142 | + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" 143 | + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"); 144 | return new X9ECParameters(curve, G, n, h); 145 | } 146 | 147 | function secp256r1() { 148 | // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1 149 | var p = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"); 150 | var a = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"); 151 | var b = fromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"); 152 | //byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90"); 153 | var n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"); 154 | var h = BigInteger.ONE; 155 | var curve = new ECCurveFp(p, a, b); 156 | var G = curve.decodePointHex("04" 157 | + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" 158 | + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"); 159 | return new X9ECParameters(curve, G, n, h); 160 | } 161 | 162 | // TODO: make this into a proper hashtable 163 | function getSECCurveByName(name) { 164 | if(name == "secp128r1") return secp128r1(); 165 | if(name == "secp160k1") return secp160k1(); 166 | if(name == "secp160r1") return secp160r1(); 167 | if(name == "secp192k1") return secp192k1(); 168 | if(name == "secp192r1") return secp192r1(); 169 | if(name == "secp224r1") return secp224r1(); 170 | if(name == "secp256k1") return secp256k1(); 171 | if(name == "secp256r1") return secp256r1(); 172 | return null; 173 | } 174 | -------------------------------------------------------------------------------- /src/bitcoin.js: -------------------------------------------------------------------------------- 1 | (function (exports) { 2 | var Bitcoin = exports; 3 | 4 | if ('object' !== typeof module) { 5 | Bitcoin.EventEmitter = EventEmitter; 6 | } 7 | })( 8 | 'object' === typeof module ? module.exports : (window.Bitcoin = {}) 9 | ); 10 | 11 | /* 12 | function makeKeypair() 13 | { 14 | // Generate private key 15 | var n = ecparams.getN(); 16 | var n1 = n.subtract(BigInteger.ONE); 17 | var r = new BigInteger(n.bitLength(), rng); 18 | 19 | var privateKey = r.mod(n1).add(BigInteger.ONE); 20 | 21 | // Generate public key 22 | var G = ecparams.getG(); 23 | var publicPoint = G.multiply(privateKey); 24 | 25 | return {priv: privateKey, pubkey: publicPoint}; 26 | }; 27 | 28 | function serializeTransaction(tx) 29 | { 30 | var buffer = []; 31 | buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(tx.version)])); 32 | buffer = buffer.concat(numToVarInt(tx.ins.length)); 33 | for (var i = 0; i < tx.ins.length; i++) { 34 | var txin = tx.ins[i]; 35 | buffer = buffer.concat(Crypto.util.base64ToBytes(txin.outpoint.hash)); 36 | buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.index)])); 37 | var scriptBytes = Crypto.util.base64ToBytes(txin.script); 38 | buffer = buffer.concat(numToVarInt(scriptBytes.length)); 39 | buffer = buffer.concat(scriptBytes); 40 | buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.sequence)])); 41 | } 42 | buffer = buffer.concat(numToVarInt(tx.outs.length)); 43 | for (var i = 0; i < tx.outs.length; i++) { 44 | var txout = tx.outs[i]; 45 | var valueHex = (new BigInteger(txout.value, 10)).toString(16); 46 | while (valueHex.length < 16) valueHex = "0" + valueHex; 47 | buffer = buffer.concat(Crypto.util.hexToBytes(valueHex)); 48 | var scriptBytes = Crypto.util.base64ToBytes(txout.script); 49 | buffer = buffer.concat(numToVarInt(scriptBytes.length)); 50 | buffer = buffer.concat(scriptBytes); 51 | } 52 | buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(tx.lock_time)])); 53 | 54 | return buffer; 55 | }; 56 | 57 | var OP_CODESEPARATOR = 171; 58 | 59 | var SIGHASH_ALL = 1; 60 | var SIGHASH_NONE = 2; 61 | var SIGHASH_SINGLE = 3; 62 | var SIGHASH_ANYONECANPAY = 80; 63 | 64 | function hashTransactionForSignature(scriptCode, tx, inIndex, hashType) 65 | { 66 | // TODO: We need to actually deep copy here 67 | var txTmp = tx; 68 | 69 | // In case concatenating two scripts ends up with two codeseparators, 70 | // or an extra one at the end, this prevents all those possible incompatibilities. 71 | scriptCode = scriptCode.filter(function (val) { 72 | return val !== OP_CODESEPARATOR; 73 | }); 74 | 75 | // Blank out other inputs' signatures 76 | for (var i = 0; i < txTmp.ins.length; i++) { 77 | txTmp.ins[i].script = Crypto.util.bytesToBase64([]); 78 | } 79 | txTmp.ins[inIndex].script = Crypto.util.bytesToBase64(scriptCode); 80 | 81 | // Blank out some of the outputs 82 | if ((hashType & 0x1f) == SIGHASH_NONE) { 83 | txTmp.outs = []; 84 | 85 | // Let the others update at will 86 | for (var i = 0; i < txTmp.ins.length; i++) 87 | if (i != inIndex) 88 | txTmp.ins[i].sequence = 0; 89 | } else if ((hashType & 0x1f) == SIGHASH_SINGLE) { 90 | // TODO: Implement 91 | } 92 | 93 | // Blank out other inputs completely, not recommended for open transactions 94 | if (hashType & SIGHASH_ANYONECANPAY) { 95 | txTmp.ins = [txTmp.ins[inIndex]]; 96 | } 97 | 98 | var buffer = serializeTransaction(txTmp); 99 | 100 | buffer.concat(Crypto.util.wordsToBytes([parseInt(hashType)])); 101 | 102 | console.log(buffer); 103 | 104 | return Crypto.SHA256(Crypto.SHA256(buffer, {asBytes: true}), {asBytes: true}); 105 | }; 106 | 107 | function verifyTransactionSignature(tx) { 108 | var hash = hashTransactionForSignature([], tx, 0, 0); 109 | return Crypto.util.bytesToHex(hash); 110 | }; 111 | 112 | function numToVarInt(i) 113 | { 114 | // TODO: THIS IS TOTALLY UNTESTED! 115 | if (i < 0xfd) { 116 | // unsigned char 117 | return [i]; 118 | } else if (i <= 1<<16) { 119 | // unsigned short (LE) 120 | return [0xfd, i >>> 8, i & 255]; 121 | } else if (i <= 1<<32) { 122 | // unsigned int (LE) 123 | return [0xfe].concat(Crypto.util.wordsToBytes([i])); 124 | } else { 125 | // unsigned long long (LE) 126 | return [0xff].concat(Crypto.util.wordsToBytes([i >>> 32, i])); 127 | } 128 | }; 129 | 130 | var testTx = { 131 | "version":"1", 132 | "lock_time":"0", 133 | "block": { 134 | "hash":"N/A", 135 | "height":115806 136 | }, 137 | "index":6, 138 | "hash":"WUFzjKubG1kqfJWMb4qZdlhU2F3l5NGXN7AUg8Jwl14=", 139 | "ins":[{ 140 | "outpoint":{ 141 | "hash":"nqcbMM1oRhfLdZga11q7x0CpUMujm+vtxHXO9V0gnwE=", 142 | "index":0 143 | }, 144 | "script":"RzBEAiB2XXkx1pca9SlfCmCGNUVf+h2sAFBttcxG1VnypIcvEgIgXrOp7LSdYBYp3nPsQAz8BOLD3K4pAlXfZImP1rkzk2EBQQRi7NcODzNfnVqLtG79Axp5UF6EhFIhCmzqKqssfKpfCIOmzCuXEeDFUFvFzeGLJx5N+wp2qRS1TqYezGD3yERk", 145 | "sequence":4294967295 146 | }], 147 | "outs":[{ 148 | "value":"3000000000", 149 | "script":"dqkUBLZwqhAPRVgZvwI8MN5gLHbU8NOIrA==" 150 | },{ 151 | "value":"25937000000", 152 | "script":"dqkUQ82gJ0O5vOBg6yK5/yorLLV5zLKIrA==" 153 | }] 154 | }; 155 | 156 | TODO: Make this stuff into test cases ;) 157 | $(function () { 158 | var key = new Bitcoin.ECKey(Crypto.util.hexToBytes("5c0b98e524ad188ddef35dc6abba13c34a351a05409e5d285403718b93336a4a")); 159 | key = new Bitcoin.ECKey(Crypto.util.hexToBytes("180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19")); 160 | //console.log(key.getBitcoinAddress().toString()); 161 | //var message = Crypto.util.hexToBytes("2aec28d323ee7b06a799d540d224b351161fe48967174ca5e43164e86137da11"); 162 | //message = [0]; 163 | //var out = key.sign(message); 164 | //console.log("pubkey: "+Crypto.util.bytesToHex(key.getPub())); 165 | //console.log("sig: "+Crypto.util.bytesToHex(out)); 166 | 167 | //console.log(key.verify(message, out)); 168 | 169 | //console.log(Bitcoin.ECDSA.verify(message, Crypto.util.hexToBytes("3046022100dffbc26774fc841bbe1c1362fd643609c6e42dcb274763476d87af2c0597e89e022100c59e3c13b96b316cae9fa0ab0260612c7a133a6fe2b3445b6bf80b3123bf274d"), Crypto.util.hexToBytes("0401de173aa944eacf7e44e5073baca93fb34fe4b7897a1c82c92dfdc8a1f75ef58cd1b06e8052096980cb6e1ad6d3df143c34b3d7394bae2782a4df570554c2fb"))); 170 | 171 | //console.log(Bitcoin.ECDSA.verify(Crypto.util.hexToBytes("230aba77ccde46bb17fcb0295a92c0cc42a6ea9f439aaadeb0094625f49e6ed8"), Crypto.util.hexToBytes("3046022100a3ee5408f0003d8ef00ff2e0537f54ba09771626ff70dca1f01296b05c510e85022100d4dc70a5bb50685b65833a97e536909a6951dd247a2fdbde6688c33ba6d6407501"),Crypto.util.hexToBytes("04a19c1f07c7a0868d86dbb37510305843cc730eb3bea8a99d92131f44950cecd923788419bfef2f635fad621d753f30d4b4b63b29da44b4f3d92db974537ad5a4"))); 172 | //console.log(Bitcoin.ECDSA.verify(Crypto.util.hexToBytes("c2c75bb77d7a5acddceb1d45ceef58e7451fd0d3abc9d4c16df7848eefafe00d"), Crypto.util.hexToBytes("3045022100ff9362dadcbf1f6ef954bc8eb27144bbb4f49abd32be1eb04c311151dcf4bcf802205112c2ca6a25aefb8be98bf460c5a9056c01253f31e118d80b81ec9604e3201a01"),Crypto.util.hexToBytes("04fe62ce7892ec209310c176ef7f06565865e286e8699e884603657efa9aa51086785099d544d4e04f1f7b4b065205c1783fade8daf4ba1e0d1962292e8eb722cd"))); 173 | }); 174 | // 175 | */ 176 | -------------------------------------------------------------------------------- /demo/split-key.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Two-party ECDSA signature generation 5 | 6 | 7 | 32 | 33 | 34 |

    Two-party ECDSA signature generation

    35 |

    Initialization

    36 |
    37 |

    Alice starts out with her share of the private key d1

    38 |
    39 | 40 | 41 |
    42 |

    And a Paillier keypair pk/sk

    43 |
    44 | 45 | 46 |
    47 |
    48 | 49 | 50 |
    51 |
    52 | 53 | 54 |
    55 |
    56 | 57 | 58 |
    59 |
    60 |
    61 |

    Bob starts out with his share d2 of the private key d

    62 |
    63 | 64 | 65 |
    66 |
    67 |

    Protocol

    68 |
    69 |

    First Alice generates her share of the one-time secret k1

    70 |
    71 | 72 | 73 |
    74 |

    And its inverse z1 = (k1)-1 mod n

    75 |
    76 | 77 | 78 |
    79 |

    She also calculates Q1 = k1G

    80 |
    81 | 82 | 83 |
    84 |

    She then encrypts z1 using Paillier to create α = Epk(z1)

    85 |
    86 | 87 | 88 |
    89 |

    And β = Epk(d1z1 mod n)

    90 |
    91 | 92 | 93 |
    94 |

    And also generates an encrypted blinding factor A = Epk(c) for some c ∈ [1, nP/nEC]

    95 |
    96 | 97 | 98 |
    99 |

    Alice composes the encrypted signature σ1 = (α ×pk e) +pk (β ×pk r) +pk (A ×pk n)

    100 |
    101 | 102 | 103 |
    104 |

    She deterministically rerandomizes it to receive σ1' = σ1HASH(σ1)n mod n2

    105 |
    106 | 107 | 108 |
    109 |

    And decrypts σ1' to receive s1

    110 |
    111 | 112 | 113 |
    114 |

    And v', the randomizing factor in σ1'

    115 |
    116 | 117 | 118 |
    119 |
    120 |
    121 | Q1, α, β, message, e, pk, A, s1, v' 122 |
    123 |
    124 |

    Bob validates Q1 by ensuring that 125 |

      126 |
    1. Q1 ≠ O
    2. 127 |
    3. xQ1 and yQ1 are in the interval [1,n - 1]
    4. 128 |
    5. yQ12 ≡ xQ13 + axQ1 + b (mod p)
    6. 129 |
    7. nQ1 = O
    8. 130 |

    131 |

    And verifies the message to be signed

    132 |

    He then verifies s1 as a valid signature

    133 |

    Bob also calculates σ1' from α, β and A

    134 |
    135 | 136 | 137 |
    138 |

    And verifies it matches Epk(s1, v')

    139 |

    He then generates his share k2 of the private one-time value k

    140 |
    141 | 142 | 143 |
    144 |

    And its inverse z2 = (k2)-1 mod n

    145 |
    146 | 147 | 148 |
    149 |

    He can calculate r = xQ where Q(xQ, yQ) = k2Q1

    150 |
    151 | 152 | 153 |
    154 |

    And Q2 = k2G

    155 |
    156 | 157 | 158 |
    159 |

    Bob prepares a random value B ∈ [1, nP/nEC] to use for blinding

    160 |

    161 | 162 | 163 |
    164 |

    Finally he calculates σ = (α ×pk z2e) +pk (β ×pk z2d2r) +pk Epk(BnEC)

    165 |
    166 | 167 | 168 |
    169 |
    170 |
    171 | Q2, r, σ 172 |
    173 |
    174 |

    Alice confirms Q2 is a valid public point 175 |

      176 |
    1. Q2 ≠ O
    2. 177 |
    3. xQ2 and yQ2 are in the interval [1,n - 1]
    4. 178 |
    5. yQ22 ≡ xQ23 + axQ2 + b (mod p)
    6. 179 |
    7. nQ2 = O
    8. 180 |

    181 |

    She now calculates r = xQ where Q = k1Q2 and matches it against what Bob claimed

    182 |

    She decrypts σ to receive s = Dsk(σ)

    183 |
    184 | 185 | 186 |
    187 |

    She verifies the signature using r and the combined public key before publishing.

    188 |
    189 | 190 | 191 |
    192 |
    193 | 194 | 195 | -------------------------------------------------------------------------------- /demo/split-key.js: -------------------------------------------------------------------------------- 1 | var window = this; 2 | 3 | importScripts( 4 | "../src/crypto-js/crypto.js", 5 | "../src/crypto-js/sha256.js", 6 | "../src/jsbn/prng4.js", 7 | "../src/jsbn/rng.js", 8 | "../src/jsbn/jsbn.js", 9 | "../src/jsbn/jsbn2.js", 10 | 11 | "../src/jsbn/ec.js", 12 | "../src/jsbn/sec.js", 13 | "../src/events/eventemitter.js", 14 | "../src/bitcoin.js", 15 | "../src/util.js", 16 | "../src/base58.js", 17 | 18 | "../src/address.js", 19 | "../src/ecdsa.js", 20 | "../src/paillier.js" 21 | ); 22 | 23 | function hex(value) { 24 | if ("function" === typeof value.getEncoded) { 25 | return Crypto.util.bytesToHex(value.getEncoded()); 26 | } else if ("function" === typeof value.toByteArrayUnsigned) { 27 | return Crypto.util.bytesToHex(value.toByteArrayUnsigned()); 28 | } else if (Array.isArray(value)) { 29 | return Crypto.util.bytesToHex(value); 30 | } 31 | return value; 32 | }; 33 | function ff(field, value) { 34 | value = hex(value); 35 | postMessage({ "cmd": "ff", "field": field, "value": value }); 36 | }; 37 | 38 | function log() { 39 | postMessage({ "cmd": "log", "args": Array.prototype.slice.apply(arguments) }); 40 | }; 41 | 42 | function start() { 43 | var ecparams = getSECCurveByName("secp256k1"); 44 | var rng = new SecureRandom(); 45 | 46 | var G = ecparams.getG(); 47 | var n = ecparams.getN(); 48 | 49 | G.validate(); 50 | 51 | var Alice = function (pubShare) { 52 | this.d1 = Bitcoin.ECDSA.getBigRandom(n); 53 | ff('d1', this.d1); 54 | 55 | this.paillier = Bitcoin.Paillier.generate(n.bitLength()*2+ 56 | Math.floor(Math.random()*10)); 57 | 58 | ff('p1_n', this.paillier.pub.n); 59 | ff('p1_g', this.paillier.pub.g); 60 | ff('p1_l', this.paillier.l); 61 | ff('p1_m', this.paillier.m); 62 | }; 63 | var Bob = function () { 64 | this.d2 = Bitcoin.ECDSA.getBigRandom(n); 65 | ff('d2', this.d2); 66 | }; 67 | 68 | Alice.prototype.getPub = function (P) { 69 | if (this.pub) return this.pub; 70 | 71 | P.validate(); 72 | 73 | return this.pub = P.multiply(this.d1).getEncoded(); 74 | }; 75 | 76 | Alice.prototype.getPubShare = function () { 77 | return G.multiply(this.d1); 78 | }; 79 | 80 | Bob.prototype.getPubShare = function () { 81 | return G.multiply(this.d2); 82 | }; 83 | 84 | Alice.prototype.step1 = function (message) { 85 | var hash = Crypto.SHA256(Crypto.SHA256(message, {asBytes: true}), {asBytes: true}); 86 | this.e = BigInteger.fromByteArrayUnsigned(hash).mod(n); 87 | 88 | this.k1 = Bitcoin.ECDSA.getBigRandom(n); 89 | ff('k1', this.k1); 90 | 91 | this.z1 = this.k1.modInverse(n); 92 | ff('z1', this.z1); 93 | 94 | var Q_1 = G.multiply(this.k1); 95 | ff('q1', Q_1); 96 | 97 | var alpha = this.paillier.encrypt(this.z1); 98 | ff('alpha', alpha); 99 | 100 | var beta = this.paillier.encrypt(this.d1.multiply(this.z1).mod(n)); 101 | ff('beta', beta); 102 | 103 | var r_1 = Q_1.getX().toBigInteger().mod(n); 104 | var A = this.paillier.encrypt(Bitcoin.ECDSA.getBigRandom(this.paillier.n.divide(n))); 105 | ff('A', A); 106 | var s_a = this.paillier.multiply(alpha, this.e); 107 | var s_b = this.paillier.multiply(beta, r_1); 108 | var sigma_1 = this.paillier.addCrypt(this.paillier.addCrypt(s_a, s_b), this.paillier.multiply(A, n)); 109 | ff('sigma_1', sigma_1); 110 | 111 | var e = Crypto.SHA256(sigma_1.toByteArrayUnsigned(), {asBytes: true}); 112 | e = BigInteger.fromByteArrayUnsigned(e); 113 | var sigma_1n = this.paillier.rerandomize(sigma_1, e); 114 | ff('sigma_1n', sigma_1n); 115 | 116 | var s_1 = this.paillier.decrypt(sigma_1n); 117 | ff('s_1', s_1); 118 | var v_n = this.paillier.decryptR(sigma_1n, s_1); 119 | ff('v_n', v_n); 120 | 121 | return { 122 | Q_1: Q_1, 123 | P_1: this.getPubShare(), 124 | alpha: alpha, 125 | beta: beta, 126 | message: message, 127 | paillier: this.paillier.pub, 128 | A: A, 129 | s_1: s_1, 130 | v_n: v_n 131 | }; 132 | }; 133 | 134 | Bob.prototype.step2 = function (pkg) { 135 | // ... In real life we would check that message is a valid transaction and 136 | // does what we want. 137 | 138 | // Throws exception on error 139 | pkg.Q_1.validate(); 140 | 141 | var hash = Crypto.SHA256(Crypto.SHA256(message, {asBytes: true}), {asBytes: true}); 142 | this.e = BigInteger.fromByteArrayUnsigned(hash).mod(n); 143 | 144 | this.paillier = pkg.paillier; 145 | this.alpha = pkg.alpha; 146 | this.beta = pkg.beta; 147 | 148 | var r_1 = pkg.Q_1.getX().toBigInteger().mod(n); 149 | var testSig = Bitcoin.ECDSA.serializeSig(r_1, pkg.s_1.mod(n)); 150 | if (!Bitcoin.ECDSA.verify(hash, testSig, pkg.P_1.getEncoded())) { 151 | throw new Error('Verification of s1 failed.'); 152 | } 153 | 154 | // Verify that alpha and beta are valid by generating and verifying sigma_1n 155 | var s_a_1 = this.paillier.multiply(this.alpha, this.e); 156 | var s_b_1 = this.paillier.multiply(this.beta, r_1); 157 | var sigma_1 = this.paillier.addCrypt(this.paillier.addCrypt(s_a_1, s_b_1), this.paillier.multiply(pkg.A, n)); 158 | 159 | var e = Crypto.SHA256(sigma_1.toByteArrayUnsigned(), {asBytes: true}); 160 | e = BigInteger.fromByteArrayUnsigned(e); 161 | var sigma_1n = this.paillier.rerandomize(sigma_1, e); 162 | ff('sigma_1n_b', sigma_1n); 163 | 164 | var sigma_1_verify = this.paillier.encrypt(pkg.s_1, pkg.v_n); 165 | if (!sigma_1n.equals(sigma_1_verify)) { 166 | throw new Error('Sigma ciphertext did not match expected value.'); 167 | } 168 | 169 | this.k2 = Bitcoin.ECDSA.getBigRandom(n); 170 | ff('k2', this.k2); 171 | 172 | this.z2 = this.k2.modInverse(n); 173 | ff('z2', this.z2); 174 | 175 | var Q_2 = G.multiply(this.k2); 176 | ff('q2', Q_2); 177 | 178 | var Q = pkg.Q_1.multiply(this.k2); 179 | this.r = Q.getX().toBigInteger().mod(n); 180 | ff('r', this.r); 181 | 182 | if (this.r.equals(BigInteger.ZERO)) { 183 | throw new Error('r must not be zero.'); 184 | } 185 | 186 | var B = Bitcoin.ECDSA.getBigRandom(this.paillier.n.divide(n)); 187 | ff('B', B); 188 | 189 | var p = this.paillier; 190 | var s_a = p.multiply(this.alpha, this.e.multiply(this.z2)); 191 | var s_b = p.multiply(this.beta, this.r.multiply(this.d2).multiply(this.z2)); 192 | var sigma = p.add(p.addCrypt(s_a, s_b), B.multiply(n)); 193 | ff('sigma', sigma); 194 | 195 | return { 196 | Q_2: Q_2, 197 | r: this.r, 198 | sigma: sigma 199 | }; 200 | }; 201 | 202 | Alice.prototype.step3 = function (pkg) { 203 | pkg.Q_2.validate(); 204 | 205 | var Q = pkg.Q_2.multiply(this.k1); 206 | this.r = Q.getX().toBigInteger().mod(n); 207 | 208 | if (!this.r.equals(pkg.r)) { 209 | throw new Error('Could not confirm value for r.'); 210 | } 211 | 212 | if (this.r.equals(BigInteger.ZERO)) { 213 | throw new Error('r must not be zero.'); 214 | } 215 | 216 | var s = this.paillier.decrypt(pkg.sigma).mod(n); 217 | ff('s', s); 218 | 219 | var sig = Bitcoin.ECDSA.serializeSig(this.r, s); 220 | 221 | var hash = this.e.toByteArrayUnsigned(); 222 | if (!Bitcoin.ECDSA.verify(hash, sig, this.getPub())) { 223 | throw new Error('Signature failed to verify.'); 224 | } 225 | 226 | return { 227 | r: this.r, 228 | s: s 229 | }; 230 | }; 231 | 232 | var message = "testmessage"; 233 | 234 | var bob = new Bob(); 235 | var pubShare = bob.getPubShare(); 236 | 237 | var alice = new Alice(pubShare); 238 | var pub = alice.getPub(pubShare); 239 | 240 | var pkg1 = alice.step1(message); 241 | var pkg2 = bob.step2(pkg1); 242 | var pkg3 = alice.step3(pkg2); 243 | 244 | var sig = Bitcoin.ECDSA.serializeSig(pkg3.r, pkg3.s); 245 | 246 | var kChk = alice.k1.multiply(bob.k2); 247 | var rChk = G.multiply(kChk).getX().toBigInteger(); 248 | log("r :", hex(pkg3.r)); 249 | log("r/CHK:", hex(rChk)); 250 | 251 | var hash = Crypto.SHA256(Crypto.SHA256(message, {asBytes: true}), {asBytes: true}); 252 | var eChk = BigInteger.fromByteArrayUnsigned(hash).mod(n); 253 | var dChk = alice.d1.multiply(bob.d2); 254 | var sChk = kChk.modInverse(n).multiply(eChk.add(dChk.multiply(rChk))).mod(n); 255 | log("s :", hex(pkg3.s)); 256 | log("s/CHK:", hex(sChk)); 257 | 258 | var sigChk = Bitcoin.ECDSA.serializeSig(rChk, sChk); 259 | log("sig :", hex(sig)); 260 | log("sig/CHK:", hex(sigChk)); 261 | 262 | var ver = Bitcoin.ECDSA.verify(hash, sig, pub); 263 | log("ver :", ver); 264 | log("ver/CHK:", Bitcoin.ECDSA.verify(hash, sigChk, pub)); 265 | log("ver/CTL:", Bitcoin.ECDSA.verify(hash, Bitcoin.ECDSA.sign(hash, dChk), pub)); 266 | ff("result", ver ? "SIGNATURE VALID" : "SIGNATURE INVALID"); 267 | 268 | var priv = Bitcoin.ECDSA.getBigRandom(n); 269 | pub = G.multiply(priv).getEncoded(); 270 | log("ver/GEN:", Bitcoin.ECDSA.verify(hash, Bitcoin.ECDSA.sign(hash, priv), pub)); 271 | }; 272 | 273 | self.onmessage = function (event) { 274 | try { 275 | start(); 276 | } catch(e) { 277 | var stack = e.stack.replace(/^[^\(]+?[\n$]/gm, '') 278 | .replace(/^\s+at\s+/gm, '') 279 | .replace(/^Object.\s*\(/gm, '{anonymous}()@') 280 | .split('\n'); 281 | log(e+'\n'+stack); 282 | } 283 | }; 284 | -------------------------------------------------------------------------------- /src/wallet.js: -------------------------------------------------------------------------------- 1 | Bitcoin.Wallet = (function () { 2 | var Script = Bitcoin.Script, 3 | TransactionIn = Bitcoin.TransactionIn, 4 | TransactionOut = Bitcoin.TransactionOut; 5 | 6 | var Wallet = function () { 7 | // Keychain 8 | // 9 | // The keychain is stored as a var in this closure to make accidental 10 | // serialization less likely. 11 | // 12 | // Any functions accessing this value therefore have to be defined in 13 | // the closure of this constructor. 14 | var keys = []; 15 | 16 | // Public hashes of our keys 17 | this.addressHashes = []; 18 | 19 | // Transaction data 20 | this.txIndex = {}; 21 | this.unspentOuts = []; 22 | 23 | // Other fields 24 | this.addressPointer = 0; 25 | 26 | /** 27 | * Add a key to the keychain. 28 | * 29 | * The corresponding public key can be provided as a second parameter. This 30 | * adds it to the cache in the ECKey object and avoid the need to 31 | * expensively calculate it later. 32 | */ 33 | this.addKey = function (key, pub) { 34 | if (!(key instanceof Bitcoin.ECKey)) { 35 | key = new Bitcoin.ECKey(key); 36 | } 37 | keys.push(key); 38 | 39 | if (pub) { 40 | if ("string" === typeof pub) { 41 | pub = Crypto.util.base64ToBytes(pub); 42 | } 43 | key.setPub(pub); 44 | } 45 | 46 | this.addressHashes.push(key.getBitcoinAddress().getHashBase64()); 47 | }; 48 | 49 | /** 50 | * Add multiple keys at once. 51 | */ 52 | this.addKeys = function (keys, pubs) { 53 | if ("string" === typeof keys) { 54 | keys = keys.split(','); 55 | } 56 | if ("string" === typeof pubs) { 57 | pubs = pubs.split(','); 58 | } 59 | var i; 60 | if (Array.isArray(pubs) && keys.length == pubs.length) { 61 | for (i = 0; i < keys.length; i++) { 62 | this.addKey(keys[i], pubs[i]); 63 | } 64 | } else { 65 | for (i = 0; i < keys.length; i++) { 66 | this.addKey(keys[i]); 67 | } 68 | } 69 | }; 70 | 71 | /** 72 | * Get the key chain. 73 | * 74 | * Returns an array of base64-encoded private values. 75 | */ 76 | this.getKeys = function () { 77 | var serializedWallet = []; 78 | 79 | for (var i = 0; i < keys.length; i++) { 80 | serializedWallet.push(keys[i].toString('base64')); 81 | } 82 | 83 | return serializedWallet; 84 | }; 85 | 86 | /** 87 | * Get the public keys. 88 | * 89 | * Returns an array of base64-encoded public keys. 90 | */ 91 | this.getPubKeys = function () { 92 | var pubs = []; 93 | 94 | for (var i = 0; i < keys.length; i++) { 95 | pubs.push(Crypto.util.bytesToBase64(keys[i].getPub())); 96 | } 97 | 98 | return pubs; 99 | }; 100 | 101 | /** 102 | * Delete all keys. 103 | */ 104 | this.clear = function () { 105 | keys = []; 106 | }; 107 | 108 | /** 109 | * Return the number of keys in this wallet. 110 | */ 111 | this.getLength = function () { 112 | return keys.length; 113 | }; 114 | 115 | /** 116 | * Get the addresses for this wallet. 117 | * 118 | * Returns an array of Address objects. 119 | */ 120 | this.getAllAddresses = function () { 121 | var addresses = []; 122 | for (var i = 0; i < keys.length; i++) { 123 | addresses.push(keys[i].getBitcoinAddress()); 124 | } 125 | return addresses; 126 | }; 127 | 128 | this.getCurAddress = function () { 129 | if (keys[this.addressPointer]) { 130 | return keys[this.addressPointer].getBitcoinAddress(); 131 | } else { 132 | return null; 133 | } 134 | }; 135 | 136 | /** 137 | * Go to the next address. 138 | * 139 | * If there are no more new addresses available, one will be generated 140 | * automatically. 141 | */ 142 | this.getNextAddress = function () { 143 | this.addressPointer++; 144 | if (!keys[this.addressPointer]) { 145 | this.generateAddress(); 146 | } 147 | return keys[this.addressPointer].getBitcoinAddress(); 148 | }; 149 | 150 | /** 151 | * Sign a hash with a key. 152 | * 153 | * This method expects the pubKeyHash as the first parameter and the hash 154 | * to be signed as the second parameter. 155 | */ 156 | this.signWithKey = function (pubKeyHash, hash) { 157 | pubKeyHash = Crypto.util.bytesToBase64(pubKeyHash); 158 | for (var i = 0; i < this.addressHashes.length; i++) { 159 | if (this.addressHashes[i] == pubKeyHash) { 160 | return keys[i].sign(hash); 161 | } 162 | } 163 | throw new Error("Missing key for signature"); 164 | }; 165 | 166 | /** 167 | * Retrieve the corresponding pubKey for a pubKeyHash. 168 | * 169 | * This function only works if the pubKey in question is part of this 170 | * wallet. 171 | */ 172 | this.getPubKeyFromHash = function (pubKeyHash) { 173 | pubKeyHash = Crypto.util.bytesToBase64(pubKeyHash); 174 | for (var i = 0; i < this.addressHashes.length; i++) { 175 | if (this.addressHashes[i] == pubKeyHash) { 176 | return keys[i].getPub(); 177 | } 178 | } 179 | throw new Error("Hash unknown"); 180 | }; 181 | }; 182 | 183 | Wallet.prototype.generateAddress = function () { 184 | this.addKey(new Bitcoin.ECKey()); 185 | }; 186 | 187 | /** 188 | * Add a transaction to the wallet's processed transaction. 189 | * 190 | * This will add a transaction to the wallet, updating its balance and 191 | * available unspent outputs. 192 | */ 193 | Wallet.prototype.process = function (tx) { 194 | if (this.txIndex[tx.hash]) return; 195 | 196 | var j; 197 | var k; 198 | var hash; 199 | // Gather outputs 200 | for (j = 0; j < tx.outs.length; j++) { 201 | var txout = new TransactionOut(tx.outs[j]); 202 | hash = Crypto.util.bytesToBase64(txout.script.simpleOutPubKeyHash()); 203 | for (k = 0; k < this.addressHashes.length; k++) { 204 | if (this.addressHashes[k] === hash) { 205 | this.unspentOuts.push({tx: tx, index: j, out: txout}); 206 | break; 207 | } 208 | } 209 | } 210 | 211 | // Remove spent outputs 212 | for (j = 0; j < tx.ins.length; j++) { 213 | var txin = new TransactionIn(tx.ins[j]); 214 | var pubkey = txin.script.simpleInPubKey(); 215 | hash = Crypto.util.bytesToBase64(Bitcoin.Util.sha256ripe160(pubkey)); 216 | for (k = 0; k < this.addressHashes.length; k++) { 217 | if (this.addressHashes[k] === hash) { 218 | for (var l = 0; l < this.unspentOuts.length; l++) { 219 | if (txin.outpoint.hash == this.unspentOuts[l].tx.hash && 220 | txin.outpoint.index == this.unspentOuts[l].index) { 221 | this.unspentOuts.splice(l, 1); 222 | } 223 | } 224 | break; 225 | } 226 | } 227 | } 228 | 229 | // Index transaction 230 | this.txIndex[tx.hash] = tx; 231 | }; 232 | 233 | Wallet.prototype.getBalance = function () { 234 | var balance = BigInteger.valueOf(0); 235 | for (var i = 0; i < this.unspentOuts.length; i++) { 236 | var txout = this.unspentOuts[i].out; 237 | balance = balance.add(Bitcoin.Util.valueToBigInt(txout.value)); 238 | } 239 | return balance; 240 | }; 241 | 242 | Wallet.prototype.createSend = function (address, sendValue, feeValue) { 243 | var selectedOuts = []; 244 | var txValue = sendValue.add(feeValue); 245 | var availableValue = BigInteger.ZERO; 246 | var i; 247 | for (i = 0; i < this.unspentOuts.length; i++) { 248 | selectedOuts.push(this.unspentOuts[i]); 249 | availableValue = availableValue.add(Bitcoin.Util.valueToBigInt(this.unspentOuts[i].out.value)); 250 | 251 | if (availableValue.compareTo(txValue) >= 0) break; 252 | } 253 | 254 | if (availableValue.compareTo(txValue) < 0) { 255 | throw new Error('Insufficient funds.'); 256 | } 257 | 258 | 259 | var changeValue = availableValue.subtract(txValue); 260 | 261 | var sendTx = new Bitcoin.Transaction(); 262 | 263 | for (i = 0; i < selectedOuts.length; i++) { 264 | sendTx.addInput(selectedOuts[i].tx, selectedOuts[i].index); 265 | } 266 | 267 | sendTx.addOutput(address, sendValue); 268 | if (changeValue.compareTo(BigInteger.ZERO) > 0) { 269 | sendTx.addOutput(this.getNextAddress(), changeValue); 270 | } 271 | 272 | var hashType = 1; // SIGHASH_ALL 273 | 274 | for (i = 0; i < sendTx.ins.length; i++) { 275 | var hash = sendTx.hashTransactionForSignature(selectedOuts[i].out.script, i, hashType); 276 | var pubKeyHash = selectedOuts[i].out.script.simpleOutPubKeyHash(); 277 | var signature = this.signWithKey(pubKeyHash, hash); 278 | 279 | // Append hash type 280 | signature.push(parseInt(hashType, 10)); 281 | 282 | sendTx.ins[i].script = Script.createInputScript(signature, this.getPubKeyFromHash(pubKeyHash)); 283 | } 284 | 285 | return sendTx; 286 | }; 287 | 288 | Wallet.prototype.clearTransactions = function () { 289 | this.txIndex = {}; 290 | this.unspentOuts = []; 291 | }; 292 | 293 | /** 294 | * Check to see if a pubKeyHash belongs to this wallet. 295 | */ 296 | Wallet.prototype.hasHash = function (hash) { 297 | if (Bitcoin.Util.isArray(hash)) hash = Crypto.util.bytesToBase64(hash); 298 | 299 | // TODO: Just create an object with base64 hashes as keys for faster lookup 300 | for (var k = 0; k < this.addressHashes.length; k++) { 301 | if (this.addressHashes[k] === hash) return true; 302 | } 303 | return false; 304 | }; 305 | 306 | return Wallet; 307 | })(); 308 | 309 | -------------------------------------------------------------------------------- /src/jsbn/ec.js: -------------------------------------------------------------------------------- 1 | // Basic Javascript Elliptic Curve implementation 2 | // Ported loosely from BouncyCastle's Java EC code 3 | // Only Fp curves implemented for now 4 | 5 | // Requires jsbn.js and jsbn2.js 6 | 7 | // ---------------- 8 | // ECFieldElementFp 9 | 10 | // constructor 11 | function ECFieldElementFp(q,x) { 12 | this.x = x; 13 | // TODO if(x.compareTo(q) >= 0) error 14 | this.q = q; 15 | } 16 | 17 | function feFpEquals(other) { 18 | if(other == this) return true; 19 | return (this.q.equals(other.q) && this.x.equals(other.x)); 20 | } 21 | 22 | function feFpToBigInteger() { 23 | return this.x; 24 | } 25 | 26 | function feFpNegate() { 27 | return new ECFieldElementFp(this.q, this.x.negate().mod(this.q)); 28 | } 29 | 30 | function feFpAdd(b) { 31 | return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q)); 32 | } 33 | 34 | function feFpSubtract(b) { 35 | return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q)); 36 | } 37 | 38 | function feFpMultiply(b) { 39 | return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q)); 40 | } 41 | 42 | function feFpSquare() { 43 | return new ECFieldElementFp(this.q, this.x.square().mod(this.q)); 44 | } 45 | 46 | function feFpDivide(b) { 47 | return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q)); 48 | } 49 | 50 | ECFieldElementFp.prototype.equals = feFpEquals; 51 | ECFieldElementFp.prototype.toBigInteger = feFpToBigInteger; 52 | ECFieldElementFp.prototype.negate = feFpNegate; 53 | ECFieldElementFp.prototype.add = feFpAdd; 54 | ECFieldElementFp.prototype.subtract = feFpSubtract; 55 | ECFieldElementFp.prototype.multiply = feFpMultiply; 56 | ECFieldElementFp.prototype.square = feFpSquare; 57 | ECFieldElementFp.prototype.divide = feFpDivide; 58 | 59 | // ---------------- 60 | // ECPointFp 61 | 62 | // constructor 63 | function ECPointFp(curve,x,y,z) { 64 | this.curve = curve; 65 | this.x = x; 66 | this.y = y; 67 | // Projective coordinates: either zinv == null or z * zinv == 1 68 | // z and zinv are just BigIntegers, not fieldElements 69 | if(z == null) { 70 | this.z = BigInteger.ONE; 71 | } 72 | else { 73 | this.z = z; 74 | } 75 | this.zinv = null; 76 | //TODO: compression flag 77 | } 78 | 79 | function pointFpGetX() { 80 | if(this.zinv == null) { 81 | this.zinv = this.z.modInverse(this.curve.q); 82 | } 83 | return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q)); 84 | } 85 | 86 | function pointFpGetY() { 87 | if(this.zinv == null) { 88 | this.zinv = this.z.modInverse(this.curve.q); 89 | } 90 | return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q)); 91 | } 92 | 93 | function pointFpEquals(other) { 94 | if(other == this) return true; 95 | if(this.isInfinity()) return other.isInfinity(); 96 | if(other.isInfinity()) return this.isInfinity(); 97 | var u, v; 98 | // u = Y2 * Z1 - Y1 * Z2 99 | u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q); 100 | if(!u.equals(BigInteger.ZERO)) return false; 101 | // v = X2 * Z1 - X1 * Z2 102 | v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q); 103 | return v.equals(BigInteger.ZERO); 104 | } 105 | 106 | function pointFpIsInfinity() { 107 | if((this.x == null) && (this.y == null)) return true; 108 | return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO); 109 | } 110 | 111 | function pointFpNegate() { 112 | return new ECPointFp(this.curve, this.x, this.y.negate(), this.z); 113 | } 114 | 115 | function pointFpAdd(b) { 116 | if(this.isInfinity()) return b; 117 | if(b.isInfinity()) return this; 118 | 119 | // u = Y2 * Z1 - Y1 * Z2 120 | var u = b.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(b.z)).mod(this.curve.q); 121 | // v = X2 * Z1 - X1 * Z2 122 | var v = b.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(b.z)).mod(this.curve.q); 123 | 124 | if(BigInteger.ZERO.equals(v)) { 125 | if(BigInteger.ZERO.equals(u)) { 126 | return this.twice(); // this == b, so double 127 | } 128 | return this.curve.getInfinity(); // this = -b, so infinity 129 | } 130 | 131 | var THREE = new BigInteger("3"); 132 | var x1 = this.x.toBigInteger(); 133 | var y1 = this.y.toBigInteger(); 134 | var x2 = b.x.toBigInteger(); 135 | var y2 = b.y.toBigInteger(); 136 | 137 | var v2 = v.square(); 138 | var v3 = v2.multiply(v); 139 | var x1v2 = x1.multiply(v2); 140 | var zu2 = u.square().multiply(this.z); 141 | 142 | // x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3) 143 | var x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).subtract(v3).multiply(v).mod(this.curve.q); 144 | // y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3 145 | var y3 = x1v2.multiply(THREE).multiply(u).subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).multiply(b.z).add(u.multiply(v3)).mod(this.curve.q); 146 | // z3 = v^3 * z1 * z2 147 | var z3 = v3.multiply(this.z).multiply(b.z).mod(this.curve.q); 148 | 149 | return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3); 150 | } 151 | 152 | function pointFpTwice() { 153 | if(this.isInfinity()) return this; 154 | if(this.y.toBigInteger().signum() == 0) return this.curve.getInfinity(); 155 | 156 | // TODO: optimized handling of constants 157 | var THREE = new BigInteger("3"); 158 | var x1 = this.x.toBigInteger(); 159 | var y1 = this.y.toBigInteger(); 160 | 161 | var y1z1 = y1.multiply(this.z); 162 | var y1sqz1 = y1z1.multiply(y1).mod(this.curve.q); 163 | var a = this.curve.a.toBigInteger(); 164 | 165 | // w = 3 * x1^2 + a * z1^2 166 | var w = x1.square().multiply(THREE); 167 | if(!BigInteger.ZERO.equals(a)) { 168 | w = w.add(this.z.square().multiply(a)); 169 | } 170 | w = w.mod(this.curve.q); 171 | // x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1) 172 | var x3 = w.square().subtract(x1.shiftLeft(3).multiply(y1sqz1)).shiftLeft(1).multiply(y1z1).mod(this.curve.q); 173 | // y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3 174 | var y3 = w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1)).shiftLeft(2).multiply(y1sqz1).subtract(w.square().multiply(w)).mod(this.curve.q); 175 | // z3 = 8 * (y1 * z1)^3 176 | var z3 = y1z1.square().multiply(y1z1).shiftLeft(3).mod(this.curve.q); 177 | 178 | return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3); 179 | } 180 | 181 | // Simple NAF (Non-Adjacent Form) multiplication algorithm 182 | // TODO: modularize the multiplication algorithm 183 | function pointFpMultiply(k) { 184 | if(this.isInfinity()) return this; 185 | if(k.signum() == 0) return this.curve.getInfinity(); 186 | 187 | var e = k; 188 | var h = e.multiply(new BigInteger("3")); 189 | 190 | var neg = this.negate(); 191 | var R = this; 192 | 193 | var i; 194 | for(i = h.bitLength() - 2; i > 0; --i) { 195 | R = R.twice(); 196 | 197 | var hBit = h.testBit(i); 198 | var eBit = e.testBit(i); 199 | 200 | if (hBit != eBit) { 201 | R = R.add(hBit ? this : neg); 202 | } 203 | } 204 | 205 | return R; 206 | } 207 | 208 | // Compute this*j + x*k (simultaneous multiplication) 209 | function pointFpMultiplyTwo(j,x,k) { 210 | var i; 211 | if(j.bitLength() > k.bitLength()) 212 | i = j.bitLength() - 1; 213 | else 214 | i = k.bitLength() - 1; 215 | 216 | var R = this.curve.getInfinity(); 217 | var both = this.add(x); 218 | while(i >= 0) { 219 | R = R.twice(); 220 | if(j.testBit(i)) { 221 | if(k.testBit(i)) { 222 | R = R.add(both); 223 | } 224 | else { 225 | R = R.add(this); 226 | } 227 | } 228 | else { 229 | if(k.testBit(i)) { 230 | R = R.add(x); 231 | } 232 | } 233 | --i; 234 | } 235 | 236 | return R; 237 | } 238 | 239 | ECPointFp.prototype.getX = pointFpGetX; 240 | ECPointFp.prototype.getY = pointFpGetY; 241 | ECPointFp.prototype.equals = pointFpEquals; 242 | ECPointFp.prototype.isInfinity = pointFpIsInfinity; 243 | ECPointFp.prototype.negate = pointFpNegate; 244 | ECPointFp.prototype.add = pointFpAdd; 245 | ECPointFp.prototype.twice = pointFpTwice; 246 | ECPointFp.prototype.multiply = pointFpMultiply; 247 | ECPointFp.prototype.multiplyTwo = pointFpMultiplyTwo; 248 | 249 | // ---------------- 250 | // ECCurveFp 251 | 252 | // constructor 253 | function ECCurveFp(q,a,b) { 254 | this.q = q; 255 | this.a = this.fromBigInteger(a); 256 | this.b = this.fromBigInteger(b); 257 | this.infinity = new ECPointFp(this, null, null); 258 | } 259 | 260 | function curveFpGetQ() { 261 | return this.q; 262 | } 263 | 264 | function curveFpGetA() { 265 | return this.a; 266 | } 267 | 268 | function curveFpGetB() { 269 | return this.b; 270 | } 271 | 272 | function curveFpEquals(other) { 273 | if(other == this) return true; 274 | return(this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b)); 275 | } 276 | 277 | function curveFpGetInfinity() { 278 | return this.infinity; 279 | } 280 | 281 | function curveFpFromBigInteger(x) { 282 | return new ECFieldElementFp(this.q, x); 283 | } 284 | 285 | // for now, work with hex strings because they're easier in JS 286 | function curveFpDecodePointHex(s) { 287 | switch(parseInt(s.substr(0,2), 16)) { // first byte 288 | case 0: 289 | return this.infinity; 290 | case 2: 291 | case 3: 292 | // point compression not supported yet 293 | return null; 294 | case 4: 295 | case 6: 296 | case 7: 297 | var len = (s.length - 2) / 2; 298 | var xHex = s.substr(2, len); 299 | var yHex = s.substr(len+2, len); 300 | 301 | return new ECPointFp(this, 302 | this.fromBigInteger(new BigInteger(xHex, 16)), 303 | this.fromBigInteger(new BigInteger(yHex, 16))); 304 | 305 | default: // unsupported 306 | return null; 307 | } 308 | } 309 | 310 | ECCurveFp.prototype.getQ = curveFpGetQ; 311 | ECCurveFp.prototype.getA = curveFpGetA; 312 | ECCurveFp.prototype.getB = curveFpGetB; 313 | ECCurveFp.prototype.equals = curveFpEquals; 314 | ECCurveFp.prototype.getInfinity = curveFpGetInfinity; 315 | ECCurveFp.prototype.fromBigInteger = curveFpFromBigInteger; 316 | ECCurveFp.prototype.decodePointHex = curveFpDecodePointHex; 317 | -------------------------------------------------------------------------------- /src/script.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | var Opcode = Bitcoin.Opcode; 3 | 4 | // Make opcodes available as pseudo-constants 5 | for (var i in Opcode.map) { 6 | eval("var " + i + " = " + Opcode.map[i] + ";"); 7 | } 8 | 9 | var Script = Bitcoin.Script = function (data) { 10 | if (!data) { 11 | this.buffer = []; 12 | } else if ("string" == typeof data) { 13 | this.buffer = Crypto.util.base64ToBytes(data); 14 | } else if (Bitcoin.Util.isArray(data)) { 15 | this.buffer = data; 16 | } else if (data instanceof Script) { 17 | this.buffer = data.buffer; 18 | } else { 19 | throw new Error("Invalid script"); 20 | } 21 | 22 | this.parse(); 23 | }; 24 | 25 | /** 26 | * Update the parsed script representation. 27 | * 28 | * Each Script object stores the script in two formats. First as a raw byte 29 | * array and second as an array of "chunks", such as opcodes and pieces of 30 | * data. 31 | * 32 | * This method updates the chunks cache. Normally this is called by the 33 | * constructor and you don't need to worry about it. However, if you change 34 | * the script buffer manually, you should update the chunks using this method. 35 | */ 36 | Script.prototype.parse = function () { 37 | var self = this; 38 | 39 | this.chunks = []; 40 | 41 | // Cursor 42 | var i = 0; 43 | 44 | // Read n bytes and store result as a chunk 45 | function readChunk(n) { 46 | self.chunks.push(self.buffer.slice(i, i + n)); 47 | i += n; 48 | }; 49 | 50 | while (i < this.buffer.length) { 51 | var opcode = this.buffer[i++]; 52 | if (opcode >= 0xF0) { 53 | // Two byte opcode 54 | opcode = (opcode << 8) | this.buffer[i++]; 55 | } 56 | 57 | var len; 58 | if (opcode > 0 && opcode < OP_PUSHDATA1) { 59 | // Read some bytes of data, opcode value is the length of data 60 | readChunk(opcode); 61 | } else if (opcode == OP_PUSHDATA1) { 62 | len = this.buffer[i++]; 63 | readChunk(len); 64 | } else if (opcode == OP_PUSHDATA2) { 65 | len = (this.buffer[i++] << 8) | this.buffer[i++]; 66 | readChunk(len); 67 | } else if (opcode == OP_PUSHDATA4) { 68 | len = (this.buffer[i++] << 24) | 69 | (this.buffer[i++] << 16) | 70 | (this.buffer[i++] << 8) | 71 | this.buffer[i++]; 72 | readChunk(len); 73 | } else { 74 | this.chunks.push(opcode); 75 | } 76 | } 77 | }; 78 | 79 | /** 80 | * Compare the script to known templates of scriptPubKey. 81 | * 82 | * This method will compare the script to a small number of standard script 83 | * templates and return a string naming the detected type. 84 | * 85 | * Currently supported are: 86 | * Address: 87 | * Paying to a Bitcoin address which is the hash of a pubkey. 88 | * OP_DUP OP_HASH160 [pubKeyHash] OP_EQUALVERIFY OP_CHECKSIG 89 | * 90 | * Pubkey: 91 | * Paying to a public key directly. 92 | * [pubKey] OP_CHECKSIG 93 | * 94 | * Strange: 95 | * Any other script (no template matched). 96 | */ 97 | Script.prototype.getOutType = function () { 98 | 99 | if (this.chunks[this.chunks.length-1] == OP_CHECKMULTISIG && this.chunks[this.chunks.length-2] <= 3) { 100 | // Transfer to M-OF-N 101 | return 'Multisig'; 102 | } else if (this.chunks.length == 5 && 103 | this.chunks[0] == OP_DUP && 104 | this.chunks[1] == OP_HASH160 && 105 | this.chunks[3] == OP_EQUALVERIFY && 106 | this.chunks[4] == OP_CHECKSIG) { 107 | // Transfer to Bitcoin address 108 | return 'Address'; 109 | } else if (this.chunks.length == 2 && 110 | this.chunks[1] == OP_CHECKSIG) { 111 | // Transfer to IP address 112 | return 'Pubkey'; 113 | } else { 114 | return 'Strange'; 115 | } 116 | } 117 | 118 | /** 119 | * Returns the affected address hash for this output. 120 | * 121 | * For standard transactions, this will return the hash of the pubKey that 122 | * can spend this output. 123 | * 124 | * In the future, for payToScriptHash outputs, this will return the 125 | * scriptHash. Note that non-standard and standard payToScriptHash transactions 126 | * look the same 127 | * 128 | * This method is useful for indexing transactions. 129 | */ 130 | Script.prototype.simpleOutHash = function () 131 | { 132 | switch (this.getOutType()) { 133 | case 'Address': 134 | return this.chunks[2]; 135 | case 'Pubkey': 136 | return Bitcoin.Util.sha256ripe160(this.chunks[0]); 137 | default: 138 | throw new Error("Encountered non-standard scriptPubKey"); 139 | } 140 | }; 141 | 142 | /** 143 | * Old name for Script#simpleOutHash. 144 | * 145 | * @deprecated 146 | */ 147 | Script.prototype.simpleOutPubKeyHash = Script.prototype.simpleOutHash; 148 | 149 | /** 150 | * Compare the script to known templates of scriptSig. 151 | * 152 | * This method will compare the script to a small number of standard script 153 | * templates and return a string naming the detected type. 154 | * 155 | * WARNING: Use this method with caution. It merely represents a heuristic 156 | * based on common transaction formats. A non-standard transaction could 157 | * very easily match one of these templates by accident. 158 | * 159 | * Currently supported are: 160 | * Address: 161 | * Paying to a Bitcoin address which is the hash of a pubkey. 162 | * [sig] [pubKey] 163 | * 164 | * Pubkey: 165 | * Paying to a public key directly. 166 | * [sig] 167 | * 168 | * Strange: 169 | * Any other script (no template matched). 170 | */ 171 | Script.prototype.getInType = function () 172 | { 173 | if (this.chunks.length == 1 && 174 | Bitcoin.Util.isArray(this.chunks[0])) { 175 | // Direct IP to IP transactions only have the signature in their scriptSig. 176 | // TODO: We could also check that the length of the data is correct. 177 | return 'Pubkey'; 178 | } else if (this.chunks.length == 2 && 179 | Bitcoin.Util.isArray(this.chunks[0]) && 180 | Bitcoin.Util.isArray(this.chunks[1])) { 181 | return 'Address'; 182 | } else { 183 | return 'Strange'; 184 | } 185 | }; 186 | 187 | /** 188 | * Returns the affected public key for this input. 189 | * 190 | * This currently only works with payToPubKeyHash transactions. It will also 191 | * work in the future for standard payToScriptHash transactions that use a 192 | * single public key. 193 | * 194 | * However for multi-key and other complex transactions, this will only return 195 | * one of the keys or raise an error. Therefore, it is recommended for indexing 196 | * purposes to use Script#simpleInHash or Script#simpleOutHash instead. 197 | * 198 | * @deprecated 199 | */ 200 | Script.prototype.simpleInPubKey = function () 201 | { 202 | switch (this.getInType()) { 203 | case 'Address': 204 | return this.chunks[1]; 205 | case 'Pubkey': 206 | // TODO: Theoretically, we could recover the pubkey from the sig here. 207 | // See https://bitcointalk.org/?topic=6430.0 208 | throw new Error("Script does not contain pubkey."); 209 | default: 210 | throw new Error("Encountered non-standard scriptSig"); 211 | } 212 | }; 213 | 214 | /** 215 | * Returns the affected address hash for this input. 216 | * 217 | * For standard transactions, this will return the hash of the pubKey that 218 | * can spend this output. 219 | * 220 | * In the future, for standard payToScriptHash inputs, this will return the 221 | * scriptHash. 222 | * 223 | * Note: This function provided for convenience. If you have the corresponding 224 | * scriptPubKey available, you are urged to use Script#simpleOutHash instead 225 | * as it is more reliable for non-standard payToScriptHash transactions. 226 | * 227 | * This method is useful for indexing transactions. 228 | */ 229 | Script.prototype.simpleInHash = function () 230 | { 231 | return Bitcoin.Util.sha256ripe160(this.simpleInPubKey()); 232 | }; 233 | 234 | /** 235 | * Old name for Script#simpleInHash. 236 | * 237 | * @deprecated 238 | */ 239 | Script.prototype.simpleInPubKeyHash = Script.prototype.simpleInHash; 240 | 241 | /** 242 | * Add an op code to the script. 243 | */ 244 | Script.prototype.writeOp = function (opcode) 245 | { 246 | this.buffer.push(opcode); 247 | this.chunks.push(opcode); 248 | }; 249 | 250 | /** 251 | * Add a data chunk to the script. 252 | */ 253 | Script.prototype.writeBytes = function (data) 254 | { 255 | if (data.length < OP_PUSHDATA1) { 256 | this.buffer.push(data.length); 257 | } else if (data.length <= 0xff) { 258 | this.buffer.push(OP_PUSHDATA1); 259 | this.buffer.push(data.length); 260 | } else if (data.length <= 0xffff) { 261 | this.buffer.push(OP_PUSHDATA2); 262 | this.buffer.push(data.length & 0xff); 263 | this.buffer.push((data.length >>> 8) & 0xff); 264 | } else { 265 | this.buffer.push(OP_PUSHDATA4); 266 | this.buffer.push(data.length & 0xff); 267 | this.buffer.push((data.length >>> 8) & 0xff); 268 | this.buffer.push((data.length >>> 16) & 0xff); 269 | this.buffer.push((data.length >>> 24) & 0xff); 270 | } 271 | this.buffer = this.buffer.concat(data); 272 | this.chunks.push(data); 273 | }; 274 | 275 | /** 276 | * Create a standard payToPubKeyHash output. 277 | */ 278 | Script.createOutputScript = function (address) 279 | { 280 | var script = new Script(); 281 | script.writeOp(OP_DUP); 282 | script.writeOp(OP_HASH160); 283 | script.writeBytes(address.hash); 284 | script.writeOp(OP_EQUALVERIFY); 285 | script.writeOp(OP_CHECKSIG); 286 | return script; 287 | }; 288 | 289 | 290 | /** 291 | * Extract bitcoin addresses from an output script 292 | */ 293 | Script.prototype.extractAddresses = function (addresses) 294 | { 295 | switch (this.getOutType()) { 296 | case 'Address': 297 | addresses.push(new Address(this.chunks[2])); 298 | return 1; 299 | case 'Pubkey': 300 | addresses.push(new Address(Util.sha256ripe160(this.chunks[0]))); 301 | return 1; 302 | case 'Multisig': 303 | for (var i = 1; i < this.chunks.length-2; ++i) { 304 | addresses.push(new Address(Util.sha256ripe160(this.chunks[i]))); 305 | } 306 | return this.chunks[0] - OP_1 + 1; 307 | default: 308 | throw new Error("Encountered non-standard scriptPubKey"); 309 | } 310 | }; 311 | 312 | /** 313 | * Create an m-of-n output script 314 | */ 315 | Script.createMultiSigOutputScript = function (m, pubkeys) 316 | { 317 | var script = new Bitcoin.Script(); 318 | 319 | script.writeOp(OP_1 + m - 1); 320 | 321 | for (var i = 0; i < pubkeys.length; ++i) { 322 | script.writeBytes(pubkeys[i]); 323 | } 324 | 325 | script.writeOp(OP_1 + pubkeys.length - 1); 326 | 327 | script.writeOp(OP_CHECKMULTISIG); 328 | 329 | return script; 330 | }; 331 | 332 | /** 333 | * Create a standard payToPubKeyHash input. 334 | */ 335 | Script.createInputScript = function (signature, pubKey) 336 | { 337 | var script = new Script(); 338 | script.writeBytes(signature); 339 | script.writeBytes(pubKey); 340 | return script; 341 | }; 342 | 343 | Script.prototype.clone = function () 344 | { 345 | return new Script(this.buffer); 346 | }; 347 | })(); 348 | -------------------------------------------------------------------------------- /src/ecdsa.js: -------------------------------------------------------------------------------- 1 | function integerToBytes(i, len) { 2 | var bytes = i.toByteArrayUnsigned(); 3 | 4 | if (len < bytes.length) { 5 | bytes = bytes.slice(bytes.length-len); 6 | } else while (len > bytes.length) { 7 | bytes.unshift(0); 8 | } 9 | 10 | return bytes; 11 | }; 12 | 13 | ECFieldElementFp.prototype.getByteLength = function () { 14 | return Math.floor((this.toBigInteger().bitLength() + 7) / 8); 15 | }; 16 | 17 | ECPointFp.prototype.getEncoded = function (compressed) { 18 | var x = this.getX().toBigInteger(); 19 | var y = this.getY().toBigInteger(); 20 | 21 | // Get value as a 32-byte Buffer 22 | // Fixed length based on a patch by bitaddress.org and Casascius 23 | var enc = integerToBytes(x, 32); 24 | 25 | if (compressed) { 26 | if (y.isEven()) { 27 | // Compressed even pubkey 28 | // M = 02 || X 29 | enc.unshift(0x02); 30 | } else { 31 | // Compressed uneven pubkey 32 | // M = 03 || X 33 | enc.unshift(0x03); 34 | } 35 | } else { 36 | // Uncompressed pubkey 37 | // M = 04 || X || Y 38 | enc.unshift(0x04); 39 | enc = enc.concat(integerToBytes(y, 32)); 40 | } 41 | return enc; 42 | }; 43 | 44 | ECPointFp.decodeFrom = function (curve, enc) { 45 | var type = enc[0]; 46 | var dataLen = enc.length-1; 47 | 48 | // Extract x and y as byte arrays 49 | var xBa = enc.slice(1, 1 + dataLen/2); 50 | var yBa = enc.slice(1 + dataLen/2, 1 + dataLen); 51 | 52 | // Prepend zero byte to prevent interpretation as negative integer 53 | xBa.unshift(0); 54 | yBa.unshift(0); 55 | 56 | // Convert to BigIntegers 57 | var x = new BigInteger(xBa); 58 | var y = new BigInteger(yBa); 59 | 60 | // Return point 61 | return new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y)); 62 | }; 63 | 64 | ECPointFp.prototype.add2D = function (b) { 65 | if(this.isInfinity()) return b; 66 | if(b.isInfinity()) return this; 67 | 68 | if (this.x.equals(b.x)) { 69 | if (this.y.equals(b.y)) { 70 | // this = b, i.e. this must be doubled 71 | return this.twice(); 72 | } 73 | // this = -b, i.e. the result is the point at infinity 74 | return this.curve.getInfinity(); 75 | } 76 | 77 | var x_x = b.x.subtract(this.x); 78 | var y_y = b.y.subtract(this.y); 79 | var gamma = y_y.divide(x_x); 80 | 81 | var x3 = gamma.square().subtract(this.x).subtract(b.x); 82 | var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); 83 | 84 | return new ECPointFp(this.curve, x3, y3); 85 | }; 86 | 87 | ECPointFp.prototype.twice2D = function () { 88 | if (this.isInfinity()) return this; 89 | if (this.y.toBigInteger().signum() == 0) { 90 | // if y1 == 0, then (x1, y1) == (x1, -y1) 91 | // and hence this = -this and thus 2(x1, y1) == infinity 92 | return this.curve.getInfinity(); 93 | } 94 | 95 | var TWO = this.curve.fromBigInteger(BigInteger.valueOf(2)); 96 | var THREE = this.curve.fromBigInteger(BigInteger.valueOf(3)); 97 | var gamma = this.x.square().multiply(THREE).add(this.curve.a).divide(this.y.multiply(TWO)); 98 | 99 | var x3 = gamma.square().subtract(this.x.multiply(TWO)); 100 | var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); 101 | 102 | return new ECPointFp(this.curve, x3, y3); 103 | }; 104 | 105 | ECPointFp.prototype.multiply2D = function (k) { 106 | if(this.isInfinity()) return this; 107 | if(k.signum() == 0) return this.curve.getInfinity(); 108 | 109 | var e = k; 110 | var h = e.multiply(new BigInteger("3")); 111 | 112 | var neg = this.negate(); 113 | var R = this; 114 | 115 | var i; 116 | for (i = h.bitLength() - 2; i > 0; --i) { 117 | R = R.twice(); 118 | 119 | var hBit = h.testBit(i); 120 | var eBit = e.testBit(i); 121 | 122 | if (hBit != eBit) { 123 | R = R.add2D(hBit ? this : neg); 124 | } 125 | } 126 | 127 | return R; 128 | }; 129 | 130 | ECPointFp.prototype.isOnCurve = function () { 131 | var x = this.getX().toBigInteger(); 132 | var y = this.getY().toBigInteger(); 133 | var a = this.curve.getA().toBigInteger(); 134 | var b = this.curve.getB().toBigInteger(); 135 | var n = this.curve.getQ(); 136 | var lhs = y.multiply(y).mod(n); 137 | var rhs = x.multiply(x).multiply(x) 138 | .add(a.multiply(x)).add(b).mod(n); 139 | return lhs.equals(rhs); 140 | }; 141 | 142 | ECPointFp.prototype.toString = function () { 143 | return '('+this.getX().toBigInteger().toString()+','+ 144 | this.getY().toBigInteger().toString()+')'; 145 | }; 146 | 147 | /** 148 | * Validate an elliptic curve point. 149 | * 150 | * See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive 151 | */ 152 | ECPointFp.prototype.validate = function () { 153 | var n = this.curve.getQ(); 154 | 155 | // Check Q != O 156 | if (this.isInfinity()) { 157 | throw new Error("Point is at infinity."); 158 | } 159 | 160 | // Check coordinate bounds 161 | var x = this.getX().toBigInteger(); 162 | var y = this.getY().toBigInteger(); 163 | if (x.compareTo(BigInteger.ONE) < 0 || 164 | x.compareTo(n.subtract(BigInteger.ONE)) > 0) { 165 | throw new Error('x coordinate out of bounds'); 166 | } 167 | if (y.compareTo(BigInteger.ONE) < 0 || 168 | y.compareTo(n.subtract(BigInteger.ONE)) > 0) { 169 | throw new Error('y coordinate out of bounds'); 170 | } 171 | 172 | // Check y^2 = x^3 + ax + b (mod n) 173 | if (!this.isOnCurve()) { 174 | throw new Error("Point is not on the curve."); 175 | } 176 | 177 | // Check nQ = 0 (Q is a scalar multiple of G) 178 | if (this.multiply(n).isInfinity()) { 179 | // TODO: This check doesn't work - fix. 180 | throw new Error("Point is not a scalar multiple of G."); 181 | } 182 | 183 | return true; 184 | }; 185 | 186 | function dmp(v) { 187 | if (!(v instanceof BigInteger)) v = v.toBigInteger(); 188 | return Crypto.util.bytesToHex(v.toByteArrayUnsigned()); 189 | }; 190 | 191 | Bitcoin.ECDSA = (function () { 192 | var ecparams = getSECCurveByName("secp256k1"); 193 | var rng = new SecureRandom(); 194 | 195 | var P_OVER_FOUR = null; 196 | 197 | function implShamirsTrick(P, k, Q, l) 198 | { 199 | var m = Math.max(k.bitLength(), l.bitLength()); 200 | var Z = P.add2D(Q); 201 | var R = P.curve.getInfinity(); 202 | 203 | for (var i = m - 1; i >= 0; --i) { 204 | R = R.twice2D(); 205 | 206 | R.z = BigInteger.ONE; 207 | 208 | if (k.testBit(i)) { 209 | if (l.testBit(i)) { 210 | R = R.add2D(Z); 211 | } else { 212 | R = R.add2D(P); 213 | } 214 | } else { 215 | if (l.testBit(i)) { 216 | R = R.add2D(Q); 217 | } 218 | } 219 | } 220 | 221 | return R; 222 | }; 223 | 224 | var ECDSA = { 225 | getBigRandom: function (limit) { 226 | return new BigInteger(limit.bitLength(), rng) 227 | .mod(limit.subtract(BigInteger.ONE)) 228 | .add(BigInteger.ONE) 229 | ; 230 | }, 231 | sign: function (hash, priv) { 232 | var d = priv; 233 | var n = ecparams.getN(); 234 | var e = BigInteger.fromByteArrayUnsigned(hash); 235 | 236 | do { 237 | var k = ECDSA.getBigRandom(n); 238 | var G = ecparams.getG(); 239 | var Q = G.multiply(k); 240 | var r = Q.getX().toBigInteger().mod(n); 241 | } while (r.compareTo(BigInteger.ZERO) <= 0); 242 | 243 | var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n); 244 | 245 | return ECDSA.serializeSig(r, s); 246 | }, 247 | 248 | verify: function (hash, sig, pubkey) { 249 | var r,s; 250 | if (Bitcoin.Util.isArray(sig)) { 251 | var obj = ECDSA.parseSig(sig); 252 | r = obj.r; 253 | s = obj.s; 254 | } else if ("object" === typeof sig && sig.r && sig.s) { 255 | r = sig.r; 256 | s = sig.s; 257 | } else { 258 | throw "Invalid value for signature"; 259 | } 260 | 261 | var Q; 262 | if (pubkey instanceof ECPointFp) { 263 | Q = pubkey; 264 | } else if (Bitcoin.Util.isArray(pubkey)) { 265 | Q = ECPointFp.decodeFrom(ecparams.getCurve(), pubkey); 266 | } else { 267 | throw "Invalid format for pubkey value, must be byte array or ECPointFp"; 268 | } 269 | var e = BigInteger.fromByteArrayUnsigned(hash); 270 | 271 | return ECDSA.verifyRaw(e, r, s, Q); 272 | }, 273 | 274 | verifyRaw: function (e, r, s, Q) { 275 | var n = ecparams.getN(); 276 | var G = ecparams.getG(); 277 | 278 | if (r.compareTo(BigInteger.ONE) < 0 || 279 | r.compareTo(n) >= 0) 280 | return false; 281 | 282 | if (s.compareTo(BigInteger.ONE) < 0 || 283 | s.compareTo(n) >= 0) 284 | return false; 285 | 286 | var c = s.modInverse(n); 287 | 288 | var u1 = e.multiply(c).mod(n); 289 | var u2 = r.multiply(c).mod(n); 290 | 291 | // TODO(!!!): For some reason Shamir's trick isn't working with 292 | // signed message verification!? Probably an implementation 293 | // error! 294 | //var point = implShamirsTrick(G, u1, Q, u2); 295 | var point = G.multiply(u1).add(Q.multiply(u2)); 296 | 297 | var v = point.getX().toBigInteger().mod(n); 298 | 299 | return v.equals(r); 300 | }, 301 | 302 | /** 303 | * Serialize a signature into DER format. 304 | * 305 | * Takes two BigIntegers representing r and s and returns a byte array. 306 | */ 307 | serializeSig: function (r, s) { 308 | var rBa = r.toByteArraySigned(); 309 | var sBa = s.toByteArraySigned(); 310 | 311 | var sequence = []; 312 | sequence.push(0x02); // INTEGER 313 | sequence.push(rBa.length); 314 | sequence = sequence.concat(rBa); 315 | 316 | sequence.push(0x02); // INTEGER 317 | sequence.push(sBa.length); 318 | sequence = sequence.concat(sBa); 319 | 320 | sequence.unshift(sequence.length); 321 | sequence.unshift(0x30); // SEQUENCE 322 | 323 | return sequence; 324 | }, 325 | 326 | /** 327 | * Parses a byte array containing a DER-encoded signature. 328 | * 329 | * This function will return an object of the form: 330 | * 331 | * { 332 | * r: BigInteger, 333 | * s: BigInteger 334 | * } 335 | */ 336 | parseSig: function (sig) { 337 | var cursor; 338 | if (sig[0] != 0x30) 339 | throw new Error("Signature not a valid DERSequence"); 340 | 341 | cursor = 2; 342 | if (sig[cursor] != 0x02) 343 | throw new Error("First element in signature must be a DERInteger");; 344 | var rBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]); 345 | 346 | cursor += 2+sig[cursor+1]; 347 | if (sig[cursor] != 0x02) 348 | throw new Error("Second element in signature must be a DERInteger"); 349 | var sBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]); 350 | 351 | cursor += 2+sig[cursor+1]; 352 | 353 | //if (cursor != sig.length) 354 | // throw new Error("Extra bytes in signature"); 355 | 356 | var r = BigInteger.fromByteArrayUnsigned(rBa); 357 | var s = BigInteger.fromByteArrayUnsigned(sBa); 358 | 359 | return {r: r, s: s}; 360 | }, 361 | 362 | parseSigCompact: function (sig) { 363 | if (sig.length !== 65) { 364 | throw "Signature has the wrong length"; 365 | } 366 | 367 | // Signature is prefixed with a type byte storing three bits of 368 | // information. 369 | var i = sig[0] - 27; 370 | if (i < 0 || i > 7) { 371 | throw "Invalid signature type"; 372 | } 373 | 374 | var n = ecparams.getN(); 375 | var r = BigInteger.fromByteArrayUnsigned(sig.slice(1, 33)).mod(n); 376 | var s = BigInteger.fromByteArrayUnsigned(sig.slice(33, 65)).mod(n); 377 | 378 | return {r: r, s: s, i: i}; 379 | }, 380 | 381 | /** 382 | * Recover a public key from a signature. 383 | * 384 | * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public 385 | * Key Recovery Operation". 386 | * 387 | * http://www.secg.org/download/aid-780/sec1-v2.pdf 388 | */ 389 | recoverPubKey: function (r, s, hash, i) { 390 | // The recovery parameter i has two bits. 391 | i = i & 3; 392 | 393 | // The less significant bit specifies whether the y coordinate 394 | // of the compressed point is even or not. 395 | var isYEven = i & 1; 396 | 397 | // The more significant bit specifies whether we should use the 398 | // first or second candidate key. 399 | var isSecondKey = i >> 1; 400 | 401 | var n = ecparams.getN(); 402 | var G = ecparams.getG(); 403 | var curve = ecparams.getCurve(); 404 | var p = curve.getQ(); 405 | var a = curve.getA().toBigInteger(); 406 | var b = curve.getB().toBigInteger(); 407 | 408 | // We precalculate (p + 1) / 4 where p is if the field order 409 | if (!P_OVER_FOUR) { 410 | P_OVER_FOUR = p.add(BigInteger.ONE).divide(BigInteger.valueOf(4)); 411 | } 412 | 413 | // 1.1 Compute x 414 | var x = isSecondKey ? r.add(n) : r; 415 | 416 | // 1.3 Convert x to point 417 | var alpha = x.multiply(x).multiply(x).add(a.multiply(x)).add(b).mod(p); 418 | var beta = alpha.modPow(P_OVER_FOUR, p); 419 | 420 | var xorOdd = beta.isEven() ? (i % 2) : ((i+1) % 2); 421 | // If beta is even, but y isn't or vice versa, then convert it, 422 | // otherwise we're done and y == beta. 423 | var y = (beta.isEven() ? !isYEven : isYEven) ? beta : p.subtract(beta); 424 | 425 | // 1.4 Check that nR is at infinity 426 | var R = new ECPointFp(curve, 427 | curve.fromBigInteger(x), 428 | curve.fromBigInteger(y)); 429 | R.validate(); 430 | 431 | // 1.5 Compute e from M 432 | var e = BigInteger.fromByteArrayUnsigned(hash); 433 | var eNeg = BigInteger.ZERO.subtract(e).mod(n); 434 | 435 | // 1.6 Compute Q = r^-1 (sR - eG) 436 | var rInv = r.modInverse(n); 437 | var Q = implShamirsTrick(R, s, G, eNeg).multiply(rInv); 438 | 439 | Q.validate(); 440 | if (!ECDSA.verifyRaw(e, r, s, Q)) { 441 | throw "Pubkey recovery unsuccessful"; 442 | } 443 | 444 | var pubKey = new Bitcoin.ECKey(); 445 | pubKey.pub = Q; 446 | return pubKey; 447 | }, 448 | 449 | /** 450 | * Calculate pubkey extraction parameter. 451 | * 452 | * When extracting a pubkey from a signature, we have to 453 | * distinguish four different cases. Rather than putting this 454 | * burden on the verifier, Bitcoin includes a 2-bit value with the 455 | * signature. 456 | * 457 | * This function simply tries all four cases and returns the value 458 | * that resulted in a successful pubkey recovery. 459 | */ 460 | calcPubkeyRecoveryParam: function (address, r, s, hash) 461 | { 462 | for (var i = 0; i < 4; i++) { 463 | try { 464 | var pubkey = Bitcoin.ECDSA.recoverPubKey(r, s, hash, i); 465 | if (pubkey.getBitcoinAddress().toString() == address) { 466 | return i; 467 | } 468 | } catch (e) {} 469 | } 470 | throw "Unable to find valid recovery factor"; 471 | } 472 | }; 473 | 474 | return ECDSA; 475 | })(); 476 | -------------------------------------------------------------------------------- /src/transaction.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | var Script = Bitcoin.Script; 3 | 4 | var Transaction = Bitcoin.Transaction = function (doc) { 5 | this.version = 1; 6 | this.lock_time = 0; 7 | this.ins = []; 8 | this.outs = []; 9 | this.timestamp = null; 10 | this.block = null; 11 | 12 | if (doc) { 13 | if (doc.hash) this.hash = doc.hash; 14 | if (doc.version) this.version = doc.version; 15 | if (doc.lock_time) this.lock_time = doc.lock_time; 16 | if (doc.ins && doc.ins.length) { 17 | for (var i = 0; i < doc.ins.length; i++) { 18 | this.addInput(new TransactionIn(doc.ins[i])); 19 | } 20 | } 21 | if (doc.outs && doc.outs.length) { 22 | for (var i = 0; i < doc.outs.length; i++) { 23 | this.addOutput(new TransactionOut(doc.outs[i])); 24 | } 25 | } 26 | if (doc.timestamp) this.timestamp = doc.timestamp; 27 | if (doc.block) this.block = doc.block; 28 | } 29 | }; 30 | 31 | /** 32 | * Turn transaction data into Transaction objects. 33 | * 34 | * Takes an array of plain JavaScript objects containing transaction data and 35 | * returns an array of Transaction objects. 36 | */ 37 | Transaction.objectify = function (txs) { 38 | var objs = []; 39 | for (var i = 0; i < txs.length; i++) { 40 | objs.push(new Transaction(txs[i])); 41 | } 42 | return objs; 43 | }; 44 | 45 | /** 46 | * Create a new txin. 47 | * 48 | * Can be called with an existing TransactionIn object to add it to the 49 | * transaction. Or it can be called with a Transaction object and an integer 50 | * output index, in which case a new TransactionIn object pointing to the 51 | * referenced output will be created. 52 | * 53 | * Note that this method does not sign the created input. 54 | */ 55 | Transaction.prototype.addInput = function (tx, outIndex) { 56 | if (arguments[0] instanceof TransactionIn) { 57 | this.ins.push(arguments[0]); 58 | } else { 59 | this.ins.push(new TransactionIn({ 60 | outpoint: { 61 | hash: tx.hash, 62 | index: outIndex 63 | }, 64 | script: new Bitcoin.Script(), 65 | sequence: 4294967295 66 | })); 67 | } 68 | }; 69 | 70 | /** 71 | * Create a new txout. 72 | * 73 | * Can be called with an existing TransactionOut object to add it to the 74 | * transaction. Or it can be called with an Address object and a BigInteger 75 | * for the amount, in which case a new TransactionOut object with those 76 | * values will be created. 77 | */ 78 | Transaction.prototype.addOutput = function (address, value) { 79 | if (arguments[0] instanceof TransactionOut) { 80 | this.outs.push(arguments[0]); 81 | } else { 82 | if (value instanceof BigInteger) { 83 | value = value.toByteArrayUnsigned().reverse(); 84 | while (value.length < 8) value.push(0); 85 | } else if (Bitcoin.Util.isArray(value)) { 86 | // Nothing to do 87 | } 88 | 89 | this.outs.push(new TransactionOut({ 90 | value: value, 91 | script: Script.createOutputScript(address) 92 | })); 93 | } 94 | }; 95 | 96 | /** 97 | * Serialize this transaction. 98 | * 99 | * Returns the transaction as a byte array in the standard Bitcoin binary 100 | * format. This method is byte-perfect, i.e. the resulting byte array can 101 | * be hashed to get the transaction's standard Bitcoin hash. 102 | */ 103 | Transaction.prototype.serialize = function () 104 | { 105 | var buffer = []; 106 | buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(this.version)]).reverse()); 107 | buffer = buffer.concat(Bitcoin.Util.numToVarInt(this.ins.length)); 108 | for (var i = 0; i < this.ins.length; i++) { 109 | var txin = this.ins[i]; 110 | buffer = buffer.concat(Crypto.util.base64ToBytes(txin.outpoint.hash)); 111 | buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.outpoint.index)]).reverse()); 112 | var scriptBytes = txin.script.buffer; 113 | buffer = buffer.concat(Bitcoin.Util.numToVarInt(scriptBytes.length)); 114 | buffer = buffer.concat(scriptBytes); 115 | buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(txin.sequence)]).reverse()); 116 | } 117 | buffer = buffer.concat(Bitcoin.Util.numToVarInt(this.outs.length)); 118 | for (var i = 0; i < this.outs.length; i++) { 119 | var txout = this.outs[i]; 120 | buffer = buffer.concat(txout.value); 121 | var scriptBytes = txout.script.buffer; 122 | buffer = buffer.concat(Bitcoin.Util.numToVarInt(scriptBytes.length)); 123 | buffer = buffer.concat(scriptBytes); 124 | } 125 | buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(this.lock_time)]).reverse()); 126 | 127 | return buffer; 128 | }; 129 | 130 | var OP_CODESEPARATOR = 171; 131 | 132 | var SIGHASH_ALL = 1; 133 | var SIGHASH_NONE = 2; 134 | var SIGHASH_SINGLE = 3; 135 | var SIGHASH_ANYONECANPAY = 80; 136 | 137 | /** 138 | * Hash transaction for signing a specific input. 139 | * 140 | * Bitcoin uses a different hash for each signed transaction input. This 141 | * method copies the transaction, makes the necessary changes based on the 142 | * hashType, serializes and finally hashes the result. This hash can then be 143 | * used to sign the transaction input in question. 144 | */ 145 | Transaction.prototype.hashTransactionForSignature = 146 | function (connectedScript, inIndex, hashType) 147 | { 148 | var txTmp = this.clone(); 149 | 150 | // In case concatenating two scripts ends up with two codeseparators, 151 | // or an extra one at the end, this prevents all those possible 152 | // incompatibilities. 153 | /*scriptCode = scriptCode.filter(function (val) { 154 | return val !== OP_CODESEPARATOR; 155 | });*/ 156 | 157 | // Blank out other inputs' signatures 158 | for (var i = 0; i < txTmp.ins.length; i++) { 159 | txTmp.ins[i].script = new Script(); 160 | } 161 | 162 | txTmp.ins[inIndex].script = connectedScript; 163 | 164 | // Blank out some of the outputs 165 | if ((hashType & 0x1f) == SIGHASH_NONE) { 166 | txTmp.outs = []; 167 | 168 | // Let the others update at will 169 | for (var i = 0; i < txTmp.ins.length; i++) 170 | if (i != inIndex) 171 | txTmp.ins[i].sequence = 0; 172 | } else if ((hashType & 0x1f) == SIGHASH_SINGLE) { 173 | // TODO: Implement 174 | } 175 | 176 | // Blank out other inputs completely, not recommended for open transactions 177 | if (hashType & SIGHASH_ANYONECANPAY) { 178 | txTmp.ins = [txTmp.ins[inIndex]]; 179 | } 180 | 181 | var buffer = txTmp.serialize(); 182 | 183 | buffer = buffer.concat(Crypto.util.wordsToBytes([parseInt(hashType)]).reverse()); 184 | 185 | var hash1 = Crypto.SHA256(buffer, {asBytes: true}); 186 | 187 | return Crypto.SHA256(hash1, {asBytes: true}); 188 | }; 189 | 190 | /** 191 | * Calculate and return the transaction's hash. 192 | */ 193 | Transaction.prototype.getHash = function () 194 | { 195 | var buffer = this.serialize(); 196 | return Crypto.SHA256(Crypto.SHA256(buffer, {asBytes: true}), {asBytes: true}); 197 | }; 198 | 199 | /** 200 | * Create a copy of this transaction object. 201 | */ 202 | Transaction.prototype.clone = function () 203 | { 204 | var newTx = new Transaction(); 205 | newTx.version = this.version; 206 | newTx.lock_time = this.lock_time; 207 | for (var i = 0; i < this.ins.length; i++) { 208 | var txin = this.ins[i].clone(); 209 | newTx.addInput(txin); 210 | } 211 | for (var i = 0; i < this.outs.length; i++) { 212 | var txout = this.outs[i].clone(); 213 | newTx.addOutput(txout); 214 | } 215 | return newTx; 216 | }; 217 | 218 | /** 219 | * Analyze how this transaction affects a wallet. 220 | * 221 | * Returns an object with properties 'impact', 'type' and 'addr'. 222 | * 223 | * 'impact' is an object, see Transaction#calcImpact. 224 | * 225 | * 'type' can be one of the following: 226 | * 227 | * recv: 228 | * This is an incoming transaction, the wallet received money. 229 | * 'addr' contains the first address in the wallet that receives money 230 | * from this transaction. 231 | * 232 | * self: 233 | * This is an internal transaction, money was sent within the wallet. 234 | * 'addr' is undefined. 235 | * 236 | * sent: 237 | * This is an outgoing transaction, money was sent out from the wallet. 238 | * 'addr' contains the first external address, i.e. the recipient. 239 | * 240 | * other: 241 | * This method was unable to detect what the transaction does. Either it 242 | */ 243 | Transaction.prototype.analyze = function (wallet) { 244 | if (!(wallet instanceof Bitcoin.Wallet)) return null; 245 | 246 | var allFromMe = true, 247 | allToMe = true, 248 | firstRecvHash = null, 249 | firstMeRecvHash = null, 250 | firstSendHash = null; 251 | 252 | for (var i = this.outs.length-1; i >= 0; i--) { 253 | var txout = this.outs[i]; 254 | var hash = txout.script.simpleOutPubKeyHash(); 255 | if (!wallet.hasHash(hash)) { 256 | allToMe = false; 257 | } else { 258 | firstMeRecvHash = hash; 259 | } 260 | firstRecvHash = hash; 261 | } 262 | for (var i = this.ins.length-1; i >= 0; i--) { 263 | var txin = this.ins[i]; 264 | firstSendHash = txin.script.simpleInPubKeyHash(); 265 | if (!wallet.hasHash(firstSendHash)) { 266 | allFromMe = false; 267 | break; 268 | } 269 | } 270 | 271 | var impact = this.calcImpact(wallet); 272 | 273 | var analysis = {}; 274 | 275 | analysis.impact = impact; 276 | 277 | if (impact.sign > 0 && impact.value.compareTo(BigInteger.ZERO) > 0) { 278 | analysis.type = 'recv'; 279 | analysis.addr = new Bitcoin.Address(firstMeRecvHash); 280 | } else if (allFromMe && allToMe) { 281 | analysis.type = 'self'; 282 | } else if (allFromMe) { 283 | analysis.type = 'sent'; 284 | // TODO: Right now, firstRecvHash is the first output, which - if the 285 | // transaction was not generated by this library could be the 286 | // change address. 287 | analysis.addr = new Bitcoin.Address(firstRecvHash); 288 | } else { 289 | analysis.type = "other"; 290 | } 291 | 292 | return analysis; 293 | }; 294 | 295 | /** 296 | * Get a human-readable version of the data returned by Transaction#analyze. 297 | * 298 | * This is merely a convenience function. Clients should consider implementing 299 | * this themselves based on their UI, I18N, etc. 300 | */ 301 | Transaction.prototype.getDescription = function (wallet) { 302 | var analysis = this.analyze(wallet); 303 | 304 | if (!analysis) return ""; 305 | 306 | switch (analysis.type) { 307 | case 'recv': 308 | return "Received with "+analysis.addr; 309 | break; 310 | 311 | case 'sent': 312 | return "Payment to "+analysis.addr; 313 | break; 314 | 315 | case 'self': 316 | return "Payment to yourself"; 317 | break; 318 | 319 | case 'other': 320 | default: 321 | return ""; 322 | } 323 | }; 324 | 325 | /** 326 | * Get the total amount of a transaction's outputs. 327 | */ 328 | Transaction.prototype.getTotalOutValue = function () { 329 | var totalValue = BigInteger.ZERO; 330 | for (var j = 0; j < this.outs.length; j++) { 331 | var txout = this.outs[j]; 332 | totalValue = totalValue.add(Bitcoin.Util.valueToBigInt(txout.value)); 333 | } 334 | return totalValue; 335 | }; 336 | 337 | /** 338 | * Old name for Transaction#getTotalOutValue. 339 | * 340 | * @deprecated 341 | */ 342 | Transaction.prototype.getTotalValue = Transaction.prototype.getTotalOutValue; 343 | 344 | /** 345 | * Calculates the impact a transaction has on this wallet. 346 | * 347 | * Based on the its public keys, the wallet will calculate the 348 | * credit or debit of this transaction. 349 | * 350 | * It will return an object with two properties: 351 | * - sign: 1 or -1 depending on sign of the calculated impact. 352 | * - value: amount of calculated impact 353 | * 354 | * @returns Object Impact on wallet 355 | */ 356 | Transaction.prototype.calcImpact = function (wallet) { 357 | if (!(wallet instanceof Bitcoin.Wallet)) return BigInteger.ZERO; 358 | 359 | // Calculate credit to us from all outputs 360 | var valueOut = BigInteger.ZERO; 361 | for (var j = 0; j < this.outs.length; j++) { 362 | var txout = this.outs[j]; 363 | var hash = Crypto.util.bytesToBase64(txout.script.simpleOutPubKeyHash()); 364 | if (wallet.hasHash(hash)) { 365 | valueOut = valueOut.add(Bitcoin.Util.valueToBigInt(txout.value)); 366 | } 367 | } 368 | 369 | // Calculate debit to us from all ins 370 | var valueIn = BigInteger.ZERO; 371 | for (var j = 0; j < this.ins.length; j++) { 372 | var txin = this.ins[j]; 373 | var hash = Crypto.util.bytesToBase64(txin.script.simpleInPubKeyHash()); 374 | if (wallet.hasHash(hash)) { 375 | var fromTx = wallet.txIndex[txin.outpoint.hash]; 376 | if (fromTx) { 377 | valueIn = valueIn.add(Bitcoin.Util.valueToBigInt(fromTx.outs[txin.outpoint.index].value)); 378 | } 379 | } 380 | } 381 | if (valueOut.compareTo(valueIn) >= 0) { 382 | return { 383 | sign: 1, 384 | value: valueOut.subtract(valueIn) 385 | }; 386 | } else { 387 | return { 388 | sign: -1, 389 | value: valueIn.subtract(valueOut) 390 | }; 391 | } 392 | }; 393 | 394 | var TransactionIn = Bitcoin.TransactionIn = function (data) 395 | { 396 | this.outpoint = data.outpoint; 397 | if (data.script instanceof Script) { 398 | this.script = data.script; 399 | } else { 400 | this.script = new Script(data.script); 401 | } 402 | this.sequence = data.sequence; 403 | }; 404 | 405 | TransactionIn.prototype.clone = function () 406 | { 407 | var newTxin = new TransactionIn({ 408 | outpoint: { 409 | hash: this.outpoint.hash, 410 | index: this.outpoint.index 411 | }, 412 | script: this.script.clone(), 413 | sequence: this.sequence 414 | }); 415 | return newTxin; 416 | }; 417 | 418 | var TransactionOut = Bitcoin.TransactionOut = function (data) 419 | { 420 | if (data.script instanceof Script) { 421 | this.script = data.script; 422 | } else { 423 | this.script = new Script(data.script); 424 | } 425 | 426 | if (Bitcoin.Util.isArray(data.value)) { 427 | this.value = data.value; 428 | } else if ("string" == typeof data.value) { 429 | var valueHex = (new BigInteger(data.value, 10)).toString(16); 430 | while (valueHex.length < 16) valueHex = "0" + valueHex; 431 | this.value = Crypto.util.hexToBytes(valueHex); 432 | } 433 | }; 434 | 435 | TransactionOut.prototype.clone = function () 436 | { 437 | var newTxout = new TransactionOut({ 438 | script: this.script.clone(), 439 | value: this.value.slice(0) 440 | }); 441 | return newTxout; 442 | }; 443 | })(); 444 | 445 | 446 | -------------------------------------------------------------------------------- /src/jsbn/jsbn.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2005 Tom Wu 2 | // All Rights Reserved. 3 | // See "LICENSE" for details. 4 | 5 | // Basic JavaScript BN library - subset useful for RSA encryption. 6 | 7 | // Bits per digit 8 | var dbits; 9 | 10 | // JavaScript engine analysis 11 | var canary = 0xdeadbeefcafe; 12 | var j_lm = ((canary&0xffffff)==0xefcafe); 13 | 14 | // (public) Constructor 15 | function BigInteger(a,b,c) { 16 | if(a != null) 17 | if("number" == typeof a) this.fromNumber(a,b,c); 18 | else if(b == null && "string" != typeof a) this.fromString(a,256); 19 | else this.fromString(a,b); 20 | } 21 | 22 | // return new, unset BigInteger 23 | function nbi() { return new BigInteger(null); } 24 | 25 | // am: Compute w_j += (x*this_i), propagate carries, 26 | // c is initial carry, returns final carry. 27 | // c < 3*dvalue, x < 2*dvalue, this_i < dvalue 28 | // We need to select the fastest one that works in this environment. 29 | 30 | // am1: use a single mult and divide to get the high bits, 31 | // max digit bits should be 26 because 32 | // max internal value = 2*dvalue^2-2*dvalue (< 2^53) 33 | function am1(i,x,w,j,c,n) { 34 | while(--n >= 0) { 35 | var v = x*this[i++]+w[j]+c; 36 | c = Math.floor(v/0x4000000); 37 | w[j++] = v&0x3ffffff; 38 | } 39 | return c; 40 | } 41 | // am2 avoids a big mult-and-extract completely. 42 | // Max digit bits should be <= 30 because we do bitwise ops 43 | // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) 44 | function am2(i,x,w,j,c,n) { 45 | var xl = x&0x7fff, xh = x>>15; 46 | while(--n >= 0) { 47 | var l = this[i]&0x7fff; 48 | var h = this[i++]>>15; 49 | var m = xh*l+h*xl; 50 | l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); 51 | c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); 52 | w[j++] = l&0x3fffffff; 53 | } 54 | return c; 55 | } 56 | // Alternately, set max digit bits to 28 since some 57 | // browsers slow down when dealing with 32-bit numbers. 58 | function am3(i,x,w,j,c,n) { 59 | var xl = x&0x3fff, xh = x>>14; 60 | while(--n >= 0) { 61 | var l = this[i]&0x3fff; 62 | var h = this[i++]>>14; 63 | var m = xh*l+h*xl; 64 | l = xl*l+((m&0x3fff)<<14)+w[j]+c; 65 | c = (l>>28)+(m>>14)+xh*h; 66 | w[j++] = l&0xfffffff; 67 | } 68 | return c; 69 | } 70 | if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { 71 | BigInteger.prototype.am = am2; 72 | dbits = 30; 73 | } 74 | else if(j_lm && (navigator.appName != "Netscape")) { 75 | BigInteger.prototype.am = am1; 76 | dbits = 26; 77 | } 78 | else { // Mozilla/Netscape seems to prefer am3 79 | BigInteger.prototype.am = am3; 80 | dbits = 28; 81 | } 82 | 83 | BigInteger.prototype.DB = dbits; 84 | BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; 112 | r.t = this.t; 113 | r.s = this.s; 114 | } 115 | 116 | // (protected) set from integer value x, -DV <= x < DV 117 | function bnpFromInt(x) { 118 | this.t = 1; 119 | this.s = (x<0)?-1:0; 120 | if(x > 0) this[0] = x; 121 | else if(x < -1) this[0] = x+DV; 122 | else this.t = 0; 123 | } 124 | 125 | // return bigint initialized to value 126 | function nbv(i) { var r = nbi(); r.fromInt(i); return r; } 127 | 128 | // (protected) set from string and radix 129 | function bnpFromString(s,b) { 130 | var k; 131 | if(b == 16) k = 4; 132 | else if(b == 8) k = 3; 133 | else if(b == 256) k = 8; // byte array 134 | else if(b == 2) k = 1; 135 | else if(b == 32) k = 5; 136 | else if(b == 4) k = 2; 137 | else { this.fromRadix(s,b); return; } 138 | this.t = 0; 139 | this.s = 0; 140 | var i = s.length, mi = false, sh = 0; 141 | while(--i >= 0) { 142 | var x = (k==8)?s[i]&0xff:intAt(s,i); 143 | if(x < 0) { 144 | if(s.charAt(i) == "-") mi = true; 145 | continue; 146 | } 147 | mi = false; 148 | if(sh == 0) 149 | this[this.t++] = x; 150 | else if(sh+k > this.DB) { 151 | this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); 153 | } 154 | else 155 | this[this.t-1] |= x<= this.DB) sh -= this.DB; 158 | } 159 | if(k == 8 && (s[0]&0x80) != 0) { 160 | this.s = -1; 161 | if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; 171 | } 172 | 173 | // (public) return string representation in given radix 174 | function bnToString(b) { 175 | if(this.s < 0) return "-"+this.negate().toString(b); 176 | var k; 177 | if(b == 16) k = 4; 178 | else if(b == 8) k = 3; 179 | else if(b == 2) k = 1; 180 | else if(b == 32) k = 5; 181 | else if(b == 4) k = 2; 182 | else return this.toRadix(b); 183 | var km = (1< 0) { 186 | if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } 187 | while(i >= 0) { 188 | if(p < k) { 189 | d = (this[i]&((1<>(p+=this.DB-k); 191 | } 192 | else { 193 | d = (this[i]>>(p-=k))&km; 194 | if(p <= 0) { p += this.DB; --i; } 195 | } 196 | if(d > 0) m = true; 197 | if(m) r += int2char(d); 198 | } 199 | } 200 | return m?r:"0"; 201 | } 202 | 203 | // (public) -this 204 | function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } 205 | 206 | // (public) |this| 207 | function bnAbs() { return (this.s<0)?this.negate():this; } 208 | 209 | // (public) return + if this > a, - if this < a, 0 if equal 210 | function bnCompareTo(a) { 211 | var r = this.s-a.s; 212 | if(r != 0) return r; 213 | var i = this.t; 214 | r = i-a.t; 215 | if(r != 0) return (this.s<0)?-r:r; 216 | while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; 217 | return 0; 218 | } 219 | 220 | // returns bit length of the integer x 221 | function nbits(x) { 222 | var r = 1, t; 223 | if((t=x>>>16) != 0) { x = t; r += 16; } 224 | if((t=x>>8) != 0) { x = t; r += 8; } 225 | if((t=x>>4) != 0) { x = t; r += 4; } 226 | if((t=x>>2) != 0) { x = t; r += 2; } 227 | if((t=x>>1) != 0) { x = t; r += 1; } 228 | return r; 229 | } 230 | 231 | // (public) return the number of bits in "this" 232 | function bnBitLength() { 233 | if(this.t <= 0) return 0; 234 | return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); 235 | } 236 | 237 | // (protected) r = this << n*DB 238 | function bnpDLShiftTo(n,r) { 239 | var i; 240 | for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; 241 | for(i = n-1; i >= 0; --i) r[i] = 0; 242 | r.t = this.t+n; 243 | r.s = this.s; 244 | } 245 | 246 | // (protected) r = this >> n*DB 247 | function bnpDRShiftTo(n,r) { 248 | for(var i = n; i < this.t; ++i) r[i-n] = this[i]; 249 | r.t = Math.max(this.t-n,0); 250 | r.s = this.s; 251 | } 252 | 253 | // (protected) r = this << n 254 | function bnpLShiftTo(n,r) { 255 | var bs = n%this.DB; 256 | var cbs = this.DB-bs; 257 | var bm = (1<= 0; --i) { 260 | r[i+ds+1] = (this[i]>>cbs)|c; 261 | c = (this[i]&bm)<= 0; --i) r[i] = 0; 264 | r[ds] = c; 265 | r.t = this.t+ds+1; 266 | r.s = this.s; 267 | r.clamp(); 268 | } 269 | 270 | // (protected) r = this >> n 271 | function bnpRShiftTo(n,r) { 272 | r.s = this.s; 273 | var ds = Math.floor(n/this.DB); 274 | if(ds >= this.t) { r.t = 0; return; } 275 | var bs = n%this.DB; 276 | var cbs = this.DB-bs; 277 | var bm = (1<>bs; 279 | for(var i = ds+1; i < this.t; ++i) { 280 | r[i-ds-1] |= (this[i]&bm)<>bs; 282 | } 283 | if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; 295 | } 296 | if(a.t < this.t) { 297 | c -= a.s; 298 | while(i < this.t) { 299 | c += this[i]; 300 | r[i++] = c&this.DM; 301 | c >>= this.DB; 302 | } 303 | c += this.s; 304 | } 305 | else { 306 | c += this.s; 307 | while(i < a.t) { 308 | c -= a[i]; 309 | r[i++] = c&this.DM; 310 | c >>= this.DB; 311 | } 312 | c -= a.s; 313 | } 314 | r.s = (c<0)?-1:0; 315 | if(c < -1) r[i++] = this.DV+c; 316 | else if(c > 0) r[i++] = c; 317 | r.t = i; 318 | r.clamp(); 319 | } 320 | 321 | // (protected) r = this * a, r != this,a (HAC 14.12) 322 | // "this" should be the larger one if appropriate. 323 | function bnpMultiplyTo(a,r) { 324 | var x = this.abs(), y = a.abs(); 325 | var i = x.t; 326 | r.t = i+y.t; 327 | while(--i >= 0) r[i] = 0; 328 | for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); 329 | r.s = 0; 330 | r.clamp(); 331 | if(this.s != a.s) BigInteger.ZERO.subTo(r,r); 332 | } 333 | 334 | // (protected) r = this^2, r != this (HAC 14.16) 335 | function bnpSquareTo(r) { 336 | var x = this.abs(); 337 | var i = r.t = 2*x.t; 338 | while(--i >= 0) r[i] = 0; 339 | for(i = 0; i < x.t-1; ++i) { 340 | var c = x.am(i,x[i],r,2*i,0,1); 341 | if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { 342 | r[i+x.t] -= x.DV; 343 | r[i+x.t+1] = 1; 344 | } 345 | } 346 | if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); 347 | r.s = 0; 348 | r.clamp(); 349 | } 350 | 351 | // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) 352 | // r != q, this != m. q or r may be null. 353 | function bnpDivRemTo(m,q,r) { 354 | var pm = m.abs(); 355 | if(pm.t <= 0) return; 356 | var pt = this.abs(); 357 | if(pt.t < pm.t) { 358 | if(q != null) q.fromInt(0); 359 | if(r != null) this.copyTo(r); 360 | return; 361 | } 362 | if(r == null) r = nbi(); 363 | var y = nbi(), ts = this.s, ms = m.s; 364 | var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus 365 | if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } 366 | else { pm.copyTo(y); pt.copyTo(r); } 367 | var ys = y.t; 368 | var y0 = y[ys-1]; 369 | if(y0 == 0) return; 370 | var yt = y0*(1<1)?y[ys-2]>>this.F2:0); 371 | var d1 = this.FV/yt, d2 = (1<= 0) { 375 | r[r.t++] = 1; 376 | r.subTo(t,r); 377 | } 378 | BigInteger.ONE.dlShiftTo(ys,t); 379 | t.subTo(y,y); // "negative" y so we can replace sub with am later 380 | while(y.t < ys) y[y.t++] = 0; 381 | while(--j >= 0) { 382 | // Estimate quotient digit 383 | var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); 384 | if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out 385 | y.dlShiftTo(j,t); 386 | r.subTo(t,r); 387 | while(r[i] < --qd) r.subTo(t,r); 388 | } 389 | } 390 | if(q != null) { 391 | r.drShiftTo(ys,q); 392 | if(ts != ms) BigInteger.ZERO.subTo(q,q); 393 | } 394 | r.t = ys; 395 | r.clamp(); 396 | if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder 397 | if(ts < 0) BigInteger.ZERO.subTo(r,r); 398 | } 399 | 400 | // (public) this mod a 401 | function bnMod(a) { 402 | var r = nbi(); 403 | this.abs().divRemTo(a,null,r); 404 | if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); 405 | return r; 406 | } 407 | 408 | // Modular reduction using "classic" algorithm 409 | function Classic(m) { this.m = m; } 410 | function cConvert(x) { 411 | if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); 412 | else return x; 413 | } 414 | function cRevert(x) { return x; } 415 | function cReduce(x) { x.divRemTo(this.m,null,x); } 416 | function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } 417 | function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } 418 | 419 | Classic.prototype.convert = cConvert; 420 | Classic.prototype.revert = cRevert; 421 | Classic.prototype.reduce = cReduce; 422 | Classic.prototype.mulTo = cMulTo; 423 | Classic.prototype.sqrTo = cSqrTo; 424 | 425 | // (protected) return "-1/this % 2^DB"; useful for Mont. reduction 426 | // justification: 427 | // xy == 1 (mod m) 428 | // xy = 1+km 429 | // xy(2-xy) = (1+km)(1-km) 430 | // x[y(2-xy)] = 1-k^2m^2 431 | // x[y(2-xy)] == 1 (mod m^2) 432 | // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 433 | // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. 434 | // JS multiply "overflows" differently from C/C++, so care is needed here. 435 | function bnpInvDigit() { 436 | if(this.t < 1) return 0; 437 | var x = this[0]; 438 | if((x&1) == 0) return 0; 439 | var y = x&3; // y == 1/x mod 2^2 440 | y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 441 | y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 442 | y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 443 | // last step - calculate inverse mod DV directly; 444 | // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints 445 | y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits 446 | // we really want the negative inverse, and -DV < y < DV 447 | return (y>0)?this.DV-y:-y; 448 | } 449 | 450 | // Montgomery reduction 451 | function Montgomery(m) { 452 | this.m = m; 453 | this.mp = m.invDigit(); 454 | this.mpl = this.mp&0x7fff; 455 | this.mph = this.mp>>15; 456 | this.um = (1<<(m.DB-15))-1; 457 | this.mt2 = 2*m.t; 458 | } 459 | 460 | // xR mod m 461 | function montConvert(x) { 462 | var r = nbi(); 463 | x.abs().dlShiftTo(this.m.t,r); 464 | r.divRemTo(this.m,null,r); 465 | if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); 466 | return r; 467 | } 468 | 469 | // x/R mod m 470 | function montRevert(x) { 471 | var r = nbi(); 472 | x.copyTo(r); 473 | this.reduce(r); 474 | return r; 475 | } 476 | 477 | // x = x/R mod m (HAC 14.32) 478 | function montReduce(x) { 479 | while(x.t <= this.mt2) // pad x so am has enough room later 480 | x[x.t++] = 0; 481 | for(var i = 0; i < this.m.t; ++i) { 482 | // faster way of calculating u0 = x[i]*mp mod DV 483 | var j = x[i]&0x7fff; 484 | var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; 485 | // use am to combine the multiply-shift-add into one call 486 | j = i+this.m.t; 487 | x[j] += this.m.am(0,u0,x,i,0,this.m.t); 488 | // propagate carry 489 | while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } 490 | } 491 | x.clamp(); 492 | x.drShiftTo(this.m.t,x); 493 | if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); 494 | } 495 | 496 | // r = "x^2/R mod m"; x != r 497 | function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } 498 | 499 | // r = "xy/R mod m"; x,y != r 500 | function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } 501 | 502 | Montgomery.prototype.convert = montConvert; 503 | Montgomery.prototype.revert = montRevert; 504 | Montgomery.prototype.reduce = montReduce; 505 | Montgomery.prototype.mulTo = montMulTo; 506 | Montgomery.prototype.sqrTo = montSqrTo; 507 | 508 | // (protected) true iff this is even 509 | function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } 510 | 511 | // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) 512 | function bnpExp(e,z) { 513 | if(e > 0xffffffff || e < 1) return BigInteger.ONE; 514 | var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; 515 | g.copyTo(r); 516 | while(--i >= 0) { 517 | z.sqrTo(r,r2); 518 | if((e&(1< 0) z.mulTo(r2,g,r); 519 | else { var t = r; r = r2; r2 = t; } 520 | } 521 | return z.revert(r); 522 | } 523 | 524 | // (public) this^e % m, 0 <= e < 2^32 525 | function bnModPowInt(e,m) { 526 | var z; 527 | if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); 528 | return this.exp(e,z); 529 | } 530 | 531 | // protected 532 | BigInteger.prototype.copyTo = bnpCopyTo; 533 | BigInteger.prototype.fromInt = bnpFromInt; 534 | BigInteger.prototype.fromString = bnpFromString; 535 | BigInteger.prototype.clamp = bnpClamp; 536 | BigInteger.prototype.dlShiftTo = bnpDLShiftTo; 537 | BigInteger.prototype.drShiftTo = bnpDRShiftTo; 538 | BigInteger.prototype.lShiftTo = bnpLShiftTo; 539 | BigInteger.prototype.rShiftTo = bnpRShiftTo; 540 | BigInteger.prototype.subTo = bnpSubTo; 541 | BigInteger.prototype.multiplyTo = bnpMultiplyTo; 542 | BigInteger.prototype.squareTo = bnpSquareTo; 543 | BigInteger.prototype.divRemTo = bnpDivRemTo; 544 | BigInteger.prototype.invDigit = bnpInvDigit; 545 | BigInteger.prototype.isEven = bnpIsEven; 546 | BigInteger.prototype.exp = bnpExp; 547 | 548 | // public 549 | BigInteger.prototype.toString = bnToString; 550 | BigInteger.prototype.negate = bnNegate; 551 | BigInteger.prototype.abs = bnAbs; 552 | BigInteger.prototype.compareTo = bnCompareTo; 553 | BigInteger.prototype.bitLength = bnBitLength; 554 | BigInteger.prototype.mod = bnMod; 555 | BigInteger.prototype.modPowInt = bnModPowInt; 556 | 557 | // "constants" 558 | BigInteger.ZERO = nbv(0); 559 | BigInteger.ONE = nbv(1); 560 | -------------------------------------------------------------------------------- /src/jsbn/jsbn2.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2005-2009 Tom Wu 2 | // All Rights Reserved. 3 | // See "LICENSE" for details. 4 | 5 | // Extended JavaScript BN functions, required for RSA private ops. 6 | 7 | // Version 1.1: new BigInteger("0", 10) returns "proper" zero 8 | // Version 1.2: square() API, isProbablePrime fix 9 | 10 | // (public) 11 | function bnClone() { var r = nbi(); this.copyTo(r); return r; } 12 | 13 | // (public) return value as integer 14 | function bnIntValue() { 15 | if(this.s < 0) { 16 | if(this.t == 1) return this[0]-this.DV; 17 | else if(this.t == 0) return -1; 18 | } 19 | else if(this.t == 1) return this[0]; 20 | else if(this.t == 0) return 0; 21 | // assumes 16 < DB < 32 22 | return ((this[1]&((1<<(32-this.DB))-1))<>24; } 27 | 28 | // (public) return value as short (assumes DB>=16) 29 | function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; } 30 | 31 | // (protected) return x s.t. r^x < DV 32 | function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } 33 | 34 | // (public) 0 if this == 0, 1 if this > 0 35 | function bnSigNum() { 36 | if(this.s < 0) return -1; 37 | else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; 38 | else return 1; 39 | } 40 | 41 | // (protected) convert to radix string 42 | function bnpToRadix(b) { 43 | if(b == null) b = 10; 44 | if(this.signum() == 0 || b < 2 || b > 36) return "0"; 45 | var cs = this.chunkSize(b); 46 | var a = Math.pow(b,cs); 47 | var d = nbv(a), y = nbi(), z = nbi(), r = ""; 48 | this.divRemTo(d,y,z); 49 | while(y.signum() > 0) { 50 | r = (a+z.intValue()).toString(b).substr(1) + r; 51 | y.divRemTo(d,y,z); 52 | } 53 | return z.intValue().toString(b) + r; 54 | } 55 | 56 | // (protected) convert from radix string 57 | function bnpFromRadix(s,b) { 58 | this.fromInt(0); 59 | if(b == null) b = 10; 60 | var cs = this.chunkSize(b); 61 | var d = Math.pow(b,cs), mi = false, j = 0, w = 0; 62 | for(var i = 0; i < s.length; ++i) { 63 | var x = intAt(s,i); 64 | if(x < 0) { 65 | if(s.charAt(i) == "-" && this.signum() == 0) mi = true; 66 | continue; 67 | } 68 | w = b*w+x; 69 | if(++j >= cs) { 70 | this.dMultiply(d); 71 | this.dAddOffset(w,0); 72 | j = 0; 73 | w = 0; 74 | } 75 | } 76 | if(j > 0) { 77 | this.dMultiply(Math.pow(b,j)); 78 | this.dAddOffset(w,0); 79 | } 80 | if(mi) BigInteger.ZERO.subTo(this,this); 81 | } 82 | 83 | // (protected) alternate constructor 84 | function bnpFromNumber(a,b,c) { 85 | if("number" == typeof b) { 86 | // new BigInteger(int,int,RNG) 87 | if(a < 2) this.fromInt(1); 88 | else { 89 | this.fromNumber(a,c); 90 | if(!this.testBit(a-1)) // force MSB set 91 | this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); 92 | if(this.isEven()) this.dAddOffset(1,0); // force odd 93 | while(!this.isProbablePrime(b)) { 94 | this.dAddOffset(2,0); 95 | if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this); 96 | } 97 | } 98 | } 99 | else { 100 | // new BigInteger(int,RNG) 101 | var x = new Array(), t = a&7; 102 | x.length = (a>>3)+1; 103 | b.nextBytes(x); 104 | if(t > 0) x[0] &= ((1< 0) { 115 | if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p) 116 | r[k++] = d|(this.s<<(this.DB-p)); 117 | while(i >= 0) { 118 | if(p < 8) { 119 | d = (this[i]&((1<>(p+=this.DB-8); 121 | } 122 | else { 123 | d = (this[i]>>(p-=8))&0xff; 124 | if(p <= 0) { p += this.DB; --i; } 125 | } 126 | if((d&0x80) != 0) d |= -256; 127 | if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; 128 | if(k > 0 || d != this.s) r[k++] = d; 129 | } 130 | } 131 | return r; 132 | } 133 | 134 | function bnEquals(a) { return(this.compareTo(a)==0); } 135 | function bnMin(a) { return(this.compareTo(a)<0)?this:a; } 136 | function bnMax(a) { return(this.compareTo(a)>0)?this:a; } 137 | 138 | // (protected) r = this op a (bitwise) 139 | function bnpBitwiseTo(a,op,r) { 140 | var i, f, m = Math.min(a.t,this.t); 141 | for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]); 142 | if(a.t < this.t) { 143 | f = a.s&this.DM; 144 | for(i = m; i < this.t; ++i) r[i] = op(this[i],f); 145 | r.t = this.t; 146 | } 147 | else { 148 | f = this.s&this.DM; 149 | for(i = m; i < a.t; ++i) r[i] = op(f,a[i]); 150 | r.t = a.t; 151 | } 152 | r.s = op(this.s,a.s); 153 | r.clamp(); 154 | } 155 | 156 | // (public) this & a 157 | function op_and(x,y) { return x&y; } 158 | function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } 159 | 160 | // (public) this | a 161 | function op_or(x,y) { return x|y; } 162 | function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } 163 | 164 | // (public) this ^ a 165 | function op_xor(x,y) { return x^y; } 166 | function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } 167 | 168 | // (public) this & ~a 169 | function op_andnot(x,y) { return x&~y; } 170 | function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } 171 | 172 | // (public) ~this 173 | function bnNot() { 174 | var r = nbi(); 175 | for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i]; 176 | r.t = this.t; 177 | r.s = ~this.s; 178 | return r; 179 | } 180 | 181 | // (public) this << n 182 | function bnShiftLeft(n) { 183 | var r = nbi(); 184 | if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); 185 | return r; 186 | } 187 | 188 | // (public) this >> n 189 | function bnShiftRight(n) { 190 | var r = nbi(); 191 | if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); 192 | return r; 193 | } 194 | 195 | // return index of lowest 1-bit in x, x < 2^31 196 | function lbit(x) { 197 | if(x == 0) return -1; 198 | var r = 0; 199 | if((x&0xffff) == 0) { x >>= 16; r += 16; } 200 | if((x&0xff) == 0) { x >>= 8; r += 8; } 201 | if((x&0xf) == 0) { x >>= 4; r += 4; } 202 | if((x&3) == 0) { x >>= 2; r += 2; } 203 | if((x&1) == 0) ++r; 204 | return r; 205 | } 206 | 207 | // (public) returns index of lowest 1-bit (or -1 if none) 208 | function bnGetLowestSetBit() { 209 | for(var i = 0; i < this.t; ++i) 210 | if(this[i] != 0) return i*this.DB+lbit(this[i]); 211 | if(this.s < 0) return this.t*this.DB; 212 | return -1; 213 | } 214 | 215 | // return number of 1 bits in x 216 | function cbit(x) { 217 | var r = 0; 218 | while(x != 0) { x &= x-1; ++r; } 219 | return r; 220 | } 221 | 222 | // (public) return number of set bits 223 | function bnBitCount() { 224 | var r = 0, x = this.s&this.DM; 225 | for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x); 226 | return r; 227 | } 228 | 229 | // (public) true iff nth bit is set 230 | function bnTestBit(n) { 231 | var j = Math.floor(n/this.DB); 232 | if(j >= this.t) return(this.s!=0); 233 | return((this[j]&(1<<(n%this.DB)))!=0); 234 | } 235 | 236 | // (protected) this op (1<>= this.DB; 259 | } 260 | if(a.t < this.t) { 261 | c += a.s; 262 | while(i < this.t) { 263 | c += this[i]; 264 | r[i++] = c&this.DM; 265 | c >>= this.DB; 266 | } 267 | c += this.s; 268 | } 269 | else { 270 | c += this.s; 271 | while(i < a.t) { 272 | c += a[i]; 273 | r[i++] = c&this.DM; 274 | c >>= this.DB; 275 | } 276 | c += a.s; 277 | } 278 | r.s = (c<0)?-1:0; 279 | if(c > 0) r[i++] = c; 280 | else if(c < -1) r[i++] = this.DV+c; 281 | r.t = i; 282 | r.clamp(); 283 | } 284 | 285 | // (public) this + a 286 | function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } 287 | 288 | // (public) this - a 289 | function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } 290 | 291 | // (public) this * a 292 | function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } 293 | 294 | // (public) this^2 295 | function bnSquare() { var r = nbi(); this.squareTo(r); return r; } 296 | 297 | // (public) this / a 298 | function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } 299 | 300 | // (public) this % a 301 | function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } 302 | 303 | // (public) [this/a,this%a] 304 | function bnDivideAndRemainder(a) { 305 | var q = nbi(), r = nbi(); 306 | this.divRemTo(a,q,r); 307 | return new Array(q,r); 308 | } 309 | 310 | // (protected) this *= n, this >= 0, 1 < n < DV 311 | function bnpDMultiply(n) { 312 | this[this.t] = this.am(0,n-1,this,0,0,this.t); 313 | ++this.t; 314 | this.clamp(); 315 | } 316 | 317 | // (protected) this += n << w words, this >= 0 318 | function bnpDAddOffset(n,w) { 319 | if(n == 0) return; 320 | while(this.t <= w) this[this.t++] = 0; 321 | this[w] += n; 322 | while(this[w] >= this.DV) { 323 | this[w] -= this.DV; 324 | if(++w >= this.t) this[this.t++] = 0; 325 | ++this[w]; 326 | } 327 | } 328 | 329 | // A "null" reducer 330 | function NullExp() {} 331 | function nNop(x) { return x; } 332 | function nMulTo(x,y,r) { x.multiplyTo(y,r); } 333 | function nSqrTo(x,r) { x.squareTo(r); } 334 | 335 | NullExp.prototype.convert = nNop; 336 | NullExp.prototype.revert = nNop; 337 | NullExp.prototype.mulTo = nMulTo; 338 | NullExp.prototype.sqrTo = nSqrTo; 339 | 340 | // (public) this^e 341 | function bnPow(e) { return this.exp(e,new NullExp()); } 342 | 343 | // (protected) r = lower n words of "this * a", a.t <= n 344 | // "this" should be the larger one if appropriate. 345 | function bnpMultiplyLowerTo(a,n,r) { 346 | var i = Math.min(this.t+a.t,n); 347 | r.s = 0; // assumes a,this >= 0 348 | r.t = i; 349 | while(i > 0) r[--i] = 0; 350 | var j; 351 | for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t); 352 | for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i); 353 | r.clamp(); 354 | } 355 | 356 | // (protected) r = "this * a" without lower n words, n > 0 357 | // "this" should be the larger one if appropriate. 358 | function bnpMultiplyUpperTo(a,n,r) { 359 | --n; 360 | var i = r.t = this.t+a.t-n; 361 | r.s = 0; // assumes a,this >= 0 362 | while(--i >= 0) r[i] = 0; 363 | for(i = Math.max(n-this.t,0); i < a.t; ++i) 364 | r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n); 365 | r.clamp(); 366 | r.drShiftTo(1,r); 367 | } 368 | 369 | // Barrett modular reduction 370 | function Barrett(m) { 371 | // setup Barrett 372 | this.r2 = nbi(); 373 | this.q3 = nbi(); 374 | BigInteger.ONE.dlShiftTo(2*m.t,this.r2); 375 | this.mu = this.r2.divide(m); 376 | this.m = m; 377 | } 378 | 379 | function barrettConvert(x) { 380 | if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); 381 | else if(x.compareTo(this.m) < 0) return x; 382 | else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } 383 | } 384 | 385 | function barrettRevert(x) { return x; } 386 | 387 | // x = x mod m (HAC 14.42) 388 | function barrettReduce(x) { 389 | x.drShiftTo(this.m.t-1,this.r2); 390 | if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } 391 | this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); 392 | this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); 393 | while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); 394 | x.subTo(this.r2,x); 395 | while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); 396 | } 397 | 398 | // r = x^2 mod m; x != r 399 | function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } 400 | 401 | // r = x*y mod m; x,y != r 402 | function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } 403 | 404 | Barrett.prototype.convert = barrettConvert; 405 | Barrett.prototype.revert = barrettRevert; 406 | Barrett.prototype.reduce = barrettReduce; 407 | Barrett.prototype.mulTo = barrettMulTo; 408 | Barrett.prototype.sqrTo = barrettSqrTo; 409 | 410 | // (public) this^e % m (HAC 14.85) 411 | function bnModPow(e,m) { 412 | var i = e.bitLength(), k, r = nbv(1), z; 413 | if(i <= 0) return r; 414 | else if(i < 18) k = 1; 415 | else if(i < 48) k = 3; 416 | else if(i < 144) k = 4; 417 | else if(i < 768) k = 5; 418 | else k = 6; 419 | if(i < 8) 420 | z = new Classic(m); 421 | else if(m.isEven()) 422 | z = new Barrett(m); 423 | else 424 | z = new Montgomery(m); 425 | 426 | // precomputation 427 | var g = new Array(), n = 3, k1 = k-1, km = (1< 1) { 430 | var g2 = nbi(); 431 | z.sqrTo(g[1],g2); 432 | while(n <= km) { 433 | g[n] = nbi(); 434 | z.mulTo(g2,g[n-2],g[n]); 435 | n += 2; 436 | } 437 | } 438 | 439 | var j = e.t-1, w, is1 = true, r2 = nbi(), t; 440 | i = nbits(e[j])-1; 441 | while(j >= 0) { 442 | if(i >= k1) w = (e[j]>>(i-k1))&km; 443 | else { 444 | w = (e[j]&((1<<(i+1))-1))<<(k1-i); 445 | if(j > 0) w |= e[j-1]>>(this.DB+i-k1); 446 | } 447 | 448 | n = k; 449 | while((w&1) == 0) { w >>= 1; --n; } 450 | if((i -= n) < 0) { i += this.DB; --j; } 451 | if(is1) { // ret == 1, don't bother squaring or multiplying it 452 | g[w].copyTo(r); 453 | is1 = false; 454 | } 455 | else { 456 | while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } 457 | if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } 458 | z.mulTo(r2,g[w],r); 459 | } 460 | 461 | while(j >= 0 && (e[j]&(1< 0) { 478 | x.rShiftTo(g,x); 479 | y.rShiftTo(g,y); 480 | } 481 | while(x.signum() > 0) { 482 | if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); 483 | if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); 484 | if(x.compareTo(y) >= 0) { 485 | x.subTo(y,x); 486 | x.rShiftTo(1,x); 487 | } 488 | else { 489 | y.subTo(x,y); 490 | y.rShiftTo(1,y); 491 | } 492 | } 493 | if(g > 0) y.lShiftTo(g,y); 494 | return y; 495 | } 496 | 497 | // (protected) this % n, n < 2^26 498 | function bnpModInt(n) { 499 | if(n <= 0) return 0; 500 | var d = this.DV%n, r = (this.s<0)?n-1:0; 501 | if(this.t > 0) 502 | if(d == 0) r = this[0]%n; 503 | else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n; 504 | return r; 505 | } 506 | 507 | // (public) 1/this % m (HAC 14.61) 508 | function bnModInverse(m) { 509 | var ac = m.isEven(); 510 | if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO; 511 | var u = m.clone(), v = this.clone(); 512 | var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); 513 | while(u.signum() != 0) { 514 | while(u.isEven()) { 515 | u.rShiftTo(1,u); 516 | if(ac) { 517 | if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } 518 | a.rShiftTo(1,a); 519 | } 520 | else if(!b.isEven()) b.subTo(m,b); 521 | b.rShiftTo(1,b); 522 | } 523 | while(v.isEven()) { 524 | v.rShiftTo(1,v); 525 | if(ac) { 526 | if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } 527 | c.rShiftTo(1,c); 528 | } 529 | else if(!d.isEven()) d.subTo(m,d); 530 | d.rShiftTo(1,d); 531 | } 532 | if(u.compareTo(v) >= 0) { 533 | u.subTo(v,u); 534 | if(ac) a.subTo(c,a); 535 | b.subTo(d,b); 536 | } 537 | else { 538 | v.subTo(u,v); 539 | if(ac) c.subTo(a,c); 540 | d.subTo(b,d); 541 | } 542 | } 543 | if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; 544 | if(d.compareTo(m) >= 0) return d.subtract(m); 545 | if(d.signum() < 0) d.addTo(m,d); else return d; 546 | if(d.signum() < 0) return d.add(m); else return d; 547 | } 548 | 549 | 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]; 550 | var lplim = (1<<26)/lowprimes[lowprimes.length-1]; 551 | 552 | // (public) test primality with certainty >= 1-.5^t 553 | function bnIsProbablePrime(t) { 554 | var i, x = this.abs(); 555 | if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) { 556 | for(i = 0; i < lowprimes.length; ++i) 557 | if(x[0] == lowprimes[i]) return true; 558 | return false; 559 | } 560 | if(x.isEven()) return false; 561 | i = 1; 562 | while(i < lowprimes.length) { 563 | var m = lowprimes[i], j = i+1; 564 | while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; 565 | m = x.modInt(m); 566 | while(i < j) if(m%lowprimes[i++] == 0) return false; 567 | } 568 | return x.millerRabin(t); 569 | } 570 | 571 | // (protected) true if probably prime (HAC 4.24, Miller-Rabin) 572 | function bnpMillerRabin(t) { 573 | var n1 = this.subtract(BigInteger.ONE); 574 | var k = n1.getLowestSetBit(); 575 | if(k <= 0) return false; 576 | var r = n1.shiftRight(k); 577 | t = (t+1)>>1; 578 | if(t > lowprimes.length) t = lowprimes.length; 579 | var a = nbi(); 580 | for(var i = 0; i < t; ++i) { 581 | //Pick bases at random, instead of starting at 2 582 | a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]); 583 | var y = a.modPow(r,this); 584 | if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { 585 | var j = 1; 586 | while(j++ < k && y.compareTo(n1) != 0) { 587 | y = y.modPowInt(2,this); 588 | if(y.compareTo(BigInteger.ONE) == 0) return false; 589 | } 590 | if(y.compareTo(n1) != 0) return false; 591 | } 592 | } 593 | return true; 594 | } 595 | 596 | // protected 597 | BigInteger.prototype.chunkSize = bnpChunkSize; 598 | BigInteger.prototype.toRadix = bnpToRadix; 599 | BigInteger.prototype.fromRadix = bnpFromRadix; 600 | BigInteger.prototype.fromNumber = bnpFromNumber; 601 | BigInteger.prototype.bitwiseTo = bnpBitwiseTo; 602 | BigInteger.prototype.changeBit = bnpChangeBit; 603 | BigInteger.prototype.addTo = bnpAddTo; 604 | BigInteger.prototype.dMultiply = bnpDMultiply; 605 | BigInteger.prototype.dAddOffset = bnpDAddOffset; 606 | BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; 607 | BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; 608 | BigInteger.prototype.modInt = bnpModInt; 609 | BigInteger.prototype.millerRabin = bnpMillerRabin; 610 | 611 | // public 612 | BigInteger.prototype.clone = bnClone; 613 | BigInteger.prototype.intValue = bnIntValue; 614 | BigInteger.prototype.byteValue = bnByteValue; 615 | BigInteger.prototype.shortValue = bnShortValue; 616 | BigInteger.prototype.signum = bnSigNum; 617 | BigInteger.prototype.toByteArray = bnToByteArray; 618 | BigInteger.prototype.equals = bnEquals; 619 | BigInteger.prototype.min = bnMin; 620 | BigInteger.prototype.max = bnMax; 621 | BigInteger.prototype.and = bnAnd; 622 | BigInteger.prototype.or = bnOr; 623 | BigInteger.prototype.xor = bnXor; 624 | BigInteger.prototype.andNot = bnAndNot; 625 | BigInteger.prototype.not = bnNot; 626 | BigInteger.prototype.shiftLeft = bnShiftLeft; 627 | BigInteger.prototype.shiftRight = bnShiftRight; 628 | BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; 629 | BigInteger.prototype.bitCount = bnBitCount; 630 | BigInteger.prototype.testBit = bnTestBit; 631 | BigInteger.prototype.setBit = bnSetBit; 632 | BigInteger.prototype.clearBit = bnClearBit; 633 | BigInteger.prototype.flipBit = bnFlipBit; 634 | BigInteger.prototype.add = bnAdd; 635 | BigInteger.prototype.subtract = bnSubtract; 636 | BigInteger.prototype.multiply = bnMultiply; 637 | BigInteger.prototype.divide = bnDivide; 638 | BigInteger.prototype.remainder = bnRemainder; 639 | BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder; 640 | BigInteger.prototype.modPow = bnModPow; 641 | BigInteger.prototype.modInverse = bnModInverse; 642 | BigInteger.prototype.pow = bnPow; 643 | BigInteger.prototype.gcd = bnGCD; 644 | BigInteger.prototype.isProbablePrime = bnIsProbablePrime; 645 | 646 | // JSBN-specific extension 647 | BigInteger.prototype.square = bnSquare; 648 | 649 | // BigInteger interfaces not implemented in jsbn: 650 | 651 | // BigInteger(int signum, byte[] magnitude) 652 | // double doubleValue() 653 | // float floatValue() 654 | // int hashCode() 655 | // long longValue() 656 | // static BigInteger valueOf(long val) 657 | --------------------------------------------------------------------------------