Skip to content

Commit

Permalink
feat(ironfish): Add encrypt method for account (#5247)
Browse files Browse the repository at this point in the history
* feat(ironfish): Add `encrypt` method for account

* fix(ironfish): Remove extra KEY_LENGTH constant

* test(ironfish): Fix serialization test

* test(ironfish): Update fixture

* feat(ironfish): Fix encrypt test for account
  • Loading branch information
rohanjadvani committed Aug 13, 2024
1 parent 468859a commit e734cc5
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 30 deletions.
31 changes: 31 additions & 0 deletions ironfish/src/wallet/account/__fixtures__/account.test.ts.fixture
Original file line number Diff line number Diff line change
Expand Up @@ -5810,5 +5810,36 @@
}
]
}
],
"Accounts encrypt returns an encrypted account that can be decrypted into the original account": [
{
"value": {
"encrypted": false,
"version": 4,
"id": "1bbc8bfa-2393-41fd-b1ad-a3ca03aee8ac",
"name": "test",
"spendingKey": "6a0ae63bd630bb5b205737f49cb0778a872fab11f7e797935adbb9716917c612",
"viewKey": "0c1888cfbe1d0f02c3069df3350665c86d2f56cfc64242d53c43925d09e1012c3f0cf9098c9a9fb7f826509d15d7140eb6d76ccfcb2fff81a3dacd382cf7fe00",
"incomingViewKey": "781829745831663347945ff2ac60e0c6181ffa8d73d9bcc4f5fd24a40f1dcd06",
"outgoingViewKey": "1b3ace62d49d5c0c55773264e78aeb6125b451595cf33f8033dcce01d9507d2a",
"publicAddress": "a634ebb5367d5ef7196b7226a7cf6583980b689992c2f595febc4648d2ee7449",
"createdAt": {
"hash": {
"type": "Buffer",
"data": "base64:R5HXrp+X3xAO8VWOhHctagm0N2I4goP3XG8goyqIqoY="
},
"sequence": 1
},
"scanningEnabled": true,
"proofAuthorizingKey": "cc1913dba277eb64857337a5144a5c2f7f4ebc4af1915b667aa1a46b3e49fe07"
},
"head": {
"hash": {
"type": "Buffer",
"data": "base64:R5HXrp+X3xAO8VWOhHctagm0N2I4goP3XG8goyqIqoY="
},
"sequence": 1
}
}
]
}
13 changes: 13 additions & 0 deletions ironfish/src/wallet/account/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2596,4 +2596,17 @@ describe('Accounts', () => {
expect(accountTransactionHashes).toEqual(blockTransactionHashes)
})
})

describe('encrypt', () => {
it('returns an encrypted account that can be decrypted into the original account', async () => {
const { node } = nodeTest
const account = await useAccountFixture(node.wallet)
const passphrase = 'foo'

const encryptedAccount = account.encrypt(passphrase)
const decryptedAccount = encryptedAccount.decrypt(passphrase)

expect(account.serialize()).toMatchObject(decryptedAccount.serialize())
})
})
})
16 changes: 14 additions & 2 deletions ironfish/src/wallet/account/account.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { multisig } from '@ironfish/rust-nodejs'
import { encrypt, multisig } from '@ironfish/rust-nodejs'
import { Asset } from '@ironfish/rust-nodejs'
import { BufferMap, BufferSet } from 'buffer-map'
import MurmurHash3 from 'imurmurhash'
Expand All @@ -15,14 +15,15 @@ import { WithNonNull, WithRequired } from '../../utils'
import { DecryptedNote } from '../../workerPool/tasks/decryptNotes'
import { AssetBalances } from '../assetBalances'
import { MultisigKeys, MultisigSigner } from '../interfaces/multisigKeys'
import { DecryptedAccountValue } from '../walletdb/accountValue'
import { AccountValueEncoding, DecryptedAccountValue } from '../walletdb/accountValue'
import { AssetValue } from '../walletdb/assetValue'
import { BalanceValue } from '../walletdb/balanceValue'
import { DecryptedNoteValue } from '../walletdb/decryptedNoteValue'
import { HeadValue } from '../walletdb/headValue'
import { isSignerMultisig } from '../walletdb/multisigKeys'
import { TransactionValue } from '../walletdb/transactionValue'
import { WalletDB } from '../walletdb/walletdb'
import { EncryptedAccount } from './encryptedAccount'

export const ACCOUNT_KEY_LENGTH = 32

