-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into db/feat/automate-typedoc-link-regeneration
- Loading branch information
Showing
28 changed files
with
11,988 additions
and
5,358 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@fuel-ts/wallet": minor | ||
--- | ||
|
||
support encrypt and decrypt json wallets |
38 changes: 38 additions & 0 deletions
38
apps/docs-snippets/src/guide/wallets/encrypting-and-decrypting-json-wallets.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { Wallet } from 'fuels'; | ||
|
||
describe(__filename, () => { | ||
it('should successfully encrypt wallet', async () => { | ||
// #region encrypting-and-decrypting-json-wallets-1 | ||
// #context import fs from 'fs'; | ||
// #context import { Wallet } from 'fuels'; | ||
|
||
const wallet = Wallet.generate(); | ||
|
||
const password = 'my-password'; | ||
|
||
const jsonWallet = await wallet.encrypt(password); | ||
|
||
// #context fs.writeFileSync('secure-path/my-wallet.json', jsonWallet); | ||
// #endregion encrypting-and-decrypting-json-wallets-1 | ||
|
||
expect(jsonWallet).toBeDefined(); | ||
}); | ||
|
||
it('should successfully decrypt a wallet', async () => { | ||
const jsonWallet = await Wallet.generate().encrypt('my-password'); | ||
// #region encrypting-and-decrypting-json-wallets-2 | ||
// #context import fs from 'fs'; | ||
// #context import { Wallet } from 'fuels'; | ||
|
||
// #context const jsonWallet = fs.readFileSync('secure-path/my-wallet.json', 'utf-8'); | ||
|
||
const password = 'my-password'; | ||
|
||
const decryptedWallet = await Wallet.fromEncryptedJson(jsonWallet, password); | ||
|
||
const myBalance = await decryptedWallet.getBalance(); | ||
// #endregion encrypting-and-decrypting-json-wallets-2 | ||
|
||
expect(myBalance).toBeDefined(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
apps/docs/src/guide/wallets/encrypting-and-decrypting-json-wallets.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Encrypting and Decrypting JSON Wallet | ||
|
||
JSON wallets are a standardized way of storing wallets securely. They follow a specific schema and are encrypted using a password. This makes it easier to manage multiple wallets and securely store them on disk. This guide will take you through the process of encrypting and decrypting JSON wallets using the Typescript SDK. | ||
|
||
## Encrypting a Wallet | ||
|
||
We will be calling `encrypt` from the `WalletUnlocked` instance which will take a password as the argument. It will encrypt the private key using a cipher and returns the JSON keystore wallet. You can then securely store this JSON wallet. | ||
|
||
Here is an example of how you can accomplish this: | ||
|
||
<<< @/../../docs-snippets/src/guide/wallets/encrypting-and-decrypting-json-wallets.test.ts#encrypting-and-decrypting-json-wallets-1{ts:line-numbers} | ||
|
||
Please note that `encrypt` must be called within an instance of `WalletUnlocked`. This instance can only be achieved through passing a private key or mnemonic phrase to a locked wallet. | ||
|
||
## Decrypting a Wallet | ||
|
||
To decrypt the JSON wallet and retrieve your private key, you can call `fromEncryptedJson` on a `Wallet` instance. It takes the encrypted JSON wallet and the password as its arguments, and returns the decrypted wallet. | ||
|
||
Here is an example: | ||
|
||
<<< @/../../docs-snippets/src/guide/wallets/encrypting-and-decrypting-json-wallets.test.ts#encrypting-and-decrypting-json-wallets-2{ts:line-numbers} | ||
|
||
In this example, `decryptedWallet` is an instance of `WalletUnlocked` class, now available for use. | ||
|
||
## Important | ||
|
||
Remember to securely store your encrypted JSON wallet and password. If you lose them, there will be no way to recover your wallet. For security reasons, avoid sharing your private key, encrypted JSON wallet or password with anyone. |
19 changes: 0 additions & 19 deletions
19
apps/docs/src/guide/wallets/encrypting-and-storing-wallets.md
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import type { CryptoApi } from '../types'; | ||
|
||
import { crypto } from './crypto'; | ||
|
||
export const encryptJsonWalletData: CryptoApi['encryptJsonWalletData'] = async ( | ||
data: Uint8Array, | ||
key: Uint8Array, | ||
iv: Uint8Array | ||
): Promise<Uint8Array> => { | ||
const subtle = crypto.subtle; | ||
const keyBuffer = new Uint8Array(key.subarray(0, 16)); | ||
const ivBuffer = iv; | ||
const dataBuffer = data; | ||
|
||
const cryptoKey = await subtle.importKey( | ||
'raw', | ||
keyBuffer, | ||
{ name: 'AES-CTR', length: 128 }, | ||
false, | ||
['encrypt', 'decrypt'] | ||
); | ||
|
||
const encrypted = (await subtle.encrypt( | ||
{ name: 'AES-CTR', counter: ivBuffer, length: 128 }, | ||
cryptoKey, | ||
dataBuffer | ||
)) as ArrayBuffer; | ||
|
||
return new Uint8Array(encrypted); | ||
}; | ||
|
||
export const decryptJsonWalletData: CryptoApi['decryptJsonWalletData'] = async ( | ||
data: Uint8Array, | ||
key: Uint8Array, | ||
iv: Uint8Array | ||
): Promise<Uint8Array> => { | ||
const subtle = crypto.subtle; | ||
const keyBuffer = new Uint8Array(key.subarray(0, 16)).buffer; | ||
const ivBuffer = new Uint8Array(iv).buffer; | ||
const dataBuffer = new Uint8Array(data).buffer; | ||
|
||
const cryptoKey = await subtle.importKey( | ||
'raw', | ||
keyBuffer, | ||
{ name: 'AES-CTR', length: 128 }, | ||
false, | ||
['encrypt', 'decrypt'] | ||
); | ||
|
||
const decrypted = (await subtle.decrypt( | ||
{ name: 'AES-CTR', counter: ivBuffer, length: 128 }, | ||
cryptoKey, | ||
dataBuffer | ||
)) as ArrayBuffer; | ||
|
||
return new Uint8Array(decrypted); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import crypto from 'crypto'; | ||
|
||
export async function encryptJsonWalletData(data: Uint8Array, key: Uint8Array, iv: Uint8Array) { | ||
const cipher = await crypto.createCipheriv('aes-128-ctr', key.subarray(0, 16), iv); | ||
|
||
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]); | ||
|
||
return new Uint8Array(encrypted); | ||
} | ||
|
||
export async function decryptJsonWalletData(data: Uint8Array, key: Uint8Array, iv: Uint8Array) { | ||
const decipher = crypto.createDecipheriv('aes-128-ctr', key.subarray(0, 16), iv); | ||
|
||
const decrypted = await Buffer.concat([decipher.update(data), decipher.final()]); | ||
|
||
return new Uint8Array(decrypted); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './scrypt'; | ||
export * from './keccak256'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import * as ethereumCryptography from 'ethereum-cryptography/keccak'; | ||
|
||
import { bufferFromString } from '..'; | ||
|
||
import { keccak256 } from './keccak256'; | ||
|
||
describe('keccak256', () => { | ||
afterEach(jest.restoreAllMocks); | ||
|
||
it('hashes using keccak256', () => { | ||
const data = bufferFromString('hashedKey'); | ||
|
||
const mock = jest.spyOn(ethereumCryptography, 'keccak256').mockImplementationOnce(() => data); | ||
|
||
const hashedKey = keccak256(data); | ||
|
||
expect(mock).toBeCalledTimes(1); | ||
expect(hashedKey).toEqual(data); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { keccak256 as keccak } from 'ethereum-cryptography/keccak'; | ||
|
||
export const keccak256 = (data: Uint8Array): Uint8Array => keccak(data); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import * as ethereumCryptography from 'ethereum-cryptography/scrypt'; | ||
|
||
import { bufferFromString } from '..'; | ||
import type { IScryptParams } from '../types'; | ||
|
||
import { scrypt } from './scrypt'; | ||
|
||
describe('scrypt', () => { | ||
afterEach(jest.restoreAllMocks); | ||
|
||
it('hashes using scrypt', () => { | ||
const mockedHashedKey = bufferFromString('hashedKey'); | ||
|
||
const mock = jest | ||
.spyOn(ethereumCryptography, 'scryptSync') | ||
.mockImplementationOnce(() => mockedHashedKey); | ||
|
||
const password = bufferFromString('password'); | ||
const salt = bufferFromString('salt'); | ||
|
||
const params: IScryptParams = { | ||
dklen: 32, | ||
n: 2, | ||
p: 4, | ||
password, | ||
r: 2, | ||
salt, | ||
}; | ||
|
||
const hashedKey = scrypt(params); | ||
|
||
expect(mock).toBeCalledTimes(1); | ||
expect(hashedKey).toEqual(mockedHashedKey); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { scryptSync as ethCryScrypt } from 'ethereum-cryptography/scrypt'; | ||
|
||
import type { IScryptParams } from '../types'; | ||
|
||
export const scrypt = (params: IScryptParams): Uint8Array => { | ||
const { password, salt, n, p, r, dklen } = params; | ||
|
||
const derivedKey = ethCryScrypt(password, salt, n, r, p, dklen); | ||
|
||
return derivedKey; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { envs } from './envs'; | ||
|
||
describe('encryptJsonWalletData', () => { | ||
it.each(envs)( | ||
'should encrypt and decrypt json wallet data correctly in %s environment', | ||
async ({ encryptJsonWalletData, decryptJsonWalletData, randomBytes }) => { | ||
const testData = new Uint8Array([104, 101, 108, 108, 111]); | ||
const testKey = randomBytes(16); | ||
const testIv = randomBytes(16); | ||
|
||
const encryptedData = await encryptJsonWalletData(testData, testKey, testIv); | ||
expect(encryptedData).not.toEqual(testData); // ensure data was encrypted | ||
|
||
const decryptedData = await decryptJsonWalletData(encryptedData, testKey, testIv); | ||
expect(decryptedData).toEqual(testData); // ensure data was decrypted correctly | ||
} | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.