Skip to content

[BC/CWC] Wallet private key updates [1]#4068

Open
MichaelAJay wants to merge 36 commits intobitpay:masterfrom
MichaelAJay:wallet-privatekey-ref
Open

[BC/CWC] Wallet private key updates [1]#4068
MichaelAJay wants to merge 36 commits intobitpay:masterfrom
MichaelAJay:wallet-privatekey-ref

Conversation

@MichaelAJay
Copy link
Contributor

@MichaelAJay MichaelAJay commented Dec 12, 2025

bitcore-client

Encryption

  • adds encryptBuffer - enables normalized buffer input
  • adds decryptToBuffer - enables improved security by not decrypting directly to string

Storage

  • adds addKeysSafe - incoming keys' private key is encrypted, so not immediately available to be used to retrieve pubkey, which should be available anyway. Throws if missing a pubkey

Wallet

  • Adds version: 2 & version checks for backwards compatibility (note: to create an old Wallet would require version: 0 - so 1 is skipped - looking for feedback on numbering/versioning).
  • create encrypts HDPrivateKey xprivkey and privateKey so they can be decrypted as buffers instead of serializing the whole masterKey and THEN encrypting
  • importKeys does the same for signing keys
  • signTx decrypts to buffers then uses deriver for chain-aware decoding. In the next phase, this decoding should be made unnecessary by passing the buffer all the way through to use, if possible

Tests

  • update prior tests to include versioning
  • introduce new tests for version 2 specifics

crypto-wallet-core

Derivation

  • Add two passthrough methods on DeriverProxy to buffer & serialize private keys
  • Adds privateKeyToBuffer and privateKeyBufferToNativePrivateKey to IDeriver & implement for each Deriver - no need to override for any of the extending classes (UTXOs to AbstractBitcoreLibDeriver & EVM to EthDeriver)

@kajoseph kajoseph added CWC This pull request modifies the crypto-wallet-core package BCC This pull request modifies the bitcore-client package labels Dec 30, 2025
@MichaelAJay MichaelAJay changed the title Draft: [BC/CWC] Wallet private key updates [1] [BC/CWC] Wallet private key updates [1] Jan 6, 2026
Copy link
Collaborator

@kajoseph kajoseph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a better approach may be to auto migrate wallets with version < 2 to v2. That way we can avoid carve-outs while actively push better security.

loadWallet() {
  const wallet = read wallet file;
  if (wallet.version < 2) {
    convert to v2 wallet;
    backup wallet file to .bak;
    overwrite wallet file with v2;
  }
}

@kajoseph kajoseph added the bitcore-lib This pull request modifies the bitcore-lib package label Feb 4, 2026
const decrypted = decipher.update(encHex, 'hex');
const final = decipher.final();
try {
return Buffer.concat([decrypted, final]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include the decipher.final() in the try.

try {
  return Buffer.concat([decrypted, decipher.final()]);

const final = decipher.final();
const output = Buffer.concat([payload, final]);
try {
return toBuffer ? output : output.toString('hex');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

include decipher.final() in the try.

let final;
try {
  final = decipher.final();
  const output = Buffer.concat([payload, final]);
  return toBuffer ? output : output.toString('hex');
} finally {
  payload.fill(0);
  final?.fill(0);
}

Not sure if defining final outside the try is necessary. If this code is going to error, it's highly likely that it's due to an invalid checksum/tag in the decipher.final() call, so it may be fine to just do Buffer.concat([payload, decipher.final()]);. Whatever is decided also applies to the other encrypt/decrypt buffer methods.

Copy link
Collaborator

@kajoseph kajoseph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functionally, this seems to work well. Nice job!

In addition to the minor comments below, we should add test cases for the migration as well as tests for critical functions with the new version wallets (i.e. deriving, sending, sign message)

}

async migrateWallet(encryptionKey: Buffer): Promise<Wallet> {
/**
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should log that a migration is taking place. E.g. "Migrating wallet from version x to version y"

throw new Error('Migration failed - wallet not found');
}

await writeFile(`${this.name}.bak`, rawWallet, 'utf8')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should write to an expected directory instead of just dumping in the cwd. e.g. ~/.bitcore/bitcoreWallets/backup/ (next to where the text wallet files are saved)

throw new Error('Migration failure: wallet not successfully saved. Use backups to restore prior wallet and keys');
});

return this;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log migration successful

}

/**
* 1: Wallet to .bak
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log that a pre-migration wallet backup is being written to <file>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BCC This pull request modifies the bitcore-client package bitcore-lib This pull request modifies the bitcore-lib package CWC This pull request modifies the crypto-wallet-core package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants