@opcat-labs/opcat 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cjs2esm.json +18 -0
- package/.mocharc.yaml +1 -1
- package/CHANGELOG.md +13 -0
- package/README.md +6 -0
- package/{lib/address.js → cjs/address.cjs} +77 -72
- package/cjs/block/block.cjs +332 -0
- package/{lib/block/blockheader.js → cjs/block/blockheader.cjs} +8 -7
- package/cjs/block/index.cjs +2 -0
- package/{lib/block/merkleblock.js → cjs/block/merkleblock.cjs} +23 -15
- package/cjs/bn.cjs +3411 -0
- package/{lib/crypto/bn.js → cjs/crypto/bn.cjs} +3 -3
- package/{lib/crypto/ecdsa.js → cjs/crypto/ecdsa.cjs} +150 -14
- package/{lib/crypto/hash.node.js → cjs/crypto/hash.cjs} +13 -2
- package/cjs/crypto/index.cjs +16 -0
- package/{lib/crypto/point.js → cjs/crypto/point.cjs} +11 -4
- package/cjs/crypto/random.cjs +18 -0
- package/{lib/crypto/signature.js → cjs/crypto/signature.cjs} +158 -8
- package/{lib/encoding/base58.js → cjs/encoding/base58.cjs} +58 -2
- package/cjs/encoding/base58check.cjs +192 -0
- package/cjs/encoding/bufferreader.cjs +333 -0
- package/cjs/encoding/bufferwriter.cjs +244 -0
- package/{lib/encoding/decode-asm.js → cjs/encoding/decode-asm.cjs} +4 -4
- package/{lib/encoding/decode-hex.js → cjs/encoding/decode-hex.cjs} +1 -1
- package/cjs/encoding/index.cjs +14 -0
- package/cjs/encoding/varint.cjs +116 -0
- package/{lib/errors/index.js → cjs/errors/index.cjs} +9 -9
- package/{lib/errors/spec.js → cjs/errors/spec.cjs} +2 -2
- package/cjs/hash-cache.cjs +98 -0
- package/{lib/hdprivatekey.js → cjs/hdprivatekey.cjs} +232 -140
- package/{lib/hdpublickey.js → cjs/hdpublickey.cjs} +120 -93
- package/cjs/index.cjs +94 -0
- package/cjs/interpreter/index.cjs +2 -0
- package/cjs/interpreter/interpreter.cjs +1988 -0
- package/{lib/script/stack.js → cjs/interpreter/stack.cjs} +9 -2
- package/{lib/message/message.js → cjs/message/message.cjs} +62 -25
- package/cjs/mnemonic/index.cjs +3 -0
- package/{lib/mnemonic/mnemonic.js → cjs/mnemonic/mnemonic.cjs} +44 -13
- package/{lib/mnemonic/pbkdf2.node.js → cjs/mnemonic/pbkdf2.cjs} +9 -2
- package/cjs/mnemonic/words/index.cjs +66 -0
- package/cjs/network.cjs +13 -0
- package/cjs/networks.cjs +321 -0
- package/{lib/opcode.js → cjs/opcode.cjs} +69 -5
- package/cjs/privatekey.cjs +422 -0
- package/{lib/publickey.js → cjs/publickey.cjs} +14 -16
- package/cjs/script/index.cjs +2 -0
- package/{lib/script/script.js → cjs/script/script.cjs} +322 -67
- package/cjs/transaction/index.cjs +5 -0
- package/cjs/transaction/input/index.cjs +34 -0
- package/cjs/transaction/input/input.cjs +396 -0
- package/{lib/transaction/input/multisig.js → cjs/transaction/input/multisig.cjs} +112 -18
- package/{lib/transaction/input/publickey.js → cjs/transaction/input/publickey.cjs} +29 -19
- package/{lib/transaction/input/publickeyhash.js → cjs/transaction/input/publickeyhash.cjs} +25 -17
- package/{lib/transaction/output.js → cjs/transaction/output.cjs} +100 -15
- package/cjs/transaction/sighash.cjs +187 -0
- package/{lib/transaction/signature.js → cjs/transaction/signature.cjs} +30 -6
- package/cjs/transaction/transaction.cjs +2000 -0
- package/{lib/transaction/unspentoutput.js → cjs/transaction/unspentoutput.cjs} +5 -5
- package/cjs/util/derivation.cjs +53 -0
- package/cjs/util/index.cjs +11 -0
- package/cjs/util/js.cjs +95 -0
- package/{lib/util/preconditions.js → cjs/util/preconditions.cjs} +2 -2
- package/esm/address.js +483 -0
- package/{lib → esm}/block/block.js +82 -27
- package/esm/block/blockheader.js +296 -0
- package/esm/block/index.js +2 -0
- package/esm/block/merkleblock.js +331 -0
- package/esm/bn.js +3411 -0
- package/esm/crypto/bn.js +278 -0
- package/esm/crypto/ecdsa.js +475 -0
- package/{lib/crypto/hash.browser.js → esm/crypto/hash.js} +18 -7
- package/esm/crypto/index.js +16 -0
- package/esm/crypto/point.js +228 -0
- package/esm/crypto/random.js +18 -0
- package/esm/crypto/signature.js +475 -0
- package/esm/encoding/base58.js +167 -0
- package/esm/encoding/base58check.js +192 -0
- package/esm/encoding/bufferreader.js +333 -0
- package/esm/encoding/bufferwriter.js +243 -0
- package/esm/encoding/decode-asm.js +24 -0
- package/esm/encoding/decode-hex.js +32 -0
- package/esm/encoding/decode-script-chunks.js +43 -0
- package/esm/encoding/encode-hex.js +284 -0
- package/esm/encoding/index.js +14 -0
- package/esm/encoding/is-hex.js +7 -0
- package/esm/encoding/varint.js +116 -0
- package/esm/errors/index.js +54 -0
- package/esm/errors/spec.js +314 -0
- package/esm/hash-cache.js +98 -0
- package/esm/hdprivatekey.js +768 -0
- package/esm/hdpublickey.js +549 -0
- package/esm/index.js +66 -0
- package/esm/interpreter/index.js +2 -0
- package/{lib/script → esm/interpreter}/interpreter.js +219 -66
- package/esm/interpreter/stack.js +116 -0
- package/esm/message/message.js +228 -0
- package/esm/mnemonic/index.js +3 -0
- package/esm/mnemonic/mnemonic.js +332 -0
- package/{lib/mnemonic/pbkdf2.browser.js → esm/mnemonic/pbkdf2.js} +13 -6
- package/esm/mnemonic/words/chinese.js +2054 -0
- package/esm/mnemonic/words/english.js +2054 -0
- package/esm/mnemonic/words/french.js +2054 -0
- package/esm/mnemonic/words/index.js +66 -0
- package/esm/mnemonic/words/italian.js +2054 -0
- package/esm/mnemonic/words/japanese.js +2054 -0
- package/esm/mnemonic/words/spanish.js +2054 -0
- package/esm/network.js +13 -0
- package/{lib → esm}/networks.js +61 -120
- package/esm/opcode.js +319 -0
- package/{lib → esm}/privatekey.js +76 -28
- package/esm/publickey.js +384 -0
- package/esm/script/index.js +2 -0
- package/esm/script/script.js +1329 -0
- package/esm/script/write-i32-le.js +17 -0
- package/esm/script/write-push-data.js +35 -0
- package/esm/script/write-u16-le.js +12 -0
- package/esm/script/write-u32-le.js +16 -0
- package/esm/script/write-u64-le.js +24 -0
- package/esm/script/write-u8-le.js +8 -0
- package/esm/script/write-varint.js +46 -0
- package/esm/transaction/index.js +5 -0
- package/esm/transaction/input/index.js +33 -0
- package/{lib → esm}/transaction/input/input.js +132 -90
- package/esm/transaction/input/multisig.js +335 -0
- package/esm/transaction/input/publickey.js +108 -0
- package/esm/transaction/input/publickeyhash.js +124 -0
- package/esm/transaction/output.js +316 -0
- package/{lib → esm}/transaction/sighash.js +42 -22
- package/esm/transaction/signature.js +120 -0
- package/{lib → esm}/transaction/transaction.js +522 -163
- package/esm/transaction/unspentoutput.js +112 -0
- package/esm/util/_.js +47 -0
- package/esm/util/derivation.js +53 -0
- package/esm/util/index.js +12 -0
- package/esm/util/js.js +95 -0
- package/esm/util/preconditions.js +33 -0
- package/fixup.cjs +17 -0
- package/package.json +40 -26
- package/test/{address.js → address.cjs} +14 -43
- package/test/block/{block.js → block.cjs} +3 -5
- package/test/block/{blockheader.js → blockheader.cjs} +2 -2
- package/test/block/{merklebloack.js → merklebloack.cjs} +2 -2
- package/test/crypto/{ecdsa.js → ecdsa.cjs} +9 -9
- package/test/crypto/{hash.browser.js → hash.browser.cjs} +2 -1
- package/test/crypto/{signature.js → signature.cjs} +2 -2
- package/test/data/bitcoind/script_tests.json +5 -5
- package/test/{hashCache.js → hashCache.cjs} +2 -1
- package/test/{hdkeys.js → hdkeys.cjs} +4 -2
- package/test/{hdprivatekey.js → hdprivatekey.cjs} +7 -6
- package/test/{hdpublickey.js → hdpublickey.cjs} +2 -7
- package/test/mnemonic/{pbkdf2.test.js → pbkdf2.test.cjs} +2 -2
- package/test/{networks.js → networks.cjs} +12 -31
- package/test/{publickey.js → publickey.cjs} +2 -2
- package/test/script/{interpreter.js → interpreter.cjs} +5 -5
- package/test/script/{script.js → script.cjs} +8 -2
- package/test/transaction/{deserialize.js → deserialize.cjs} +2 -2
- package/test/transaction/input/{input.js → input.cjs} +1 -1
- package/test/transaction/input/{multisig.js → multisig.cjs} +2 -1
- package/test/transaction/input/{publickeyhash.js → publickeyhash.cjs} +1 -1
- package/test/transaction/{sighash.js → sighash.cjs} +1 -1
- package/test/transaction/{transaction.js → transaction.cjs} +2 -2
- package/tsconfig.json +13 -0
- package/types/address.d.cts +252 -0
- package/types/block/block.d.cts +139 -0
- package/types/block/blockheader.d.cts +125 -0
- package/types/block/index.d.cts +2 -0
- package/types/block/merkleblock.d.cts +95 -0
- package/types/bn.d.cts +202 -0
- package/types/crypto/bn.d.cts +2 -0
- package/types/crypto/ecdsa.d.cts +187 -0
- package/types/crypto/hash.d.cts +118 -0
- package/types/crypto/index.d.cts +7 -0
- package/types/crypto/point.d.cts +134 -0
- package/types/crypto/random.d.cts +13 -0
- package/types/crypto/signature.d.cts +160 -0
- package/types/encoding/base58.d.cts +106 -0
- package/types/encoding/base58check.d.cts +107 -0
- package/types/encoding/bufferreader.d.cts +164 -0
- package/types/encoding/bufferwriter.d.cts +126 -0
- package/types/encoding/decode-asm.d.cts +2 -0
- package/types/encoding/decode-hex.d.cts +2 -0
- package/types/encoding/decode-script-chunks.d.cts +14 -0
- package/types/encoding/encode-hex.d.cts +2 -0
- package/types/encoding/index.d.cts +6 -0
- package/types/encoding/is-hex.d.cts +2 -0
- package/types/encoding/varint.d.cts +66 -0
- package/types/errors/index.d.cts +4 -0
- package/types/errors/spec.d.cts +22 -0
- package/types/hash-cache.d.cts +65 -0
- package/types/hdprivatekey.d.cts +281 -0
- package/types/hdpublickey.d.cts +240 -0
- package/types/index.d.cts +26 -0
- package/types/interpreter/index.d.cts +2 -0
- package/types/interpreter/interpreter.d.cts +228 -0
- package/types/interpreter/stack.d.cts +35 -0
- package/types/message/message.d.cts +110 -0
- package/types/mnemonic/index.d.cts +2 -0
- package/types/mnemonic/mnemonic.d.cts +171 -0
- package/types/mnemonic/pbkdf2.d.cts +14 -0
- package/types/mnemonic/words/chinese.d.cts +2 -0
- package/types/mnemonic/words/english.d.cts +2 -0
- package/types/mnemonic/words/french.d.cts +2 -0
- package/types/mnemonic/words/index.d.cts +22 -0
- package/types/mnemonic/words/italian.d.cts +2 -0
- package/types/mnemonic/words/japanese.d.cts +2 -0
- package/types/mnemonic/words/spanish.d.cts +2 -0
- package/types/network.d.cts +11 -0
- package/types/networks.d.cts +76 -0
- package/types/opcode.d.cts +93 -0
- package/types/privatekey.d.cts +169 -0
- package/types/publickey.d.cts +202 -0
- package/types/script/index.d.cts +2 -0
- package/types/script/script.d.cts +449 -0
- package/types/script/write-i32-le.d.cts +2 -0
- package/types/script/write-push-data.d.cts +2 -0
- package/types/script/write-u16-le.d.cts +2 -0
- package/types/script/write-u32-le.d.cts +2 -0
- package/types/script/write-u64-le.d.cts +2 -0
- package/types/script/write-u8-le.d.cts +2 -0
- package/types/script/write-varint.d.cts +2 -0
- package/types/transaction/index.d.cts +2 -0
- package/types/transaction/input/index.d.cts +2 -0
- package/types/transaction/input/input.d.cts +178 -0
- package/types/transaction/input/multisig.d.cts +127 -0
- package/types/transaction/input/publickey.d.cts +44 -0
- package/types/transaction/input/publickeyhash.d.cts +45 -0
- package/types/transaction/output.d.cts +118 -0
- package/types/transaction/sighash.d.cts +61 -0
- package/types/transaction/signature.d.cts +43 -0
- package/types/transaction/transaction.d.cts +716 -0
- package/types/transaction/unspentoutput.d.cts +83 -0
- package/types/util/_.d.cts +26 -0
- package/types/util/derivation.d.cts +21 -0
- package/types/util/index.d.cts +5 -0
- package/types/util/js.d.cts +50 -0
- package/types/util/preconditions.d.cts +3 -0
- package/index.d.ts +0 -1541
- package/index.js +0 -74
- package/lib/block/index.js +0 -4
- package/lib/bn.js +0 -3423
- package/lib/crypto/hash.js +0 -2
- package/lib/crypto/random.browser.js +0 -28
- package/lib/crypto/random.js +0 -2
- package/lib/crypto/random.node.js +0 -11
- package/lib/encoding/base58check.js +0 -121
- package/lib/encoding/bufferreader.js +0 -212
- package/lib/encoding/bufferwriter.js +0 -140
- package/lib/encoding/varint.js +0 -75
- package/lib/hash-cache.js +0 -50
- package/lib/mnemonic/pbkdf2.js +0 -2
- package/lib/mnemonic/words/index.js +0 -8
- package/lib/script/index.js +0 -5
- package/lib/transaction/index.js +0 -7
- package/lib/transaction/input/index.js +0 -5
- package/lib/util/js.js +0 -90
- /package/{lib/encoding/decode-script-chunks.js → cjs/encoding/decode-script-chunks.cjs} +0 -0
- /package/{lib/encoding/encode-hex.js → cjs/encoding/encode-hex.cjs} +0 -0
- /package/{lib/encoding/is-hex.js → cjs/encoding/is-hex.cjs} +0 -0
- /package/{lib/mnemonic/words/chinese.js → cjs/mnemonic/words/chinese.cjs} +0 -0
- /package/{lib/mnemonic/words/english.js → cjs/mnemonic/words/english.cjs} +0 -0
- /package/{lib/mnemonic/words/french.js → cjs/mnemonic/words/french.cjs} +0 -0
- /package/{lib/mnemonic/words/italian.js → cjs/mnemonic/words/italian.cjs} +0 -0
- /package/{lib/mnemonic/words/japanese.js → cjs/mnemonic/words/japanese.cjs} +0 -0
- /package/{lib/mnemonic/words/spanish.js → cjs/mnemonic/words/spanish.cjs} +0 -0
- /package/{lib/script/write-i32-le.js → cjs/script/write-i32-le.cjs} +0 -0
- /package/{lib/script/write-push-data.js → cjs/script/write-push-data.cjs} +0 -0
- /package/{lib/script/write-u16-le.js → cjs/script/write-u16-le.cjs} +0 -0
- /package/{lib/script/write-u32-le.js → cjs/script/write-u32-le.cjs} +0 -0
- /package/{lib/script/write-u64-le.js → cjs/script/write-u64-le.cjs} +0 -0
- /package/{lib/script/write-u8-le.js → cjs/script/write-u8-le.cjs} +0 -0
- /package/{lib/script/write-varint.js → cjs/script/write-varint.cjs} +0 -0
- /package/{lib/util/_.js → cjs/util/_.cjs} +0 -0
- /package/test/crypto/{bn.js → bn.cjs} +0 -0
- /package/test/crypto/{hash.js → hash.cjs} +0 -0
- /package/test/crypto/{point.js → point.cjs} +0 -0
- /package/test/crypto/{random.js → random.cjs} +0 -0
- /package/test/data/{blk86756-testnet.js → blk86756-testnet.cjs} +0 -0
- /package/test/data/{merkleblocks.js → merkleblocks.cjs} +0 -0
- /package/test/encoding/{base58.js → base58.cjs} +0 -0
- /package/test/encoding/{base58check.js → base58check.cjs} +0 -0
- /package/test/encoding/{bufferreader.js → bufferreader.cjs} +0 -0
- /package/test/encoding/{bufferwriter.js → bufferwriter.cjs} +0 -0
- /package/test/encoding/{varint.js → varint.cjs} +0 -0
- /package/test/{index.js → index.cjs} +0 -0
- /package/test/message/{message.js → message.cjs} +0 -0
- /package/test/mnemonic/{mnemonic.js → mnemonic.cjs} +0 -0
- /package/test/{opcode.js → opcode.cjs} +0 -0
- /package/test/{privatekey.js → privatekey.cjs} +0 -0
- /package/test/transaction/input/{publickey.js → publickey.cjs} +0 -0
- /package/test/transaction/{output.js → output.cjs} +0 -0
- /package/test/transaction/{signature.js → signature.cjs} +0 -0
- /package/test/transaction/{unspentoutput.js → unspentoutput.cjs} +0 -0
- /package/test/util/{js.js → js.cjs} +0 -0
- /package/test/util/{preconditions.js → preconditions.cjs} +0 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import BN from './bn.js';
|
|
4
|
+
import Point from './point.js';
|
|
5
|
+
import Signature from './signature.js';
|
|
6
|
+
import PublicKey from '../publickey.js';
|
|
7
|
+
import Random from './random.js';
|
|
8
|
+
import Hash from './hash.js';
|
|
9
|
+
import _ from '../util/_.js';
|
|
10
|
+
import $ from '../util/preconditions.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Creates an ECDSA instance.
|
|
14
|
+
* @constructor
|
|
15
|
+
* @param {Object} [obj] - Optional object containing properties to initialize the instance.
|
|
16
|
+
*/
|
|
17
|
+
function ECDSA(obj) {
|
|
18
|
+
if (!(this instanceof ECDSA)) {
|
|
19
|
+
return new ECDSA(obj);
|
|
20
|
+
}
|
|
21
|
+
if (obj) {
|
|
22
|
+
this.set(obj);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Updates the ECDSA instance properties with provided values.
|
|
28
|
+
* @param {Object} obj - Object containing properties to update
|
|
29
|
+
* @param {Buffer} [obj.hashbuf] - Hash buffer
|
|
30
|
+
* @param {string} [obj.endian] - Endianness of hashbuf
|
|
31
|
+
* @param {PrivateKey} [obj.privkey] - Private key
|
|
32
|
+
* @param {PublicKey} [obj.pubkey] - Public key (derived from privkey if not provided)
|
|
33
|
+
* @param {Signature} [obj.sig] - Signature
|
|
34
|
+
* @param {BigInteger} [obj.k] - Random number k
|
|
35
|
+
* @param {boolean} [obj.verified] - Verification status
|
|
36
|
+
* @returns {ECDSA} Returns the updated ECDSA instance
|
|
37
|
+
*/
|
|
38
|
+
ECDSA.prototype.set = function (obj) {
|
|
39
|
+
this.hashbuf = obj.hashbuf || this.hashbuf;
|
|
40
|
+
this.endian = obj.endian || this.endian; // the endianness of hashbuf
|
|
41
|
+
this.privkey = obj.privkey || this.privkey;
|
|
42
|
+
this.pubkey = obj.pubkey || (this.privkey ? this.privkey.publicKey : this.pubkey);
|
|
43
|
+
this.sig = obj.sig || this.sig;
|
|
44
|
+
this.k = obj.k || this.k;
|
|
45
|
+
this.verified = obj.verified || this.verified;
|
|
46
|
+
return this;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Converts the private key to a public key and stores it in the `pubkey` property.
|
|
51
|
+
*/
|
|
52
|
+
ECDSA.prototype.privkey2pubkey = function () {
|
|
53
|
+
this.pubkey = this.privkey.toPublicKey();
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Calculates the recovery factor (i) for ECDSA signature verification.
|
|
58
|
+
* Iterates through possible recovery factors (0-3) to find the one that
|
|
59
|
+
* reconstructs the correct public key from the signature.
|
|
60
|
+
*
|
|
61
|
+
* @returns {ECDSA} Returns the instance with updated signature properties if successful.
|
|
62
|
+
* @throws {Error} Throws if no valid recovery factor is found after all iterations.
|
|
63
|
+
*/
|
|
64
|
+
ECDSA.prototype.calci = function () {
|
|
65
|
+
for (var i = 0; i < 4; i++) {
|
|
66
|
+
this.sig.i = i;
|
|
67
|
+
var Qprime;
|
|
68
|
+
try {
|
|
69
|
+
Qprime = this.toPublicKey();
|
|
70
|
+
} catch (e) {
|
|
71
|
+
console.error(e);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (Qprime.point.eq(this.pubkey.point)) {
|
|
76
|
+
this.sig.compressed = this.pubkey.compressed;
|
|
77
|
+
return this;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.sig.i = undefined;
|
|
82
|
+
throw new Error('Unable to find valid recovery factor');
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Creates an ECDSA instance from a JSON string representation.
|
|
87
|
+
* @param {string} str - JSON string containing ECDSA parameters.
|
|
88
|
+
* @returns {ECDSA} New ECDSA instance initialized with parsed data.
|
|
89
|
+
*/
|
|
90
|
+
ECDSA.fromString = function (str) {
|
|
91
|
+
var obj = JSON.parse(str);
|
|
92
|
+
return new ECDSA(obj);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Generates a random value `k` for ECDSA signing.
|
|
97
|
+
* The value is generated within the range (0, N) where N is the curve order.
|
|
98
|
+
* The generated `k` is stored in the instance and returned for chaining.
|
|
99
|
+
*/
|
|
100
|
+
ECDSA.prototype.randomK = function () {
|
|
101
|
+
var N = Point.getN();
|
|
102
|
+
var k;
|
|
103
|
+
do {
|
|
104
|
+
k = BN.fromBuffer(Random.getRandomBuffer(32));
|
|
105
|
+
} while (!(k.lt(N) && k.gt(BN.Zero)));
|
|
106
|
+
this.k = k;
|
|
107
|
+
return this;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Generates a deterministic K value for ECDSA signing as per RFC 6979.
|
|
113
|
+
* See:
|
|
114
|
+
* https://tools.ietf.org/html/rfc6979#section-3.2
|
|
115
|
+
* Handles invalid r/s cases by incrementing badrs counter and regenerating K.
|
|
116
|
+
* @param {number} [badrs=0] - Counter for invalid r/s cases (default: 0)
|
|
117
|
+
* @returns {ECDSA} Returns the ECDSA instance for chaining
|
|
118
|
+
*/
|
|
119
|
+
ECDSA.prototype.deterministicK = function (badrs) {
|
|
120
|
+
// if r or s were invalid when this function was used in signing,
|
|
121
|
+
// we do not want to actually compute r, s here for efficiency, so,
|
|
122
|
+
// we can increment badrs. explained at end of RFC 6979 section 3.2
|
|
123
|
+
if (_.isUndefined(badrs)) {
|
|
124
|
+
badrs = 0;
|
|
125
|
+
}
|
|
126
|
+
var v = Buffer.alloc(32);
|
|
127
|
+
v.fill(0x01);
|
|
128
|
+
var k = Buffer.alloc(32);
|
|
129
|
+
k.fill(0x00);
|
|
130
|
+
var x = this.privkey.bn.toBuffer({
|
|
131
|
+
size: 32,
|
|
132
|
+
});
|
|
133
|
+
var hashbuf = this.endian === 'little' ? Buffer.from(this.hashbuf).reverse() : this.hashbuf;
|
|
134
|
+
k = Hash.sha256hmac(Buffer.concat([v, Buffer.from([0x00]), x, hashbuf]), k);
|
|
135
|
+
v = Hash.sha256hmac(v, k);
|
|
136
|
+
k = Hash.sha256hmac(Buffer.concat([v, Buffer.from([0x01]), x, hashbuf]), k);
|
|
137
|
+
v = Hash.sha256hmac(v, k);
|
|
138
|
+
v = Hash.sha256hmac(v, k);
|
|
139
|
+
var T = BN.fromBuffer(v);
|
|
140
|
+
var N = Point.getN();
|
|
141
|
+
|
|
142
|
+
// also explained in 3.2, we must ensure T is in the proper range (0, N)
|
|
143
|
+
for (var i = 0; i < badrs || !(T.lt(N) && T.gt(BN.Zero)); i++) {
|
|
144
|
+
k = Hash.sha256hmac(Buffer.concat([v, Buffer.from([0x00])]), k);
|
|
145
|
+
v = Hash.sha256hmac(v, k);
|
|
146
|
+
v = Hash.sha256hmac(v, k);
|
|
147
|
+
T = BN.fromBuffer(v);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
this.k = T;
|
|
151
|
+
return this;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Converts an ECDSA signature to its corresponding public key.
|
|
156
|
+
*
|
|
157
|
+
* The method follows the ECDSA public key recovery process:
|
|
158
|
+
* 1. Validates the recovery parameter `i` (must be 0-3)
|
|
159
|
+
* 2. Derives the public key point Q using the formula: Q = r⁻¹(sR - eG)
|
|
160
|
+
* 3. Validates the derived curve point
|
|
161
|
+
*
|
|
162
|
+
* see:
|
|
163
|
+
* https://bitcointalk.org/index.php?topic=6430.0
|
|
164
|
+
* http://stackoverflow.com/questions/19665491/how-do-i-get-an-ecdsa-public-key-from-just-a-bitcoin-signature-sec1-4-1-6-k
|
|
165
|
+
* @returns {PublicKey} The recovered public key
|
|
166
|
+
* @throws {Error} If recovery parameter is invalid or derived point is invalid
|
|
167
|
+
*/
|
|
168
|
+
ECDSA.prototype.toPublicKey = function () {
|
|
169
|
+
var i = this.sig.i;
|
|
170
|
+
$.checkArgument(
|
|
171
|
+
i === 0 || i === 1 || i === 2 || i === 3,
|
|
172
|
+
new Error('i must be equal to 0, 1, 2, or 3'),
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
var e = BN.fromBuffer(this.hashbuf);
|
|
176
|
+
var r = this.sig.r;
|
|
177
|
+
var s = this.sig.s;
|
|
178
|
+
|
|
179
|
+
// A set LSB signifies that the y-coordinate is odd
|
|
180
|
+
var isYOdd = i & 1;
|
|
181
|
+
|
|
182
|
+
// The more significant bit specifies whether we should use the
|
|
183
|
+
// first or second candidate key.
|
|
184
|
+
var isSecondKey = i >> 1;
|
|
185
|
+
|
|
186
|
+
var n = Point.getN();
|
|
187
|
+
var G = Point.getG();
|
|
188
|
+
|
|
189
|
+
// 1.1 Let x = r + jn
|
|
190
|
+
var x = isSecondKey ? r.add(n) : r;
|
|
191
|
+
var R = Point.fromX(isYOdd, x);
|
|
192
|
+
|
|
193
|
+
// 1.4 Check that nR is at infinity
|
|
194
|
+
var nR = R.mul(n);
|
|
195
|
+
|
|
196
|
+
if (!nR.isInfinity()) {
|
|
197
|
+
throw new Error('nR is not a valid curve point');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Compute -e from e
|
|
201
|
+
var eNeg = e.neg().umod(n);
|
|
202
|
+
|
|
203
|
+
// 1.6.1 Compute Q = r^-1 (sR - eG)
|
|
204
|
+
// Q = r^-1 (sR + -eG)
|
|
205
|
+
var rInv = r.invm(n);
|
|
206
|
+
|
|
207
|
+
// var Q = R.multiplyTwo(s, G, eNeg).mul(rInv);
|
|
208
|
+
var Q = R.mul(s).add(G.mul(eNeg)).mul(rInv);
|
|
209
|
+
|
|
210
|
+
var pubkey = PublicKey.fromPoint(Q, this.sig.compressed);
|
|
211
|
+
|
|
212
|
+
return pubkey;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Validates an ECDSA signature and returns an error message if invalid.
|
|
217
|
+
* Checks:
|
|
218
|
+
* - hashbuf is a 32-byte buffer
|
|
219
|
+
* - r and s values are within valid range
|
|
220
|
+
* - Signature verification against public key
|
|
221
|
+
* @returns {string|boolean} Error message if invalid, false if valid
|
|
222
|
+
*/
|
|
223
|
+
ECDSA.prototype.sigError = function () {
|
|
224
|
+
if (!Buffer.isBuffer(this.hashbuf) || this.hashbuf.length !== 32) {
|
|
225
|
+
return 'hashbuf must be a 32 byte buffer';
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
var r = this.sig.r;
|
|
229
|
+
var s = this.sig.s;
|
|
230
|
+
if (!(r.gt(BN.Zero) && r.lt(Point.getN())) || !(s.gt(BN.Zero) && s.lt(Point.getN()))) {
|
|
231
|
+
return 'r and s not in range';
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
var e = BN.fromBuffer(
|
|
235
|
+
this.hashbuf,
|
|
236
|
+
this.endian
|
|
237
|
+
? {
|
|
238
|
+
endian: this.endian,
|
|
239
|
+
}
|
|
240
|
+
: undefined,
|
|
241
|
+
);
|
|
242
|
+
var n = Point.getN();
|
|
243
|
+
var sinv = s.invm(n);
|
|
244
|
+
var u1 = sinv.mul(e).umod(n);
|
|
245
|
+
var u2 = sinv.mul(r).umod(n);
|
|
246
|
+
|
|
247
|
+
var p = Point.getG().mulAdd(u1, this.pubkey.point, u2);
|
|
248
|
+
if (p.isInfinity()) {
|
|
249
|
+
return 'p is infinity';
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (p.getX().umod(n).cmp(r) !== 0) {
|
|
253
|
+
return 'Invalid signature';
|
|
254
|
+
} else {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Converts the signature `s` value to its low-S form to comply with BIP 62.
|
|
261
|
+
* This prevents signature malleability by ensuring `s` is not greater than half the curve order.
|
|
262
|
+
* @param {BN} s - The signature `s` value as a big number.
|
|
263
|
+
* @returns {BN} The low-S normalized value.
|
|
264
|
+
* @static
|
|
265
|
+
*/
|
|
266
|
+
ECDSA.toLowS = function (s) {
|
|
267
|
+
// enforce low s
|
|
268
|
+
// see BIP 62, "low S values in signatures"
|
|
269
|
+
if (
|
|
270
|
+
s.gt(
|
|
271
|
+
BN.fromBuffer(
|
|
272
|
+
Buffer.from('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex'),
|
|
273
|
+
),
|
|
274
|
+
)
|
|
275
|
+
) {
|
|
276
|
+
s = Point.getN().sub(s);
|
|
277
|
+
}
|
|
278
|
+
return s;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Finds a valid ECDSA signature (r, s) for the given private key `d` and message hash `e`.
|
|
283
|
+
* Uses deterministic k-value generation if initial attempts fail.
|
|
284
|
+
*
|
|
285
|
+
* @param {BN} d - Private key as a big number.
|
|
286
|
+
* @param {BN} e - Message hash as a big number.
|
|
287
|
+
* @returns {Object} Signature object with properties `r` and `s` (big numbers).
|
|
288
|
+
* @throws Will throw if unable to find valid signature after multiple attempts.
|
|
289
|
+
*/
|
|
290
|
+
ECDSA.prototype._findSignature = function (d, e) {
|
|
291
|
+
var N = Point.getN();
|
|
292
|
+
var G = Point.getG();
|
|
293
|
+
// try different values of k until r, s are valid
|
|
294
|
+
var badrs = 0;
|
|
295
|
+
var k, Q, r, s;
|
|
296
|
+
do {
|
|
297
|
+
if (!this.k || badrs > 0) {
|
|
298
|
+
this.deterministicK(badrs);
|
|
299
|
+
}
|
|
300
|
+
badrs++;
|
|
301
|
+
k = this.k;
|
|
302
|
+
Q = G.mul(k);
|
|
303
|
+
r = new BN(1).mul(Q.x.umod(N));
|
|
304
|
+
s = k
|
|
305
|
+
.invm(N)
|
|
306
|
+
.mul(e.add(d.mul(r)))
|
|
307
|
+
.umod(N);
|
|
308
|
+
} while (r.cmp(BN.Zero) <= 0 || s.cmp(BN.Zero) <= 0);
|
|
309
|
+
|
|
310
|
+
s = ECDSA.toLowS(s);
|
|
311
|
+
return {
|
|
312
|
+
s: s,
|
|
313
|
+
r: r,
|
|
314
|
+
};
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Signs a message using ECDSA.
|
|
319
|
+
*
|
|
320
|
+
* @param {Buffer} hashbuf - 32-byte buffer containing the hash of the message to sign.
|
|
321
|
+
* @param {PrivateKey} privkey - Private key used for signing.
|
|
322
|
+
* @returns {ECDSA} Returns the instance for chaining.
|
|
323
|
+
* @throws {Error} Throws if parameters are invalid or hashbuf is not a 32-byte buffer.
|
|
324
|
+
*/
|
|
325
|
+
ECDSA.prototype.sign = function () {
|
|
326
|
+
var hashbuf = this.hashbuf;
|
|
327
|
+
var privkey = this.privkey;
|
|
328
|
+
var d = privkey.bn;
|
|
329
|
+
|
|
330
|
+
$.checkState(hashbuf && privkey && d, new Error('invalid parameters'));
|
|
331
|
+
$.checkState(
|
|
332
|
+
Buffer.isBuffer(hashbuf) && hashbuf.length === 32,
|
|
333
|
+
new Error('hashbuf must be a 32 byte buffer'),
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
var e = BN.fromBuffer(
|
|
337
|
+
hashbuf,
|
|
338
|
+
this.endian
|
|
339
|
+
? {
|
|
340
|
+
endian: this.endian,
|
|
341
|
+
}
|
|
342
|
+
: undefined,
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
var obj = this._findSignature(d, e);
|
|
346
|
+
obj.compressed = this.pubkey.compressed;
|
|
347
|
+
|
|
348
|
+
this.sig = new Signature(obj);
|
|
349
|
+
return this;
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Signs the message using a randomly generated k value.
|
|
354
|
+
*
|
|
355
|
+
* @returns The signature object containing r and s values.
|
|
356
|
+
*/
|
|
357
|
+
ECDSA.prototype.signRandomK = function () {
|
|
358
|
+
this.randomK();
|
|
359
|
+
return this.sign();
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Converts the ECDSA instance to a JSON string representation.
|
|
364
|
+
* Includes hash buffer, private key, public key, signature, and k value if present.
|
|
365
|
+
* Each property is converted to a string format (hex for hashbuf, toString() for others).
|
|
366
|
+
* @returns {string} JSON string containing the ECDSA instance properties
|
|
367
|
+
*/
|
|
368
|
+
ECDSA.prototype.toString = function () {
|
|
369
|
+
var obj = {};
|
|
370
|
+
if (this.hashbuf) {
|
|
371
|
+
obj.hashbuf = this.hashbuf.toString('hex');
|
|
372
|
+
}
|
|
373
|
+
if (this.privkey) {
|
|
374
|
+
obj.privkey = this.privkey.toString();
|
|
375
|
+
}
|
|
376
|
+
if (this.pubkey) {
|
|
377
|
+
obj.pubkey = this.pubkey.toString();
|
|
378
|
+
}
|
|
379
|
+
if (this.sig) {
|
|
380
|
+
obj.sig = this.sig.toString();
|
|
381
|
+
}
|
|
382
|
+
if (this.k) {
|
|
383
|
+
obj.k = this.k.toString();
|
|
384
|
+
}
|
|
385
|
+
return JSON.stringify(obj);
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Verifies the ECDSA signature and updates the `verified` property.
|
|
390
|
+
* @returns {ECDSA} The current instance for chaining.
|
|
391
|
+
*/
|
|
392
|
+
ECDSA.prototype.verify = function () {
|
|
393
|
+
if (!this.sigError()) {
|
|
394
|
+
this.verified = true;
|
|
395
|
+
} else {
|
|
396
|
+
this.verified = false;
|
|
397
|
+
}
|
|
398
|
+
return this;
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Signs a message hash using ECDSA with the given private key.
|
|
403
|
+
* @param {Buffer} hashbuf - The hash of the message to sign
|
|
404
|
+
* @param {PrivateKey} privkey - The private key to sign with
|
|
405
|
+
* @param {string} [endian] - Endianness of the input/output (optional)
|
|
406
|
+
* @returns {Signature} The ECDSA signature
|
|
407
|
+
*/
|
|
408
|
+
ECDSA.sign = function (hashbuf, privkey, endian) {
|
|
409
|
+
return ECDSA()
|
|
410
|
+
.set({
|
|
411
|
+
hashbuf: hashbuf,
|
|
412
|
+
endian: endian,
|
|
413
|
+
privkey: privkey,
|
|
414
|
+
})
|
|
415
|
+
.sign().sig;
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Signs a hash buffer with a private key and calculates the 'i' value.
|
|
420
|
+
* @param {Buffer} hashbuf - The hash buffer to sign.
|
|
421
|
+
* @param {Buffer} privkey - The private key used for signing.
|
|
422
|
+
* @param {string} [endian] - The endianness of the input data (optional).
|
|
423
|
+
* @returns {Buffer} The resulting signature.
|
|
424
|
+
* @static
|
|
425
|
+
*/
|
|
426
|
+
ECDSA.signWithCalcI = function (hashbuf, privkey, endian) {
|
|
427
|
+
return ECDSA()
|
|
428
|
+
.set({
|
|
429
|
+
hashbuf: hashbuf,
|
|
430
|
+
endian: endian,
|
|
431
|
+
privkey: privkey,
|
|
432
|
+
})
|
|
433
|
+
.sign()
|
|
434
|
+
.calci().sig;
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Signs a message hash using ECDSA with a randomly generated K value.
|
|
439
|
+
* @param {Buffer} hashbuf - The message hash to sign.
|
|
440
|
+
* @param {Buffer} privkey - The private key used for signing.
|
|
441
|
+
* @param {string} [endian] - The endianness of the input/output (default: 'big').
|
|
442
|
+
* @returns {Buffer} The generated ECDSA signature.
|
|
443
|
+
* @static
|
|
444
|
+
*/
|
|
445
|
+
ECDSA.signRandomK = function (hashbuf, privkey, endian) {
|
|
446
|
+
return ECDSA()
|
|
447
|
+
.set({
|
|
448
|
+
hashbuf: hashbuf,
|
|
449
|
+
endian: endian,
|
|
450
|
+
privkey: privkey,
|
|
451
|
+
})
|
|
452
|
+
.signRandomK().sig;
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Verifies an ECDSA signature against a hash and public key.
|
|
457
|
+
* @param {Buffer} hashbuf - The hash buffer to verify against.
|
|
458
|
+
* @param {Signature} sig - The signature to verify.
|
|
459
|
+
* @param {PublicKey} pubkey - The public key to verify with.
|
|
460
|
+
* @param {string} [endian] - The endianness of the input data (optional).
|
|
461
|
+
* @returns {boolean} True if the signature is valid, false otherwise.
|
|
462
|
+
* @static
|
|
463
|
+
*/
|
|
464
|
+
ECDSA.verify = function (hashbuf, sig, pubkey, endian) {
|
|
465
|
+
return ECDSA()
|
|
466
|
+
.set({
|
|
467
|
+
hashbuf: hashbuf,
|
|
468
|
+
endian: endian,
|
|
469
|
+
sig: sig,
|
|
470
|
+
pubkey: pubkey,
|
|
471
|
+
})
|
|
472
|
+
.verify().verified;
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
export default ECDSA;
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import crypto from 'crypto';
|
|
4
|
+
import $ from '../util/preconditions.js';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Represents a hash utility class.
|
|
8
|
+
* @constructor
|
|
9
|
+
*/
|
|
10
|
+
function Hash() {
|
|
11
|
+
if (!(this instanceof Hash)) {
|
|
12
|
+
return new Hash();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
7
15
|
|
|
8
16
|
/**
|
|
9
17
|
* A SHA or SHA1 hash, which is always 160 bits or 20 bytes long.
|
|
@@ -16,7 +24,7 @@ var Hash = module.exports;
|
|
|
16
24
|
*/
|
|
17
25
|
Hash.sha1 = function (buf) {
|
|
18
26
|
$.checkArgument(Buffer.isBuffer(buf));
|
|
19
|
-
return
|
|
27
|
+
return crypto.createHash('sha1').update(buf).digest();
|
|
20
28
|
};
|
|
21
29
|
|
|
22
30
|
Hash.sha1.blocksize = 512;
|
|
@@ -32,7 +40,7 @@ Hash.sha1.blocksize = 512;
|
|
|
32
40
|
*/
|
|
33
41
|
Hash.sha256 = function (buf) {
|
|
34
42
|
$.checkArgument(Buffer.isBuffer(buf));
|
|
35
|
-
return
|
|
43
|
+
return crypto.createHash('sha256').update(buf).digest();
|
|
36
44
|
};
|
|
37
45
|
|
|
38
46
|
Hash.sha256.blocksize = 512;
|
|
@@ -64,7 +72,7 @@ Hash.sha256sha256 = function (buf) {
|
|
|
64
72
|
*/
|
|
65
73
|
Hash.ripemd160 = function (buf) {
|
|
66
74
|
$.checkArgument(Buffer.isBuffer(buf));
|
|
67
|
-
return
|
|
75
|
+
return crypto.createHash('ripemd160').update(buf).digest();
|
|
68
76
|
};
|
|
69
77
|
/**
|
|
70
78
|
* A RIPEMD160 hash of a SHA256 hash, which is always 160 bits or 20 bytes long.
|
|
@@ -93,7 +101,7 @@ Hash.sha256ripemd160 = function (buf) {
|
|
|
93
101
|
*/
|
|
94
102
|
Hash.sha512 = function (buf) {
|
|
95
103
|
$.checkArgument(Buffer.isBuffer(buf));
|
|
96
|
-
return
|
|
104
|
+
return crypto.createHash('sha512').update(buf).digest();
|
|
97
105
|
};
|
|
98
106
|
|
|
99
107
|
Hash.sha512.blocksize = 1024;
|
|
@@ -169,3 +177,6 @@ Hash.sha256hmac = function (data, key) {
|
|
|
169
177
|
Hash.sha512hmac = function (data, key) {
|
|
170
178
|
return Hash.hmac(Hash.sha512, data, key);
|
|
171
179
|
};
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
export default Hash;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import BN from './bn.js';
|
|
2
|
+
import ECDSA from './ecdsa.js';
|
|
3
|
+
import Hash from './hash.js';
|
|
4
|
+
import Random from './random.js';
|
|
5
|
+
import Point from './point.js';
|
|
6
|
+
import Signature from './signature.js';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
BN: BN,
|
|
10
|
+
ECDSA: ECDSA,
|
|
11
|
+
Hash: Hash,
|
|
12
|
+
Random: Random,
|
|
13
|
+
Point: Point,
|
|
14
|
+
Signature: Signature
|
|
15
|
+
};
|
|
16
|
+
|