d0938d817f
This commit implements a new secure, scalable, hierarchical deterministic wallet address manager package. The following is an overview of features: - BIP0032 hierarchical deterministic keys - BIP0043/BIP0044 multi-account hierarchy - Strong focus on security: - Fully encrypted database including public information such as addresses as well as private information such as private keys and scripts needed to redeem pay-to-script-hash transactions - Hardened against memory scraping through the use of actively clearing private material from memory when locked - Different crypto keys used for public, private, and script data - Ability for different passphrases for public and private data - Scrypt-based key derivation - NaCl-based secretbox cryptography (XSalsa20 and Poly1305) - Multi-tier scalable key design to allow instant password changes regardless of the number of addresses stored - Import WIF keys - Import pay-to-script-hash scripts for things such as multi-signature transactions - Ability to export a watching-only version which does not contain any private key material - Programmatically detectable errors, including encapsulation of errors from packages it relies on - Address synchronization capabilities This commit only provides the implementation package. It does not include integration into to the existing wallet code base or conversion of existing addresses. That functionality will be provided by future commits.
167 lines
8.1 KiB
Go
167 lines
8.1 KiB
Go
/*
|
|
* Copyright (c) 2014 Conformal Systems LLC <info@conformal.com>
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
/*
|
|
Package waddrmgr provides a secure hierarchical deterministic wallet address
|
|
manager.
|
|
|
|
Overview
|
|
|
|
One of the fundamental jobs of a wallet is to manage addresses, private keys,
|
|
and script data associated with them. At a high level, this package provides
|
|
the facilities to perform this task with a focus on security and also allows
|
|
recovery through the use of hierarchical deterministic keys (BIP0032) generated
|
|
from a caller provided seed. The specific structure used is as described in
|
|
BIP0044. This setup means as long as the user writes the seed down (even better
|
|
is to use a mnemonic for the seed), all their addresses and private keys can be
|
|
regenerated from the seed.
|
|
|
|
There are two master keys which are protected by two independent passphrases.
|
|
One is intended for public facing data, while the other is intended for private
|
|
data. The public password can be hardcoded for callers who don't want the
|
|
additional public data protection or the same password can be used if a single
|
|
password is desired. These choices provide a usability versus security
|
|
tradeoff. However, keep in mind that extended hd keys, as called out in BIP0032
|
|
need to be handled more carefully than normal EC public keys because they can be
|
|
used to generate all future addresses. While this is part of what makes them
|
|
attractive, it also means an attacker getting access to your extended public key
|
|
for an account will allow them to know all addresses you will use and hence
|
|
reduces privacy. For this reason, it is highly recommended that you do not hard
|
|
code a password which allows any attacker who gets a copy of your address
|
|
manager database to access your effectively plain text extended public keys.
|
|
|
|
Each master key in turn protects the three real encryption keys (called crypto
|
|
keys) for public, private, and script data. Some examples include payment
|
|
addresses, extended hd keys, and scripts associated with pay-to-script-hash
|
|
addresses. This scheme makes changing passphrases more efficient since only the
|
|
crypto keys need to be re-encrypted versus every single piece of information
|
|
(which is what is needed for *rekeying*). This results in a fully encrypted
|
|
database where access to it does not compromise address, key, or script privacy.
|
|
This differs from the handling by other wallets at the time of this writing in
|
|
that they divulge your addresses, and worse, some even expose the chain code
|
|
which can be used by the attacker to know all future addresses that will be
|
|
used.
|
|
|
|
The address manager is also hardened against memory scrapers. This is
|
|
accomplished by typically having the address manager locked meaning no private
|
|
keys or scripts are in memory. Unlocking the address manager causes the crypto
|
|
private and script keys to be decrypted and loaded in memory which in turn are
|
|
used to decrypt private keys and scripts on demand. Relocking the address
|
|
manager actively zeros all private material from memory. In addition, temp
|
|
private key material used internally is zeroed as soon as it's used.
|
|
|
|
Locking and Unlocking
|
|
|
|
As previously mentioned, this package provide facilities for locking and
|
|
unlocking the address manager to protect access to private material and remove
|
|
it from memory when locked. The Lock, Unlock, and IsLocked functions are used
|
|
for this purpose.
|
|
|
|
Creating a New Address Manager
|
|
|
|
A new address manager is created via the Create function. This function accepts
|
|
the path to a database file to create, passphrases, network, and perhaps most
|
|
importantly, a cryptographically random seed which is used to generate the
|
|
master node of the hierarchical deterministic keychain which allows all
|
|
addresses and private keys to be recovered with only the seed. The GenerateSeed
|
|
function in the hdkeychain package can be used as a convenient way to create a
|
|
random seed for use with this function. The address manager is locked
|
|
immediately upon being created.
|
|
|
|
Opening an Existing Address Manager
|
|
|
|
An existing address manager is opened via the Open function. This function
|
|
accepts the path to the existing database file, the public passphrase, and
|
|
network. The address manager is opened locked as expected since the open
|
|
function does not take the private passphrase to unlock it.
|
|
|
|
Closing the Address Manager
|
|
|
|
The Close method should be called on the address manager when the caller is done
|
|
with it. While it is not required, it is recommended because it sanely shuts
|
|
down the database and ensures all private and public key material is purged from
|
|
memory.
|
|
|
|
Managed Addresses
|
|
|
|
Each address returned by the address manager satisifies the ManagedAddress
|
|
interface as well as either the ManagedPubKeyAddress or ManagedScriptAddress
|
|
interfaces. These interfaces provide the means to obtain relevant information
|
|
about the addresses such as their private keys and scripts.
|
|
|
|
Chained Addresses
|
|
|
|
Most callers will make use of the chained addresses for normal operations.
|
|
Internal addresses are intended for internal wallet uses such as change outputs,
|
|
while external addresses are intended for uses such payment addresses that are
|
|
shared. The NextInternalAddresses and NextExternalAddresses functions provide
|
|
the means to acquire one or more of the next addresses that have not already
|
|
been provided. In addition, the LastInternalAddress and LastExternalAddress
|
|
functions can be used to get the most recently provided internal and external
|
|
address, respectively.
|
|
|
|
Requesting Existing Addresses
|
|
|
|
In addition to generating new addresses, access to old addresses is often
|
|
required. Most notably, to sign transactions in order to redeem them. The
|
|
Address function provides this capability and returns a ManagedAddress
|
|
|
|
Importing Addresses
|
|
|
|
While the recommended approach is to use the chained addresses discussed above
|
|
because they can be deterministically regenerated to avoid losing funds as long
|
|
as the user has the master seed, there are many addresses that already exist,
|
|
and as a result, this package provides the ability to import existing private
|
|
keys in Wallet Import Format (WIF) and hence the associated public key and
|
|
address.
|
|
|
|
Importing Scripts
|
|
|
|
In order to support pay-to-script-hash transactions, the script must be securely
|
|
stored as it is needed to redeem the transaction. This can be useful for a
|
|
variety of scenarios, however the most common use is currently multi-signature
|
|
transactions.
|
|
|
|
Syncing
|
|
|
|
The address manager also supports storing and retrieving a block hash and height
|
|
which the manager is known to have all addresses synced through. The manager
|
|
itself does not have any notion of which addresses are synced or not. It only
|
|
provides the storage as a convenience for the caller.
|
|
|
|
Network
|
|
|
|
The address manager must be associated with a given network in order to provide
|
|
appropriate addresses and reject imported addresses and scripts which don't
|
|
apply to the associated network.
|
|
|
|
Errors
|
|
|
|
All errors returned from this package are of type waddrmgr.ManagerError. This
|
|
allows the caller to programmatically ascertain the specific reasons for failure
|
|
by examining the ErrorCode field of the type asserted ManagerError. For certain
|
|
error codes, as documented the specific error codes, the underlying error will
|
|
be contained in the Err field.
|
|
|
|
Bitcoin Improvement Proposals
|
|
|
|
This package includes concepts outlined by the following BIPs:
|
|
|
|
BIP0032 (https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
|
|
BIP0043 (https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki)
|
|
BIP0044 (https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
|
|
*/
|
|
package waddrmgr
|