Expand Down Expand Up @@ -1289,6 +1290,17 @@ export class Account {
const publicKeyPackage = new multisig.PublicKeyPackage(this.multisigKeys.publicKeyPackage)
return publicKeyPackage.identities()
}

encrypt(passphrase: string): EncryptedAccount {
const encoder = new AccountValueEncoding()
const serialized = encoder.serialize(this.serialize())
const data = encrypt(serialized, passphrase)

return new EncryptedAccount({
data,
walletDb: this.walletDb,
})
}
}

export function calculateAccountPrefix(id: string): Buffer {
Expand Down
26 changes: 4 additions & 22 deletions ironfish/src/wallet/account/encryptedAccount.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { encrypt } from '@ironfish/rust-nodejs'
import { useAccountFixture } from '../../testUtilities/fixtures/account'
import { createNodeTest } from '../../testUtilities/nodeTest'
import { AccountDecryptionFailedError } from '../errors'
import { AccountValueEncoding } from '../walletdb/accountValue'
import { EncryptedAccount } from './encryptedAccount'

describe('EncryptedAccount', () => {
const nodeTest = createNodeTest()
Expand All @@ -16,18 +13,10 @@ describe('EncryptedAccount', () => {
const { node } = nodeTest
const account = await useAccountFixture(node.wallet)

const encoder = new AccountValueEncoding()
const data = encoder.serialize(account.serialize())

const encryptedData = encrypt(data, passphrase)
const encryptedAccount = new EncryptedAccount({
data: encryptedData,
walletDb: node.wallet.walletDb,
})

const encryptedAccount = account.encrypt(passphrase)
const decryptedAccount = encryptedAccount.decrypt(passphrase)
const decryptedData = encoder.serialize(decryptedAccount.serialize())
expect(data.toString('hex')).toEqual(decryptedData.toString('hex'))

expect(account.serialize()).toMatchObject(decryptedAccount.serialize())
})

it('throws an error when an invalid passphrase is used', async () => {
Expand All @@ -36,14 +25,7 @@ describe('EncryptedAccount', () => {
const { node } = nodeTest
const account = await useAccountFixture(node.wallet)

const encoder = new AccountValueEncoding()
const data = encoder.serialize(account.serialize())

const encryptedData = encrypt(data, passphrase)
const encryptedAccount = new EncryptedAccount({
data: encryptedData,
walletDb: node.wallet.walletDb,
})
const encryptedAccount = account.encrypt(passphrase)

expect(() => encryptedAccount.decrypt(invalidPassphrase)).toThrow(
AccountDecryptionFailedError,
Expand Down
4 changes: 2 additions & 2 deletions ironfish/src/wallet/exporter/encoders/bech32.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { PUBLIC_ADDRESS_LENGTH } from '@ironfish/rust-nodejs'
import { KEY_LENGTH, PUBLIC_ADDRESS_LENGTH } from '@ironfish/rust-nodejs'
import bufio, { EncodingError } from 'bufio'
import { Bech32m } from '../../../utils'
import { ACCOUNT_SCHEMA_VERSION } from '../../account/account'
import { KEY_LENGTH, VIEW_KEY_LENGTH } from '../../walletdb/accountValue'
import { VIEW_KEY_LENGTH } from '../../walletdb/accountValue'
import { AccountImport } from '../accountImport'
import { AccountDecodingOptions, AccountEncoder, DecodeFailed, DecodeInvalid } from '../encoder'
import { MultisigKeysEncoding } from './multisigKeys'
Expand Down
6 changes: 2 additions & 4 deletions ironfish/src/wallet/walletdb/accountValue.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { PUBLIC_ADDRESS_LENGTH } from '@ironfish/rust-nodejs'
import { KEY_LENGTH, PUBLIC_ADDRESS_LENGTH } from '@ironfish/rust-nodejs'
import bufio from 'bufio'
import { IDatabaseEncoding } from '../../storage'
import { ACCOUNT_KEY_LENGTH } from '../account/account'
import { MultisigKeys } from '../interfaces/multisigKeys'
import { HeadValue, NullableHeadValueEncoding } from './headValue'
import { MultisigKeysEncoding } from './multisigKeys'

export const KEY_LENGTH = ACCOUNT_KEY_LENGTH
export const VIEW_KEY_LENGTH = 64
const VERSION_LENGTH = 2

Expand All @@ -18,7 +16,7 @@ export interface EncryptedAccountValue {
data: Buffer
}

export interface DecryptedAccountValue {
export type DecryptedAccountValue = {
encrypted: false
version: number
id: string
Expand Down

0 comments on commit e734cc5

Please sign in to comment.