@steemit/steem-js 0.7.10 → 0.8.0
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/README.md +22 -3
- package/circle.yml +1 -1
- package/config.json +1 -1
- package/dist/steem-tests.min.js +4097 -23
- package/dist/steem.min.js +2089 -18
- package/docker-webpack.config.js +44 -0
- package/lib/api/index.js +305 -412
- package/lib/api/methods.js +16 -1
- package/lib/api/rpc-auth.js +135 -0
- package/lib/api/transports/base.js +25 -66
- package/lib/api/transports/http.js +114 -129
- package/lib/api/transports/index.js +8 -15
- package/lib/api/transports/ws.js +107 -207
- package/lib/auth/ecc/index.js +9 -9
- package/lib/auth/ecc/src/address.js +48 -78
- package/lib/auth/ecc/src/aes.js +93 -129
- package/lib/auth/ecc/src/brain_key.js +7 -7
- package/lib/auth/ecc/src/ecdsa.js +7 -33
- package/lib/auth/ecc/src/ecsignature.js +4 -30
- package/lib/auth/ecc/src/enforce_types.js +1 -8
- package/lib/auth/ecc/src/hash.js +16 -25
- package/lib/auth/ecc/src/key_private.js +146 -199
- package/lib/auth/ecc/src/key_public.js +130 -202
- package/lib/auth/ecc/src/key_utils.js +64 -106
- package/lib/auth/ecc/src/signature.js +125 -177
- package/lib/auth/index.js +84 -97
- package/lib/auth/memo.js +90 -118
- package/lib/auth/serializer/index.js +12 -18
- package/lib/auth/serializer/src/ChainTypes.js +0 -3
- package/lib/auth/serializer/src/convert.js +29 -32
- package/lib/auth/serializer/src/error_with_cause.js +22 -37
- package/lib/auth/serializer/src/fast_parser.js +54 -74
- package/lib/auth/serializer/src/number_utils.js +30 -54
- package/lib/auth/serializer/src/object_id.js +37 -62
- package/lib/auth/serializer/src/operations.js +597 -689
- package/lib/auth/serializer/src/precision.js +55 -73
- package/lib/auth/serializer/src/serializer.js +158 -204
- package/lib/auth/serializer/src/template.js +13 -8
- package/lib/auth/serializer/src/types.js +949 -1110
- package/lib/auth/serializer/src/validation.js +268 -328
- package/lib/broadcast/helpers.js +61 -98
- package/lib/broadcast/index.js +61 -82
- package/lib/browser.js +15 -19
- package/lib/config.js +16 -38
- package/lib/formatter.js +89 -115
- package/lib/index.js +19 -17
- package/lib/utils.js +4 -9
- package/node-18.dockerfile +28 -0
- package/package.json +62 -38
- package/test/Crypto.js +16 -16
- package/test/KeyFormats.js +1 -1
- package/test/api.test.js +37 -0
- package/test/broadcast.test.js +14 -8
- package/test/comment.test.js +17 -3
- package/test/operations_test.js +1 -1
- package/test/promise-broadcast.test.js +86 -0
- package/test/reputation.test.js +68 -0
- package/test/smt.test.js +11 -11
- package/test-github-workflow.bat +19 -0
- package/test-github-workflow.sh +15 -0
- package/webpack/makeConfig.js +25 -17
- package/.circleci/config.yml +0 -23
- package/dist/statistics.html +0 -208
- package/dist/steem-tests.min.js.gz +0 -0
- package/dist/steem-tests.min.js.map +0 -1
- package/dist/steem.min.js.gz +0 -0
- package/dist/steem.min.js.map +0 -1
- package/lib/auth/ecc/README.md +0 -20
- package/lib/auth/ecc/package.json +0 -36
- package/lib/auth/serializer/README.md +0 -13
- package/lib/auth/serializer/package.json +0 -32
- package/node-4.dockerfile +0 -6
- package/node-6.dockerfile +0 -6
- package/yarn.lock +0 -3336
package/lib/auth/ecc/src/aes.js
CHANGED
|
@@ -1,48 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
var _secureRandom2 = _interopRequireDefault(_secureRandom);
|
|
12
|
-
|
|
13
|
-
var _bytebuffer = require('bytebuffer');
|
|
14
|
-
|
|
15
|
-
var _bytebuffer2 = _interopRequireDefault(_bytebuffer);
|
|
16
|
-
|
|
17
|
-
var _browserifyAes = require('browserify-aes');
|
|
18
|
-
|
|
19
|
-
var _browserifyAes2 = _interopRequireDefault(_browserifyAes);
|
|
20
|
-
|
|
21
|
-
var _assert = require('assert');
|
|
22
|
-
|
|
23
|
-
var _assert2 = _interopRequireDefault(_assert);
|
|
24
|
-
|
|
25
|
-
var _key_public = require('./key_public');
|
|
26
|
-
|
|
27
|
-
var _key_public2 = _interopRequireDefault(_key_public);
|
|
28
|
-
|
|
29
|
-
var _key_private = require('./key_private');
|
|
30
|
-
|
|
31
|
-
var _key_private2 = _interopRequireDefault(_key_private);
|
|
32
|
-
|
|
33
|
-
var _hash = require('./hash');
|
|
34
|
-
|
|
35
|
-
var _hash2 = _interopRequireDefault(_hash);
|
|
36
|
-
|
|
37
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
38
|
-
|
|
39
|
-
var Long = _bytebuffer2.default.Long;
|
|
3
|
+
const secureRandom = require('secure-random');
|
|
4
|
+
const ByteBuffer = require('bytebuffer');
|
|
5
|
+
const crypto = require('browserify-aes');
|
|
6
|
+
const assert = require('assert');
|
|
7
|
+
const PublicKey = require('./key_public');
|
|
8
|
+
const PrivateKey = require('./key_private');
|
|
9
|
+
const hash = require('./hash');
|
|
10
|
+
const Long = ByteBuffer.Long;
|
|
40
11
|
|
|
41
12
|
/**
|
|
42
13
|
Spec: http://localhost:3002/steem/@dantheman/how-to-encrypt-a-memo-when-transferring-steem
|
|
43
14
|
@throws {Error|TypeError} - "Invalid Key, ..."
|
|
44
15
|
@arg {PrivateKey} private_key - required and used for decryption
|
|
45
|
-
@arg {PublicKey} public_key - required and used to
|
|
16
|
+
@arg {PublicKey} public_key - required and used to calculate the shared secret
|
|
46
17
|
@arg {string} [nonce = uniqueNonce()] - assigned a random unique uint64
|
|
47
18
|
|
|
48
19
|
@return {object}
|
|
@@ -50,16 +21,14 @@ var Long = _bytebuffer2.default.Long;
|
|
|
50
21
|
@property {Buffer} message - Plain text message
|
|
51
22
|
@property {number} checksum - shared secret checksum
|
|
52
23
|
*/
|
|
53
|
-
function encrypt(private_key, public_key, message) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return crypt(private_key, public_key, nonce, message);
|
|
24
|
+
function encrypt(private_key, public_key, message, nonce = uniqueNonce()) {
|
|
25
|
+
return crypt(private_key, public_key, nonce, message);
|
|
57
26
|
}
|
|
58
27
|
|
|
59
28
|
/**
|
|
60
29
|
Spec: http://localhost:3002/steem/@dantheman/how-to-encrypt-a-memo-when-transferring-steem
|
|
61
30
|
@arg {PrivateKey} private_key - required and used for decryption
|
|
62
|
-
@arg {PublicKey} public_key - required and used to
|
|
31
|
+
@arg {PublicKey} public_key - required and used to calculate the shared secret
|
|
63
32
|
@arg {string} nonce - random or unique uint64, provides entropy when re-using the same private/public keys.
|
|
64
33
|
@arg {Buffer} message - Encrypted or plain text message
|
|
65
34
|
@arg {number} checksum - shared secret checksum
|
|
@@ -67,7 +36,7 @@ function encrypt(private_key, public_key, message) {
|
|
|
67
36
|
@return {Buffer} - message
|
|
68
37
|
*/
|
|
69
38
|
function decrypt(private_key, public_key, nonce, message, checksum) {
|
|
70
|
-
|
|
39
|
+
return crypt(private_key, public_key, nonce, message, checksum).message;
|
|
71
40
|
}
|
|
72
41
|
|
|
73
42
|
/**
|
|
@@ -75,55 +44,54 @@ function decrypt(private_key, public_key, nonce, message, checksum) {
|
|
|
75
44
|
@arg {number} checksum - shared secret checksum (null to encrypt, non-null to decrypt)
|
|
76
45
|
*/
|
|
77
46
|
function crypt(private_key, public_key, nonce, message, checksum) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
check
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return { nonce: nonce, message: message, checksum: check };
|
|
47
|
+
private_key = toPrivateObj(private_key);
|
|
48
|
+
if (!private_key) throw new TypeError('private_key is required');
|
|
49
|
+
public_key = toPublicObj(public_key);
|
|
50
|
+
if (!public_key) throw new TypeError('public_key is required');
|
|
51
|
+
nonce = toLongObj(nonce);
|
|
52
|
+
if (!nonce) throw new TypeError('nonce is required');
|
|
53
|
+
if (!Buffer.isBuffer(message)) {
|
|
54
|
+
if (typeof message !== 'string') throw new TypeError('message should be buffer or string');
|
|
55
|
+
message = new Buffer.from(message, 'binary');
|
|
56
|
+
}
|
|
57
|
+
if (checksum && typeof checksum !== 'number') throw new TypeError('checksum should be a number');
|
|
58
|
+
const S = private_key.get_shared_secret(public_key);
|
|
59
|
+
let ebuf = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
|
|
60
|
+
ebuf.writeUint64(nonce);
|
|
61
|
+
ebuf.append(S.toString('binary'), 'binary');
|
|
62
|
+
ebuf = new Buffer.from(ebuf.copy(0, ebuf.offset).toBinary(), 'binary');
|
|
63
|
+
const encryption_key = hash.sha512(ebuf);
|
|
64
|
+
|
|
65
|
+
// D E B U G
|
|
66
|
+
// console.log('crypt', {
|
|
67
|
+
// priv_to_pub: private_key.toPublicKey().toString(),
|
|
68
|
+
// pub: public_key.toString(),
|
|
69
|
+
// nonce: nonce.toString(),
|
|
70
|
+
// message: message.length,
|
|
71
|
+
// checksum,
|
|
72
|
+
// S: S.toString('hex'),
|
|
73
|
+
// encryption_key: encryption_key.toString('hex'),
|
|
74
|
+
// })
|
|
75
|
+
|
|
76
|
+
const iv = encryption_key.slice(32, 48);
|
|
77
|
+
const key = encryption_key.slice(0, 32);
|
|
78
|
+
|
|
79
|
+
// check is first 64 bit of sha256 hash treated as uint64_t truncated to 32 bits.
|
|
80
|
+
let check = hash.sha256(encryption_key);
|
|
81
|
+
check = check.slice(0, 4);
|
|
82
|
+
const cbuf = ByteBuffer.fromBinary(check.toString('binary'), ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
|
|
83
|
+
check = cbuf.readUint32();
|
|
84
|
+
if (checksum) {
|
|
85
|
+
if (check !== checksum) throw new Error('Invalid key');
|
|
86
|
+
message = cryptoJsDecrypt(message, key, iv);
|
|
87
|
+
} else {
|
|
88
|
+
message = cryptoJsEncrypt(message, key, iv);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
nonce,
|
|
92
|
+
message,
|
|
93
|
+
checksum: check
|
|
94
|
+
};
|
|
127
95
|
}
|
|
128
96
|
|
|
129
97
|
/** This method does not use a checksum, the returned data must be validated some other way.
|
|
@@ -131,12 +99,12 @@ function crypt(private_key, public_key, nonce, message, checksum) {
|
|
|
131
99
|
@return {Buffer}
|
|
132
100
|
*/
|
|
133
101
|
function cryptoJsDecrypt(message, key, iv) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
102
|
+
assert(message, "Missing cipher text");
|
|
103
|
+
message = toBinaryBuffer(message);
|
|
104
|
+
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
|
|
105
|
+
// decipher.setAutoPadding(true)
|
|
106
|
+
message = Buffer.concat([decipher.update(message), decipher.final()]);
|
|
107
|
+
return message;
|
|
140
108
|
}
|
|
141
109
|
|
|
142
110
|
/** This method does not use a checksum, the returned data must be validated some other way.
|
|
@@ -144,41 +112,37 @@ function cryptoJsDecrypt(message, key, iv) {
|
|
|
144
112
|
@return {Buffer} binary
|
|
145
113
|
*/
|
|
146
114
|
function cryptoJsEncrypt(message, key, iv) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
115
|
+
assert(message, "Missing plain text");
|
|
116
|
+
message = toBinaryBuffer(message);
|
|
117
|
+
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
|
118
|
+
// cipher.setAutoPadding(true)
|
|
119
|
+
message = Buffer.concat([cipher.update(message), cipher.final()]);
|
|
120
|
+
return message;
|
|
153
121
|
}
|
|
154
122
|
|
|
155
123
|
/** @return {string} unique 64 bit unsigned number string. Being time based, this is careful to never choose the same nonce twice. This value could be recorded in the blockchain for a long time.
|
|
156
124
|
*/
|
|
157
125
|
function uniqueNonce() {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
126
|
+
if (unique_nonce_entropy === null) {
|
|
127
|
+
const b = secureRandom.randomUint8Array(2);
|
|
128
|
+
unique_nonce_entropy = parseInt(b[0] << 8 | b[1], 10);
|
|
129
|
+
}
|
|
130
|
+
let long = Long.fromNumber(Date.now());
|
|
131
|
+
const entropy = ++unique_nonce_entropy % 0xFFFF;
|
|
132
|
+
// console.log('uniqueNonce date\t', ByteBuffer.allocate(8).writeUint64(long).toHex(0))
|
|
133
|
+
// console.log('uniqueNonce entropy\t', ByteBuffer.allocate(8).writeUint64(Long.fromNumber(entropy)).toHex(0))
|
|
134
|
+
long = long.shiftLeft(16).or(Long.fromNumber(entropy));
|
|
135
|
+
// console.log('uniqueNonce final\t', ByteBuffer.allocate(8).writeUint64(long).toHex(0))
|
|
136
|
+
return long.toString();
|
|
169
137
|
}
|
|
170
|
-
|
|
138
|
+
let unique_nonce_entropy = null;
|
|
171
139
|
// for(let i=1; i < 10; i++) key.uniqueNonce()
|
|
172
140
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return o ? Long.isLong(o) ? o : Long.fromString(o) : o;
|
|
181
|
-
};
|
|
182
|
-
var toBinaryBuffer = function toBinaryBuffer(o) {
|
|
183
|
-
return o ? Buffer.isBuffer(o) ? o : new Buffer(o, 'binary') : o;
|
|
141
|
+
const toPrivateObj = o => o ? o.d ? o : PrivateKey.fromWif(o) : o /*null or undefined*/;
|
|
142
|
+
const toPublicObj = o => o ? o.Q ? o : PublicKey.fromString(o) : o /*null or undefined*/;
|
|
143
|
+
const toLongObj = o => o ? Long.isLong(o) ? o : Long.fromString(o) : o;
|
|
144
|
+
const toBinaryBuffer = o => o ? Buffer.isBuffer(o) ? o : new Buffer.from(o, 'binary') : o;
|
|
145
|
+
module.exports = {
|
|
146
|
+
encrypt,
|
|
147
|
+
decrypt
|
|
184
148
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
|
|
4
|
+
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.normalize = normalize;
|
|
7
7
|
function normalize(brain_key) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
if (typeof brain_key !== 'string') {
|
|
9
|
+
throw new Error("string required for brain_key");
|
|
10
|
+
}
|
|
11
|
+
brain_key = brain_key.trim();
|
|
12
|
+
return brain_key.split(/[\t\n\v\f\r ]+/).join(' ');
|
|
13
13
|
}
|
|
@@ -1,28 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
var assert = require('assert'); // from github.com/bitcoinjs/bitcoinjs-lib from github.com/cryptocoinjs/ecdsa
|
|
4
4
|
var crypto = require('./hash');
|
|
5
5
|
var enforceType = require('./enforce_types');
|
|
6
|
-
|
|
7
6
|
var BigInteger = require('bigi');
|
|
8
7
|
var ECSignature = require('./ecsignature');
|
|
9
8
|
|
|
10
9
|
// https://tools.ietf.org/html/rfc6979#section-3.2
|
|
11
10
|
function deterministicGenerateK(curve, hash, d, checkSig, nonce) {
|
|
12
|
-
|
|
13
11
|
enforceType('Buffer', hash);
|
|
14
12
|
enforceType(BigInteger, d);
|
|
15
|
-
|
|
16
13
|
if (nonce) {
|
|
17
|
-
hash = crypto.sha256(Buffer.concat([hash, new Buffer(nonce)]));
|
|
14
|
+
hash = crypto.sha256(Buffer.concat([hash, new Buffer.alloc(nonce)]));
|
|
18
15
|
}
|
|
19
16
|
|
|
20
17
|
// sanity check
|
|
21
18
|
assert.equal(hash.length, 32, 'Hash must be 256 bit');
|
|
22
|
-
|
|
23
19
|
var x = d.toBuffer(32);
|
|
24
|
-
var k = new Buffer(32);
|
|
25
|
-
var v = new Buffer(32);
|
|
20
|
+
var k = new Buffer.alloc(32);
|
|
21
|
+
var v = new Buffer.alloc(32);
|
|
26
22
|
|
|
27
23
|
// Step B
|
|
28
24
|
v.fill(1);
|
|
@@ -31,13 +27,13 @@ function deterministicGenerateK(curve, hash, d, checkSig, nonce) {
|
|
|
31
27
|
k.fill(0);
|
|
32
28
|
|
|
33
29
|
// Step D
|
|
34
|
-
k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([0]), x, hash]), k);
|
|
30
|
+
k = crypto.HmacSHA256(Buffer.concat([v, new Buffer.from([0]), x, hash]), k);
|
|
35
31
|
|
|
36
32
|
// Step E
|
|
37
33
|
v = crypto.HmacSHA256(v, k);
|
|
38
34
|
|
|
39
35
|
// Step F
|
|
40
|
-
k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([1]), x, hash]), k);
|
|
36
|
+
k = crypto.HmacSHA256(Buffer.concat([v, new Buffer.from([1]), x, hash]), k);
|
|
41
37
|
|
|
42
38
|
// Step G
|
|
43
39
|
v = crypto.HmacSHA256(v, k);
|
|
@@ -45,60 +41,46 @@ function deterministicGenerateK(curve, hash, d, checkSig, nonce) {
|
|
|
45
41
|
// Step H1/H2a, ignored as tlen === qlen (256 bit)
|
|
46
42
|
// Step H2b
|
|
47
43
|
v = crypto.HmacSHA256(v, k);
|
|
48
|
-
|
|
49
44
|
var T = BigInteger.fromBuffer(v);
|
|
50
45
|
|
|
51
46
|
// Step H3, repeat until T is within the interval [1, n - 1]
|
|
52
47
|
while (T.signum() <= 0 || T.compareTo(curve.n) >= 0 || !checkSig(T)) {
|
|
53
|
-
k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([0])]), k);
|
|
48
|
+
k = crypto.HmacSHA256(Buffer.concat([v, new Buffer.from([0])]), k);
|
|
54
49
|
v = crypto.HmacSHA256(v, k);
|
|
55
50
|
|
|
56
51
|
// Step H1/H2a, again, ignored as tlen === qlen (256 bit)
|
|
57
52
|
// Step H2b again
|
|
58
53
|
v = crypto.HmacSHA256(v, k);
|
|
59
|
-
|
|
60
54
|
T = BigInteger.fromBuffer(v);
|
|
61
55
|
}
|
|
62
|
-
|
|
63
56
|
return T;
|
|
64
57
|
}
|
|
65
|
-
|
|
66
58
|
function sign(curve, hash, d, nonce) {
|
|
67
|
-
|
|
68
59
|
var e = BigInteger.fromBuffer(hash);
|
|
69
60
|
var n = curve.n;
|
|
70
61
|
var G = curve.G;
|
|
71
|
-
|
|
72
62
|
var r, s;
|
|
73
63
|
var k = deterministicGenerateK(curve, hash, d, function (k) {
|
|
74
64
|
// find canonically valid signature
|
|
75
65
|
var Q = G.multiply(k);
|
|
76
|
-
|
|
77
66
|
if (curve.isInfinity(Q)) return false;
|
|
78
|
-
|
|
79
67
|
r = Q.affineX.mod(n);
|
|
80
68
|
if (r.signum() === 0) return false;
|
|
81
|
-
|
|
82
69
|
s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
|
|
83
70
|
if (s.signum() === 0) return false;
|
|
84
|
-
|
|
85
71
|
return true;
|
|
86
72
|
}, nonce);
|
|
87
|
-
|
|
88
73
|
var N_OVER_TWO = n.shiftRight(1);
|
|
89
74
|
|
|
90
75
|
// enforce low S values, see bip62: 'low s values in signatures'
|
|
91
76
|
if (s.compareTo(N_OVER_TWO) > 0) {
|
|
92
77
|
s = n.subtract(s);
|
|
93
78
|
}
|
|
94
|
-
|
|
95
79
|
return new ECSignature(r, s);
|
|
96
80
|
}
|
|
97
|
-
|
|
98
81
|
function verifyRaw(curve, e, signature, Q) {
|
|
99
82
|
var n = curve.n;
|
|
100
83
|
var G = curve.G;
|
|
101
|
-
|
|
102
84
|
var r = signature.r;
|
|
103
85
|
var s = signature.s;
|
|
104
86
|
|
|
@@ -129,7 +111,6 @@ function verifyRaw(curve, e, signature, Q) {
|
|
|
129
111
|
// 1.4.8 If v = r, output "valid", and if v != r, output "invalid"
|
|
130
112
|
return v.equals(r);
|
|
131
113
|
}
|
|
132
|
-
|
|
133
114
|
function verify(curve, hash, signature, Q) {
|
|
134
115
|
// 1.4.2 H = Hash(M), already done by the user
|
|
135
116
|
// 1.4.3 e = H
|
|
@@ -147,13 +128,10 @@ function verify(curve, hash, signature, Q) {
|
|
|
147
128
|
*/
|
|
148
129
|
function recoverPubKey(curve, e, signature, i) {
|
|
149
130
|
assert.strictEqual(i & 3, i, 'Recovery param is more than two bits');
|
|
150
|
-
|
|
151
131
|
var n = curve.n;
|
|
152
132
|
var G = curve.G;
|
|
153
|
-
|
|
154
133
|
var r = signature.r;
|
|
155
134
|
var s = signature.s;
|
|
156
|
-
|
|
157
135
|
assert(r.signum() > 0 && r.compareTo(n) < 0, 'Invalid r value');
|
|
158
136
|
assert(s.signum() > 0 && s.compareTo(n) < 0, 'Invalid s value');
|
|
159
137
|
|
|
@@ -178,10 +156,8 @@ function recoverPubKey(curve, e, signature, i) {
|
|
|
178
156
|
// 1.6.1 Compute Q = r^-1 (sR - eG)
|
|
179
157
|
// Q = r^-1 (sR + -eG)
|
|
180
158
|
var rInv = r.modInverse(n);
|
|
181
|
-
|
|
182
159
|
var Q = R.multiplyTwo(s, G, eNeg).multiply(rInv);
|
|
183
160
|
curve.validate(Q);
|
|
184
|
-
|
|
185
161
|
return Q;
|
|
186
162
|
}
|
|
187
163
|
|
|
@@ -205,10 +181,8 @@ function calcPubKeyRecoveryParam(curve, e, signature, Q) {
|
|
|
205
181
|
return i;
|
|
206
182
|
}
|
|
207
183
|
}
|
|
208
|
-
|
|
209
184
|
throw new Error('Unable to find valid recovery factor');
|
|
210
185
|
}
|
|
211
|
-
|
|
212
186
|
module.exports = {
|
|
213
187
|
calcPubKeyRecoveryParam: calcPubKeyRecoveryParam,
|
|
214
188
|
deterministicGenerateK: deterministicGenerateK,
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
var assert = require('assert'); // from https://github.com/bitcoinjs/bitcoinjs-lib
|
|
4
4
|
var enforceType = require('./enforce_types');
|
|
5
|
-
|
|
6
5
|
var BigInteger = require('bigi');
|
|
7
|
-
|
|
8
6
|
function ECSignature(r, s) {
|
|
9
7
|
enforceType(BigInteger, r);
|
|
10
8
|
enforceType(BigInteger, s);
|
|
11
|
-
|
|
12
9
|
this.r = r;
|
|
13
10
|
this.s = s;
|
|
14
11
|
}
|
|
@@ -24,50 +21,38 @@ ECSignature.parseCompact = function (buffer) {
|
|
|
24
21
|
|
|
25
22
|
// Recovery param only
|
|
26
23
|
i = i & 3;
|
|
27
|
-
|
|
28
24
|
var r = BigInteger.fromBuffer(buffer.slice(1, 33));
|
|
29
25
|
var s = BigInteger.fromBuffer(buffer.slice(33));
|
|
30
|
-
|
|
31
26
|
return {
|
|
32
27
|
compressed: compressed,
|
|
33
28
|
i: i,
|
|
34
29
|
signature: new ECSignature(r, s)
|
|
35
30
|
};
|
|
36
31
|
};
|
|
37
|
-
|
|
38
32
|
ECSignature.fromDER = function (buffer) {
|
|
39
33
|
assert.equal(buffer.readUInt8(0), 0x30, 'Not a DER sequence');
|
|
40
34
|
assert.equal(buffer.readUInt8(1), buffer.length - 2, 'Invalid sequence length');
|
|
41
35
|
assert.equal(buffer.readUInt8(2), 0x02, 'Expected a DER integer');
|
|
42
|
-
|
|
43
36
|
var rLen = buffer.readUInt8(3);
|
|
44
37
|
assert(rLen > 0, 'R length is zero');
|
|
45
|
-
|
|
46
38
|
var offset = 4 + rLen;
|
|
47
39
|
assert.equal(buffer.readUInt8(offset), 0x02, 'Expected a DER integer (2)');
|
|
48
|
-
|
|
49
40
|
var sLen = buffer.readUInt8(offset + 1);
|
|
50
41
|
assert(sLen > 0, 'S length is zero');
|
|
51
|
-
|
|
52
42
|
var rB = buffer.slice(4, offset);
|
|
53
43
|
var sB = buffer.slice(offset + 2);
|
|
54
44
|
offset += 2 + sLen;
|
|
55
|
-
|
|
56
45
|
if (rLen > 1 && rB.readUInt8(0) === 0x00) {
|
|
57
46
|
assert(rB.readUInt8(1) & 0x80, 'R value excessively padded');
|
|
58
47
|
}
|
|
59
|
-
|
|
60
48
|
if (sLen > 1 && sB.readUInt8(0) === 0x00) {
|
|
61
49
|
assert(sB.readUInt8(1) & 0x80, 'S value excessively padded');
|
|
62
50
|
}
|
|
63
|
-
|
|
64
51
|
assert.equal(offset, buffer.length, 'Invalid DER encoding');
|
|
65
52
|
var r = BigInteger.fromDERInteger(rB);
|
|
66
53
|
var s = BigInteger.fromDERInteger(sB);
|
|
67
|
-
|
|
68
54
|
assert(r.signum() >= 0, 'R value is negative');
|
|
69
55
|
assert(s.signum() >= 0, 'S value is negative');
|
|
70
|
-
|
|
71
56
|
return new ECSignature(r, s);
|
|
72
57
|
};
|
|
73
58
|
|
|
@@ -75,9 +60,7 @@ ECSignature.fromDER = function (buffer) {
|
|
|
75
60
|
ECSignature.parseScriptSignature = function (buffer) {
|
|
76
61
|
var hashType = buffer.readUInt8(buffer.length - 1);
|
|
77
62
|
var hashTypeMod = hashType & ~0x80;
|
|
78
|
-
|
|
79
63
|
assert(hashTypeMod > 0x00 && hashTypeMod < 0x04, 'Invalid hashType');
|
|
80
|
-
|
|
81
64
|
return {
|
|
82
65
|
signature: ECSignature.fromDER(buffer.slice(0, -1)),
|
|
83
66
|
hashType: hashType
|
|
@@ -88,20 +71,15 @@ ECSignature.parseScriptSignature = function (buffer) {
|
|
|
88
71
|
ECSignature.prototype.toCompact = function (i, compressed) {
|
|
89
72
|
if (compressed) i += 4;
|
|
90
73
|
i += 27;
|
|
91
|
-
|
|
92
|
-
var buffer = new Buffer(65);
|
|
74
|
+
var buffer = new Buffer.alloc(65);
|
|
93
75
|
buffer.writeUInt8(i, 0);
|
|
94
|
-
|
|
95
76
|
this.r.toBuffer(32).copy(buffer, 1);
|
|
96
77
|
this.s.toBuffer(32).copy(buffer, 33);
|
|
97
|
-
|
|
98
78
|
return buffer;
|
|
99
79
|
};
|
|
100
|
-
|
|
101
80
|
ECSignature.prototype.toDER = function () {
|
|
102
81
|
var rBa = this.r.toDERInteger();
|
|
103
82
|
var sBa = this.s.toDERInteger();
|
|
104
|
-
|
|
105
83
|
var sequence = [];
|
|
106
84
|
|
|
107
85
|
// INTEGER
|
|
@@ -114,15 +92,11 @@ ECSignature.prototype.toDER = function () {
|
|
|
114
92
|
|
|
115
93
|
// SEQUENCE
|
|
116
94
|
sequence.unshift(0x30, sequence.length);
|
|
117
|
-
|
|
118
|
-
return new Buffer(sequence);
|
|
95
|
+
return new Buffer.from(sequence);
|
|
119
96
|
};
|
|
120
|
-
|
|
121
97
|
ECSignature.prototype.toScriptSignature = function (hashType) {
|
|
122
|
-
var hashTypeBuffer = new Buffer(1);
|
|
98
|
+
var hashTypeBuffer = new Buffer.alloc(1);
|
|
123
99
|
hashTypeBuffer.writeUInt8(hashType, 0);
|
|
124
|
-
|
|
125
100
|
return Buffer.concat([this.toDER(), hashTypeBuffer]);
|
|
126
101
|
};
|
|
127
|
-
|
|
128
102
|
module.exports = ECSignature;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
module.exports = function enforce(type, value) {
|
|
4
4
|
// Copied from https://github.com/bitcoinjs/bitcoinjs-lib
|
|
@@ -8,40 +8,33 @@ module.exports = function enforce(type, value) {
|
|
|
8
8
|
if (Array.isArray(value)) return;
|
|
9
9
|
break;
|
|
10
10
|
}
|
|
11
|
-
|
|
12
11
|
case 'Boolean':
|
|
13
12
|
{
|
|
14
13
|
if (typeof value === 'boolean') return;
|
|
15
14
|
break;
|
|
16
15
|
}
|
|
17
|
-
|
|
18
16
|
case 'Buffer':
|
|
19
17
|
{
|
|
20
18
|
if (Buffer.isBuffer(value)) return;
|
|
21
19
|
break;
|
|
22
20
|
}
|
|
23
|
-
|
|
24
21
|
case 'Number':
|
|
25
22
|
{
|
|
26
23
|
if (typeof value === 'number') return;
|
|
27
24
|
break;
|
|
28
25
|
}
|
|
29
|
-
|
|
30
26
|
case 'String':
|
|
31
27
|
{
|
|
32
28
|
if (typeof value === 'string') return;
|
|
33
29
|
break;
|
|
34
30
|
}
|
|
35
|
-
|
|
36
31
|
default:
|
|
37
32
|
{
|
|
38
33
|
if (getName(value.constructor) === getName(type)) return;
|
|
39
34
|
}
|
|
40
35
|
}
|
|
41
|
-
|
|
42
36
|
throw new TypeError('Expected ' + (getName(type) || type) + ', got ' + value);
|
|
43
37
|
};
|
|
44
|
-
|
|
45
38
|
function getName(fn) {
|
|
46
39
|
// Why not fn.name: https://kangax.github.io/compat-table/es6/#function_name_property
|
|
47
40
|
var match = fn.toString().match(/function (.*?)\(/);
|