@bsv/sdk 1.0.12 → 1.0.14
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/dist/cjs/package.json +1 -1
- package/dist/cjs/src/compat/BSM.js.map +1 -1
- package/dist/cjs/src/compat/ECIES.js +105 -76
- package/dist/cjs/src/compat/ECIES.js.map +1 -1
- package/dist/cjs/src/compat/HD.js +65 -65
- package/dist/cjs/src/compat/HD.js.map +1 -1
- package/dist/cjs/src/compat/Mnemonic.js +79 -79
- package/dist/cjs/src/compat/Mnemonic.js.map +1 -1
- package/dist/cjs/src/compat/bip-39-wordlist-en.js +2 -2
- package/dist/cjs/src/compat/bip-39-wordlist-en.js.map +1 -1
- package/dist/cjs/src/primitives/AESGCM.js.map +1 -1
- package/dist/cjs/src/primitives/BigNumber.js.map +1 -1
- package/dist/cjs/src/primitives/DRBG.js.map +1 -1
- package/dist/cjs/src/primitives/ECDSA.js.map +1 -1
- package/dist/cjs/src/primitives/Hash.js +26 -13
- package/dist/cjs/src/primitives/Hash.js.map +1 -1
- package/dist/cjs/src/primitives/PrivateKey.js +3 -2
- package/dist/cjs/src/primitives/PrivateKey.js.map +1 -1
- package/dist/cjs/src/primitives/PublicKey.js +1 -2
- package/dist/cjs/src/primitives/PublicKey.js.map +1 -1
- package/dist/cjs/src/primitives/Random.js +2 -2
- package/dist/cjs/src/primitives/Random.js.map +1 -1
- package/dist/cjs/src/primitives/Signature.js +141 -4
- package/dist/cjs/src/primitives/Signature.js.map +1 -1
- package/dist/cjs/src/primitives/SymmetricKey.js.map +1 -1
- package/dist/cjs/src/primitives/TransactionSignature.js.map +1 -1
- package/dist/cjs/src/primitives/utils.js +14 -9
- package/dist/cjs/src/primitives/utils.js.map +1 -1
- package/dist/cjs/src/script/Spend.js.map +1 -1
- package/dist/cjs/src/script/templates/P2PKH.js +1 -1
- package/dist/cjs/src/script/templates/P2PKH.js.map +1 -1
- package/dist/cjs/src/transaction/MerklePath.js +3 -3
- package/dist/cjs/src/transaction/MerklePath.js.map +1 -1
- package/dist/cjs/src/transaction/Transaction.js +15 -4
- package/dist/cjs/src/transaction/Transaction.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/compat/BSM.js.map +1 -1
- package/dist/esm/src/compat/ECIES.js +105 -76
- package/dist/esm/src/compat/ECIES.js.map +1 -1
- package/dist/esm/src/compat/HD.js +65 -65
- package/dist/esm/src/compat/HD.js.map +1 -1
- package/dist/esm/src/compat/Mnemonic.js +79 -79
- package/dist/esm/src/compat/Mnemonic.js.map +1 -1
- package/dist/esm/src/compat/bip-39-wordlist-en.js +2 -2
- package/dist/esm/src/compat/bip-39-wordlist-en.js.map +1 -1
- package/dist/esm/src/primitives/AESGCM.js.map +1 -1
- package/dist/esm/src/primitives/BigNumber.js.map +1 -1
- package/dist/esm/src/primitives/DRBG.js.map +1 -1
- package/dist/esm/src/primitives/ECDSA.js.map +1 -1
- package/dist/esm/src/primitives/Hash.js +26 -13
- package/dist/esm/src/primitives/Hash.js.map +1 -1
- package/dist/esm/src/primitives/PrivateKey.js +3 -2
- package/dist/esm/src/primitives/PrivateKey.js.map +1 -1
- package/dist/esm/src/primitives/PublicKey.js +1 -2
- package/dist/esm/src/primitives/PublicKey.js.map +1 -1
- package/dist/esm/src/primitives/Random.js +2 -2
- package/dist/esm/src/primitives/Random.js.map +1 -1
- package/dist/esm/src/primitives/Signature.js +141 -4
- package/dist/esm/src/primitives/Signature.js.map +1 -1
- package/dist/esm/src/primitives/SymmetricKey.js.map +1 -1
- package/dist/esm/src/primitives/TransactionSignature.js.map +1 -1
- package/dist/esm/src/primitives/utils.js +14 -9
- package/dist/esm/src/primitives/utils.js.map +1 -1
- package/dist/esm/src/script/Spend.js.map +1 -1
- package/dist/esm/src/script/templates/P2PKH.js +1 -1
- package/dist/esm/src/script/templates/P2PKH.js.map +1 -1
- package/dist/esm/src/transaction/MerklePath.js +3 -3
- package/dist/esm/src/transaction/MerklePath.js.map +1 -1
- package/dist/esm/src/transaction/Transaction.js +16 -4
- package/dist/esm/src/transaction/Transaction.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/compat/ECIES.d.ts +36 -36
- package/dist/types/src/compat/ECIES.d.ts.map +1 -1
- package/dist/types/src/compat/HD.d.ts +65 -65
- package/dist/types/src/compat/HD.d.ts.map +1 -1
- package/dist/types/src/compat/Mnemonic.d.ts +79 -79
- package/dist/types/src/compat/Mnemonic.d.ts.map +1 -1
- package/dist/types/src/primitives/AESGCM.d.ts.map +1 -1
- package/dist/types/src/primitives/BigNumber.d.ts.map +1 -1
- package/dist/types/src/primitives/Hash.d.ts.map +1 -1
- package/dist/types/src/primitives/PrivateKey.d.ts.map +1 -1
- package/dist/types/src/primitives/PublicKey.d.ts.map +1 -1
- package/dist/types/src/primitives/Signature.d.ts +62 -0
- package/dist/types/src/primitives/Signature.d.ts.map +1 -1
- package/dist/types/src/primitives/SymmetricKey.d.ts.map +1 -1
- package/dist/types/src/primitives/TransactionSignature.d.ts.map +1 -1
- package/dist/types/src/primitives/utils.d.ts.map +1 -1
- package/dist/types/src/script/Spend.d.ts.map +1 -1
- package/dist/types/src/transaction/Transaction.d.ts +1 -0
- package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/docs/compat.md +4 -4
- package/docs/primitives.md +288 -79
- package/package.json +1 -1
- package/src/compat/BSM.ts +12 -12
- package/src/compat/ECIES.ts +417 -418
- package/src/compat/HD.ts +228 -228
- package/src/compat/Mnemonic.ts +173 -173
- package/src/compat/__tests/BSM.test.ts +13 -2
- package/src/compat/bip-39-wordlist-en.ts +2052 -2052
- package/src/primitives/AESGCM.ts +30 -30
- package/src/primitives/BigNumber.ts +0 -1
- package/src/primitives/DRBG.ts +5 -5
- package/src/primitives/ECDSA.ts +1 -1
- package/src/primitives/Hash.ts +278 -293
- package/src/primitives/PrivateKey.ts +18 -19
- package/src/primitives/PublicKey.ts +9 -10
- package/src/primitives/Random.ts +4 -4
- package/src/primitives/Signature.ts +158 -14
- package/src/primitives/SymmetricKey.ts +3 -3
- package/src/primitives/TransactionSignature.ts +9 -9
- package/src/primitives/index.ts +1 -1
- package/src/primitives/utils.ts +60 -64
- package/src/script/Spend.ts +12 -12
- package/src/script/index.ts +1 -1
- package/src/script/templates/P2PKH.ts +1 -1
- package/src/transaction/MerklePath.ts +3 -3
- package/src/transaction/Transaction.ts +36 -26
- package/src/transaction/__tests/Transaction.test.ts +5 -5
package/src/compat/Mnemonic.ts
CHANGED
|
@@ -5,7 +5,7 @@ import Random from '../primitives/Random.js'
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @class Mnemonic
|
|
8
|
-
*
|
|
8
|
+
*
|
|
9
9
|
* @description
|
|
10
10
|
* Class representing Mnemonic functionality.
|
|
11
11
|
* This class provides methods for generating, converting, and validating mnemonic phrases
|
|
@@ -13,154 +13,154 @@ import Random from '../primitives/Random.js'
|
|
|
13
13
|
* converting mnemonics to seeds, and validating mnemonic phrases.
|
|
14
14
|
*/
|
|
15
15
|
export default class Mnemonic {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
public mnemonic: string
|
|
17
|
+
public seed: number[]
|
|
18
|
+
public Wordlist: { value: string[], space: string }
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
21
|
* Constructs a Mnemonic object.
|
|
22
22
|
* @param {string} [mnemonic] - An optional mnemonic phrase.
|
|
23
23
|
* @param {number[]} [seed] - An optional seed derived from the mnemonic.
|
|
24
24
|
* @param {object} [wordlist=wordList] - An object containing a list of words and space character used in the mnemonic.
|
|
25
25
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
constructor (mnemonic?: string, seed?: number[], wordlist = wordList) {
|
|
27
|
+
this.mnemonic = mnemonic
|
|
28
|
+
this.seed = seed
|
|
29
|
+
this.Wordlist = wordlist
|
|
30
|
+
}
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
/**
|
|
33
33
|
* Converts the mnemonic and seed into a binary representation.
|
|
34
34
|
* @returns {number[]} The binary representation of the mnemonic and seed.
|
|
35
35
|
*/
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
return bw.toArray()
|
|
36
|
+
public toBinary (): number[] {
|
|
37
|
+
const bw = new Writer()
|
|
38
|
+
if (this.mnemonic) {
|
|
39
|
+
const buf = toArray(this.mnemonic, 'utf8')
|
|
40
|
+
bw.writeVarIntNum(buf.length)
|
|
41
|
+
bw.write(buf)
|
|
42
|
+
} else {
|
|
43
|
+
bw.writeVarIntNum(0)
|
|
44
|
+
}
|
|
45
|
+
if (this.seed) {
|
|
46
|
+
bw.writeVarIntNum(this.seed.length)
|
|
47
|
+
bw.write(this.seed)
|
|
48
|
+
} else {
|
|
49
|
+
bw.writeVarIntNum(0)
|
|
52
50
|
}
|
|
51
|
+
return bw.toArray()
|
|
52
|
+
}
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
/**
|
|
55
55
|
* Loads a mnemonic and seed from a binary representation.
|
|
56
56
|
* @param {number[]} bin - The binary representation of a mnemonic and seed.
|
|
57
57
|
* @returns {this} The Mnemonic instance with loaded mnemonic and seed.
|
|
58
58
|
*/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
return this
|
|
59
|
+
public fromBinary (bin: number[]): this {
|
|
60
|
+
const br = new Reader(bin)
|
|
61
|
+
const mnemoniclen = br.readVarIntNum()
|
|
62
|
+
if (mnemoniclen > 0) {
|
|
63
|
+
this.mnemonic = encode(br.read(mnemoniclen), 'utf8') as string
|
|
64
|
+
}
|
|
65
|
+
const seedlen = br.readVarIntNum()
|
|
66
|
+
if (seedlen > 0) {
|
|
67
|
+
this.seed = br.read(seedlen)
|
|
70
68
|
}
|
|
69
|
+
return this
|
|
70
|
+
}
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
/**
|
|
73
73
|
* Generates a random mnemonic from a given bit length.
|
|
74
74
|
* @param {number} [bits=128] - The bit length for the random mnemonic (must be a multiple of 32 and at least 128).
|
|
75
75
|
* @returns {this} The Mnemonic instance with the new random mnemonic.
|
|
76
76
|
* @throws {Error} If the bit length is not a multiple of 32 or is less than 128.
|
|
77
77
|
*/
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
if (bits % 32 !== 0) {
|
|
83
|
-
throw new Error('bits must be multiple of 32')
|
|
84
|
-
}
|
|
85
|
-
if (bits < 128) {
|
|
86
|
-
throw new Error('bits must be at least 128')
|
|
87
|
-
}
|
|
88
|
-
const buf = Random(bits / 8)
|
|
89
|
-
this.entropy2Mnemonic(buf)
|
|
90
|
-
this.mnemonic2Seed()
|
|
91
|
-
return this
|
|
78
|
+
public fromRandom (bits?: number): this {
|
|
79
|
+
if (!bits) {
|
|
80
|
+
bits = 128
|
|
92
81
|
}
|
|
82
|
+
if (bits % 32 !== 0) {
|
|
83
|
+
throw new Error('bits must be multiple of 32')
|
|
84
|
+
}
|
|
85
|
+
if (bits < 128) {
|
|
86
|
+
throw new Error('bits must be at least 128')
|
|
87
|
+
}
|
|
88
|
+
const buf = Random(bits / 8)
|
|
89
|
+
this.entropy2Mnemonic(buf)
|
|
90
|
+
this.mnemonic2Seed()
|
|
91
|
+
return this
|
|
92
|
+
}
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
/**
|
|
95
95
|
* Static method to generate a Mnemonic instance with a random mnemonic.
|
|
96
96
|
* @param {number} [bits=128] - The bit length for the random mnemonic.
|
|
97
97
|
* @returns {Mnemonic} A new Mnemonic instance.
|
|
98
98
|
*/
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
public static fromRandom (bits?: number): Mnemonic {
|
|
100
|
+
return new this().fromRandom(bits)
|
|
101
|
+
}
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
/**
|
|
104
104
|
* Converts given entropy into a mnemonic phrase.
|
|
105
105
|
* This method is used to generate a mnemonic from a specific entropy source.
|
|
106
106
|
* @param {number[]} buf - The entropy buffer, must be at least 128 bits.
|
|
107
107
|
* @returns {this} The Mnemonic instance with the mnemonic set from the given entropy.
|
|
108
108
|
* @throws {Error} If the entropy is less than 128 bits.
|
|
109
109
|
*/
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
public fromEntropy (buf: number[]): this {
|
|
111
|
+
this.entropy2Mnemonic(buf)
|
|
112
|
+
return this
|
|
113
|
+
}
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
/**
|
|
116
116
|
* Static method to create a Mnemonic instance from a given entropy.
|
|
117
117
|
* @param {number[]} buf - The entropy buffer.
|
|
118
118
|
* @returns {Mnemonic} A new Mnemonic instance.
|
|
119
119
|
*/
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
public static fromEntropy (buf: number[]): Mnemonic {
|
|
121
|
+
return new this().fromEntropy(buf)
|
|
122
|
+
}
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
/**
|
|
125
125
|
* Sets the mnemonic for the instance from a string.
|
|
126
126
|
* @param {string} mnemonic - The mnemonic phrase as a string.
|
|
127
127
|
* @returns {this} The Mnemonic instance with the set mnemonic.
|
|
128
128
|
*/
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
public fromString (mnemonic: string): this {
|
|
130
|
+
this.mnemonic = mnemonic
|
|
131
|
+
return this
|
|
132
|
+
}
|
|
133
133
|
|
|
134
|
-
|
|
134
|
+
/**
|
|
135
135
|
* Static method to create a Mnemonic instance from a mnemonic string.
|
|
136
136
|
* @param {string} str - The mnemonic phrase.
|
|
137
137
|
* @returns {Mnemonic} A new Mnemonic instance.
|
|
138
138
|
*/
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
public static fromString (str: string): Mnemonic {
|
|
140
|
+
return new this().fromString(str)
|
|
141
|
+
}
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
/**
|
|
144
144
|
* Converts the instance's mnemonic to a string representation.
|
|
145
145
|
* @returns {string} The mnemonic phrase as a string.
|
|
146
146
|
*/
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
public toString (): string {
|
|
148
|
+
return this.mnemonic
|
|
149
|
+
}
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
/**
|
|
152
152
|
* Converts the mnemonic to a seed.
|
|
153
153
|
* The mnemonic must pass the validity check before conversion.
|
|
154
154
|
* @param {string} [passphrase=''] - An optional passphrase for additional security.
|
|
155
155
|
* @returns {number[]} The generated seed.
|
|
156
156
|
* @throws {Error} If the mnemonic is invalid.
|
|
157
157
|
*/
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
public toSeed (passphrase?: string): number[] {
|
|
159
|
+
this.mnemonic2Seed(passphrase)
|
|
160
|
+
return this.seed
|
|
161
|
+
}
|
|
162
162
|
|
|
163
|
-
|
|
163
|
+
/**
|
|
164
164
|
* Converts entropy to a mnemonic phrase.
|
|
165
165
|
* This method takes a buffer of entropy and converts it into a corresponding
|
|
166
166
|
* mnemonic phrase based on the Mnemonic wordlist. The entropy should be at least 128 bits.
|
|
@@ -169,78 +169,78 @@ export default class Mnemonic {
|
|
|
169
169
|
* @returns {this} The Mnemonic instance with the mnemonic set from the entropy.
|
|
170
170
|
* @throws {Error} If the entropy is less than 128 bits or if it's not an even multiple of 11 bits.
|
|
171
171
|
*/
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const hash = Hash.sha256(buf)
|
|
178
|
-
let bin = ''
|
|
179
|
-
const bits = buf.length * 8
|
|
180
|
-
for (let i = 0; i < buf.length; i++) {
|
|
181
|
-
bin = bin + ('00000000' + buf[i].toString(2)).slice(-8)
|
|
182
|
-
}
|
|
183
|
-
let hashbits = hash[0].toString(2)
|
|
184
|
-
hashbits = ('00000000' + hashbits).slice(-8).slice(0, bits / 32)
|
|
185
|
-
bin = bin + hashbits
|
|
172
|
+
public entropy2Mnemonic (buf: number[]): this {
|
|
173
|
+
if (buf.length < 128 / 8) {
|
|
174
|
+
throw new Error('Entropy is less than 128 bits. It must be 128 bits or more.')
|
|
175
|
+
}
|
|
186
176
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
177
|
+
const hash = Hash.sha256(buf)
|
|
178
|
+
let bin = ''
|
|
179
|
+
const bits = buf.length * 8
|
|
180
|
+
for (let i = 0; i < buf.length; i++) {
|
|
181
|
+
bin = bin + ('00000000' + buf[i].toString(2)).slice(-8)
|
|
182
|
+
}
|
|
183
|
+
let hashbits = hash[0].toString(2)
|
|
184
|
+
hashbits = ('00000000' + hashbits).slice(-8).slice(0, bits / 32)
|
|
185
|
+
bin = bin + hashbits
|
|
190
186
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
mnemonic = mnemonic + this.Wordlist.space
|
|
195
|
-
}
|
|
196
|
-
const wi = parseInt(bin.slice(i * 11, (i + 1) * 11), 2)
|
|
197
|
-
mnemonic = mnemonic + this.Wordlist.value[wi]
|
|
198
|
-
}
|
|
187
|
+
if (bin.length % 11 !== 0) {
|
|
188
|
+
throw new Error('internal error - entropy not an even multiple of 11 bits - ' + bin.length)
|
|
189
|
+
}
|
|
199
190
|
|
|
200
|
-
|
|
201
|
-
|
|
191
|
+
let mnemonic = ''
|
|
192
|
+
for (let i = 0; i < bin.length / 11; i++) {
|
|
193
|
+
if (mnemonic !== '') {
|
|
194
|
+
mnemonic = mnemonic + this.Wordlist.space
|
|
195
|
+
}
|
|
196
|
+
const wi = parseInt(bin.slice(i * 11, (i + 1) * 11), 2)
|
|
197
|
+
mnemonic = mnemonic + this.Wordlist.value[wi]
|
|
202
198
|
}
|
|
203
199
|
|
|
204
|
-
|
|
200
|
+
this.mnemonic = mnemonic
|
|
201
|
+
return this
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
205
|
* Validates the mnemonic phrase.
|
|
206
206
|
* Checks for correct length, absence of invalid words, and proper checksum.
|
|
207
207
|
* @returns {boolean} True if the mnemonic is valid, false otherwise.
|
|
208
208
|
* @throws {Error} If the mnemonic is not an even multiple of 11 bits.
|
|
209
209
|
*/
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
// confirm no invalid words
|
|
214
|
-
const words = mnemonic.split(this.Wordlist.space)
|
|
215
|
-
let bin = ''
|
|
216
|
-
for (let i = 0; i < words.length; i++) {
|
|
217
|
-
const ind = this.Wordlist.value.indexOf(words[i])
|
|
218
|
-
if (ind < 0) {
|
|
219
|
-
return false
|
|
220
|
-
}
|
|
221
|
-
bin = bin + ('00000000000' + ind.toString(2)).slice(-11)
|
|
222
|
-
}
|
|
210
|
+
public check (): boolean {
|
|
211
|
+
const mnemonic = this.mnemonic
|
|
223
212
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
213
|
+
// confirm no invalid words
|
|
214
|
+
const words = mnemonic.split(this.Wordlist.space)
|
|
215
|
+
let bin = ''
|
|
216
|
+
for (let i = 0; i < words.length; i++) {
|
|
217
|
+
const ind = this.Wordlist.value.indexOf(words[i])
|
|
218
|
+
if (ind < 0) {
|
|
219
|
+
return false
|
|
220
|
+
}
|
|
221
|
+
bin = bin + ('00000000000' + ind.toString(2)).slice(-11)
|
|
222
|
+
}
|
|
227
223
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const nonhashBits = bin.slice(0, bin.length - cs)
|
|
232
|
-
const buf = []
|
|
233
|
-
for (let i = 0; i < nonhashBits.length / 8; i++) {
|
|
234
|
-
buf.push(parseInt(bin.slice(i * 8, (i + 1) * 8), 2))
|
|
235
|
-
}
|
|
236
|
-
const hash = Hash.sha256(buf.slice(0, nonhashBits.length / 8))
|
|
237
|
-
let expectedHashBits = hash[0].toString(2)
|
|
238
|
-
expectedHashBits = ('00000000' + expectedHashBits).slice(-8).slice(0, cs)
|
|
224
|
+
if (bin.length % 11 !== 0) {
|
|
225
|
+
throw new Error('internal error - entropy not an even multiple of 11 bits - ' + bin.length)
|
|
226
|
+
}
|
|
239
227
|
|
|
240
|
-
|
|
228
|
+
// confirm checksum
|
|
229
|
+
const cs = bin.length / 33
|
|
230
|
+
const hashBits = bin.slice(-cs)
|
|
231
|
+
const nonhashBits = bin.slice(0, bin.length - cs)
|
|
232
|
+
const buf = []
|
|
233
|
+
for (let i = 0; i < nonhashBits.length / 8; i++) {
|
|
234
|
+
buf.push(parseInt(bin.slice(i * 8, (i + 1) * 8), 2))
|
|
241
235
|
}
|
|
236
|
+
const hash = Hash.sha256(buf.slice(0, nonhashBits.length / 8))
|
|
237
|
+
let expectedHashBits = hash[0].toString(2)
|
|
238
|
+
expectedHashBits = ('00000000' + expectedHashBits).slice(-8).slice(0, cs)
|
|
239
|
+
|
|
240
|
+
return expectedHashBits === hashBits
|
|
241
|
+
}
|
|
242
242
|
|
|
243
|
-
|
|
243
|
+
/**
|
|
244
244
|
* Converts a mnemonic to a seed.
|
|
245
245
|
* This method takes the instance's mnemonic phrase, combines it with a passphrase (if provided),
|
|
246
246
|
* and uses PBKDF2 to generate a seed. It also validates the mnemonic before conversion.
|
|
@@ -249,47 +249,47 @@ export default class Mnemonic {
|
|
|
249
249
|
* @returns {this} The Mnemonic instance with the seed generated from the mnemonic.
|
|
250
250
|
* @throws {Error} If the mnemonic does not pass validation or if the passphrase is not a string.
|
|
251
251
|
*/
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
-
if (typeof passphrase !== 'string') {
|
|
260
|
-
throw new Error('passphrase must be a string or undefined')
|
|
261
|
-
}
|
|
262
|
-
mnemonic = mnemonic.normalize('NFKD')
|
|
263
|
-
passphrase = passphrase.normalize('NFKD')
|
|
264
|
-
const mbuf = toArray(mnemonic, 'utf8')
|
|
265
|
-
const pbuf = [...toArray('mnemonic', 'utf8'), ...toArray(passphrase, 'utf8')]
|
|
266
|
-
this.seed = Hash.pbkdf2(mbuf, pbuf, 2048, 64, 'sha512')
|
|
267
|
-
return this
|
|
252
|
+
public mnemonic2Seed (passphrase = ''): this {
|
|
253
|
+
let mnemonic = this.mnemonic
|
|
254
|
+
if (!this.check()) {
|
|
255
|
+
throw new Error(
|
|
256
|
+
'Mnemonic does not pass the check - was the mnemonic typed incorrectly? Are there extra spaces?'
|
|
257
|
+
)
|
|
268
258
|
}
|
|
259
|
+
if (typeof passphrase !== 'string') {
|
|
260
|
+
throw new Error('passphrase must be a string or undefined')
|
|
261
|
+
}
|
|
262
|
+
mnemonic = mnemonic.normalize('NFKD')
|
|
263
|
+
passphrase = passphrase.normalize('NFKD')
|
|
264
|
+
const mbuf = toArray(mnemonic, 'utf8')
|
|
265
|
+
const pbuf = [...toArray('mnemonic', 'utf8'), ...toArray(passphrase, 'utf8')]
|
|
266
|
+
this.seed = Hash.pbkdf2(mbuf, pbuf, 2048, 64, 'sha512')
|
|
267
|
+
return this
|
|
268
|
+
}
|
|
269
269
|
|
|
270
|
-
|
|
270
|
+
/**
|
|
271
271
|
* Determines the validity of a given passphrase with the mnemonic.
|
|
272
272
|
* This method is useful for checking if a passphrase matches with the mnemonic.
|
|
273
273
|
* @param {string} [passphrase=''] - The passphrase to validate.
|
|
274
274
|
* @returns {boolean} True if the mnemonic and passphrase combination is valid, false otherwise.
|
|
275
275
|
*/
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}
|
|
283
|
-
return isValid
|
|
276
|
+
public isValid (passphrase = ''): boolean {
|
|
277
|
+
let isValid
|
|
278
|
+
try {
|
|
279
|
+
isValid = !!this.mnemonic2Seed(passphrase)
|
|
280
|
+
} catch (err) {
|
|
281
|
+
isValid = false
|
|
284
282
|
}
|
|
283
|
+
return isValid
|
|
284
|
+
}
|
|
285
285
|
|
|
286
|
-
|
|
286
|
+
/**
|
|
287
287
|
* Static method to check the validity of a given mnemonic and passphrase combination.
|
|
288
288
|
* @param {string} mnemonic - The mnemonic phrase.
|
|
289
289
|
* @param {string} [passphrase=''] - The passphrase to validate.
|
|
290
290
|
* @returns {boolean} True if the combination is valid, false otherwise.
|
|
291
291
|
*/
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
}
|
|
292
|
+
public static isValid (mnemonic: string, passphrase = ''): boolean {
|
|
293
|
+
return new Mnemonic(mnemonic).isValid(passphrase)
|
|
294
|
+
}
|
|
295
|
+
}
|
|
@@ -3,6 +3,7 @@ import { toArray } from '../../../dist/cjs/src/primitives/utils'
|
|
|
3
3
|
import PrivateKey from '../../../dist/cjs/src/primitives/PrivateKey'
|
|
4
4
|
import PublicKey from '../../../dist/cjs/src/primitives/PublicKey'
|
|
5
5
|
import Signature from '../../../dist/cjs/src/primitives/Signature'
|
|
6
|
+
import BigNumber from '../../../dist/cjs/src/primitives/BigNumber'
|
|
6
7
|
|
|
7
8
|
describe('BSM', () => {
|
|
8
9
|
describe('magicHash', () => {
|
|
@@ -30,9 +31,19 @@ describe('BSM', () => {
|
|
|
30
31
|
})
|
|
31
32
|
it('Should verify a signed message in base64', () => {
|
|
32
33
|
const message = toArray("Texas", 'utf8')
|
|
33
|
-
const signature = Signature.
|
|
34
|
-
const publicKey = PublicKey.fromString(
|
|
34
|
+
const signature = Signature.fromCompact('IAV89EkfHSzAIA8cEWbbKHUYzJqcShkpWaXGJ5+mf4+YIlf3XNlr0bj9X60sNe1A7+x9qyk+zmXropMDY4370n8=', 'base64')
|
|
35
|
+
const publicKey = PublicKey.fromString('03d4d1a6c5d8c03b0e671bc1891b69afaecb40c0686188fe9019f93581b43e8334')
|
|
35
36
|
expect(verify(message, signature, publicKey)).toBe(true)
|
|
36
37
|
})
|
|
38
|
+
it('Should be able to calculate the recovery number for a signature and public key', () => {
|
|
39
|
+
const message = toArray("Texas", 'utf8')
|
|
40
|
+
const signature = Signature.fromCompact('IAV89EkfHSzAIA8cEWbbKHUYzJqcShkpWaXGJ5+mf4+YIlf3XNlr0bj9X60sNe1A7+x9qyk+zmXropMDY4370n8=', 'base64')
|
|
41
|
+
const publicKey = PublicKey.fromString('03d4d1a6c5d8c03b0e671bc1891b69afaecb40c0686188fe9019f93581b43e8334')
|
|
42
|
+
const msgHash = new BigNumber(magicHash(message))
|
|
43
|
+
const recovery = signature.CalculateRecoveryFactor(publicKey, msgHash)
|
|
44
|
+
expect(recovery).toBe(1)
|
|
45
|
+
const recoveredPubkey = signature.RecoverPublicKey(recovery, msgHash) as PublicKey
|
|
46
|
+
expect(recoveredPubkey.toDER()).toEqual(publicKey.toDER())
|
|
47
|
+
})
|
|
37
48
|
})
|
|
38
49
|
})
|