static {
NODE: this.parentPort = parentPort
const listener = (message: MessageEvent<any>): Promise<void> => {
- return this._extractData(message.data).then(extracted => {
- const {
- action,
- type,
- key,
- keySalt,
- iv,
- seed,
- mnemonicPhrase,
- mnemonicSalt,
- index,
- encrypted,
- data
- } = extracted
- let result: Promise<NamedData>
- switch (action) {
- case 'STOP': {
- BROWSER: close()
- NODE: process.exit()
- }
- case 'create': {
- result = this.create(type, key, keySalt, mnemonicSalt)
- break
- }
- case 'derive': {
- result = this.derive(index)
- break
- }
- case 'load': {
- result = this.load(type, key, keySalt, mnemonicPhrase ?? seed, mnemonicSalt)
- break
- }
- case 'lock': {
- result = Promise.resolve(this.lock())
- break
- }
- case 'sign': {
- result = this.sign(index, data)
- break
- }
- case 'unlock': {
- result = this.unlock(type, key, iv, encrypted)
- break
- }
- case 'update': {
- result = this.update(key, keySalt)
- break
- }
- case 'verify': {
- result = Promise.resolve(this.verify(seed, mnemonicPhrase))
- break
- }
- default: {
- throw new Error(`Unknown wallet action '${action}'`)
- }
- }
- return result.then(result => {
- const transfer = []
- for (const k of Object.keys(result)) {
- if (result[k] instanceof ArrayBuffer || result[k] instanceof CryptoKey) {
- transfer.push(result[k])
+ return this._extractData(message.data)
+ .then(extracted => {
+ const {
+ action,
+ type,
+ key,
+ keySalt,
+ iv,
+ seed,
+ mnemonicPhrase,
+ mnemonicSalt,
+ index,
+ encrypted,
+ data
+ } = extracted
+ let result: Promise<NamedData>
+ switch (action) {
+ case 'STOP': {
+ BROWSER: close()
+ NODE: process.exit()
+ }
+ case 'create': {
+ result = this.create(type, key, keySalt, mnemonicSalt)
+ break
+ }
+ case 'derive': {
+ result = this.derive(index)
+ break
+ }
+ case 'load': {
+ result = this.load(type, key, keySalt, mnemonicPhrase ?? seed, mnemonicSalt)
+ break
+ }
+ case 'lock': {
+ result = Promise.resolve(this.lock())
+ break
+ }
+ case 'sign': {
+ result = this.sign(index, data)
+ break
+ }
+ case 'unlock': {
+ result = this.unlock(type, key, iv, encrypted)
+ break
+ }
+ case 'update': {
+ result = this.update(key, keySalt)
+ break
+ }
+ case 'verify': {
+ result = Promise.resolve(this.verify(seed, mnemonicPhrase))
+ break
+ }
+ default: {
+ throw new Error(`Unknown wallet action '${action}'`)
}
}
- //@ts-expect-error
- BROWSER: postMessage(result, transfer)
- //@ts-expect-error
- NODE: parentPort?.postMessage(result, transfer)
+ return result.then(result => {
+ const transfer = []
+ for (const k of Object.keys(result)) {
+ if (result[k] instanceof ArrayBuffer || result[k] instanceof CryptoKey) {
+ transfer.push(result[k])
+ }
+ }
+ //@ts-expect-error
+ BROWSER: postMessage(result, transfer)
+ //@ts-expect-error
+ NODE: parentPort?.postMessage(result, transfer)
+ })
})
- })
.catch((err: any) => {
console.error(err)
for (const key of Object.keys(message.data)) {
}
static _createAesKey (purpose: 'encrypt' | 'decrypt', keySalt: ArrayBuffer, password?: ArrayBuffer): Promise<CryptoKey | undefined> {
- return new Promise((resolve, reject): void => {
- if (password == null) {
- resolve(undefined)
- return
- }
- try {
- crypto.subtle
- .importKey('raw', password, 'PBKDF2', false, ['deriveKey'])
- .then(derivationKey => {
- new Uint8Array(password).fill(0).buffer.transfer?.()
- const derivationAlgorithm: Pbkdf2Params = {
- name: 'PBKDF2',
- hash: 'SHA-512',
- iterations: 210000,
- salt: keySalt
- }
- const derivedKeyType: AesKeyGenParams = {
- name: 'AES-GCM',
- length: 256
- }
- crypto.subtle
- .deriveKey(derivationAlgorithm, derivationKey, derivedKeyType, false, [purpose])
- .then(resolve)
- })
- } catch (err) {
- reject(err)
- }
- })
+ if (password == null) {
+ return Promise.resolve(undefined)
+ }
+ return crypto.subtle
+ .importKey('raw', password, 'PBKDF2', false, ['deriveKey'])
+ .then(derivationKey => {
+ new Uint8Array(password).fill(0).buffer.transfer?.()
+ const derivationAlgorithm: Pbkdf2Params = {
+ name: 'PBKDF2',
+ hash: 'SHA-512',
+ iterations: 210000,
+ salt: keySalt
+ }
+ const derivedKeyType: AesKeyGenParams = {
+ name: 'AES-GCM',
+ length: 256
+ }
+ return crypto.subtle
+ .deriveKey(derivationAlgorithm, derivationKey, derivedKeyType, false, [purpose])
+ .then(derivedKey => derivedKey)
+ })
+ .catch(err => {
+ throw new Error(err)
+ })
}
static _decryptWallet (type: string, key: CryptoKey, iv: ArrayBuffer, encrypted: ArrayBuffer): Promise<void> {
const seedLength = type === 'BIP-44' ? 64 : 32
const additionalData = utf8.toBytes(type)
- return crypto.subtle.decrypt({ name: 'AES-GCM', iv, additionalData }, key, encrypted)
+ return crypto.subtle
+ .decrypt({ name: 'AES-GCM', iv, additionalData }, key, encrypted)
.then(decrypted => {
this.seed = decrypted.slice(0, seedLength)
this.mnemonic = decrypted.slice(seedLength)
const iv = crypto.getRandomValues(new Uint8Array(12)).buffer
const additionalData = utf8.toBytes(this.type)
const encoded = new Uint8Array([...seed, ...mnemonic])
- return crypto.subtle.encrypt({ name: 'AES-GCM', iv, additionalData }, key, encoded)
+ return crypto.subtle
+ .encrypt({ name: 'AES-GCM', iv, additionalData }, key, encoded)
.then(encrypted => {
encoded.fill(0)
return { iv, encrypted }
return seed.then(seed => {
this.seed = seed
return this._encryptWallet(key)
- .then(({ iv, encrypted }) => {
- return { iv, salt: keySalt, encrypted }
- })
+ .then(({ iv, encrypted }) => ({ iv, salt: keySalt, encrypted }))
})
} catch (err) {
throw new Error('Failed to load wallet', { cause: err })