168 lines
8.1 KiB
Go
168 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
|