keystore

package
v0.0.0-...-753aa41 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 19, 2023 License: LGPL-3.0 Imports: 35 Imported by: 0

Documentation

Overview

Package keystore implements encrypted storage of secp256k1 private keys.

Keys are stored as encrypted JSON files according to the Web3 Secret Storage specification. See https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition for more information.

Index

Constants

View Source
const (

	// StandardScryptN is the N parameter of Scrypt encryption algorithm, using 256MB
	// memory and taking approximately 1s CPU time on a modern processor.
	StandardScryptN = 1 << 18

	// StandardScryptP is the P parameter of Scrypt encryption algorithm, using 256MB
	// memory and taking approximately 1s CPU time on a modern processor.
	StandardScryptP = 1

	// LightScryptN is the N parameter of Scrypt encryption algorithm, using 4MB
	// memory and taking approximately 100ms CPU time on a modern processor.
	LightScryptN = 1 << 12

	// LightScryptP is the P parameter of Scrypt encryption algorithm, using 4MB
	// memory and taking approximately 100ms CPU time on a modern processor.
	LightScryptP = 6
)
View Source
const KeyStoreScheme = "keystore"

KeyStoreScheme is the protocol scheme prefixing account and wallet URLs.

Variables

View Source
var (
	ErrLocked  = NewAuthNeededError("password or unlock")
	ErrNoMatch = errors.New("no key for given address or file")
	ErrDecrypt = errors.New("could not decrypt key with given passphrase")

	// ErrAccountAlreadyExists is returned if an account attempted to import is
	// already present in the keystore.
	ErrAccountAlreadyExists = errors.New("account already exists")
)

ErrLocked ...

View Source
var ErrInvalidPassphrase = errors.New("invalid passphrase")

ErrInvalidPassphrase is returned when a decryption operation receives a bad passphrase.

View Source
var ErrNotSupported = errors.New("not supported")

ErrNotSupported is returned when an operation is requested from an account backend that it does not support.

View Source
var ErrUnknownAccount = errors.New("unknown account")

ErrUnknownAccount is returned for any requested operation for which no backend provides the specified account.

View Source
var ErrUnknownWallet = errors.New("unknown wallet")

ErrUnknownWallet is returned for any requested operation for which no backend provides the specified wallet.

View Source
var ErrWalletAlreadyOpen = errors.New("wallet already open")

ErrWalletAlreadyOpen is returned if a wallet is attempted to be opened the second time.

View Source
var ErrWalletClosed = errors.New("wallet closed")

ErrWalletClosed is returned if a wallet is attempted to be opened the secodn time.

View Source
var KeyStoreType = reflect.TypeOf(&KeyStore{})

KeyStoreType is the reflect type of a keystore backend.

Functions

func DecryptDataV3

func DecryptDataV3(cj CryptoJSON, auth string) ([]byte, error)

DecryptDataV3 ...

func EncryptKey

func EncryptKey(key *Key, auth string, scryptN, scryptP int) ([]byte, error)

EncryptKey encrypts a key using the specified scrypt parameters into a json blob that can be decrypted later on.

func NewAuthNeededError

func NewAuthNeededError(needed string) error

NewAuthNeededError creates a new authentication error with the extra details about the needed fields set.

func TextAndHash

func TextAndHash(data []byte) ([]byte, string)

TextAndHash is a helper function that calculates a hash for the given message that can be safely used to calculate a signature from.

The hash is calulcated as

keccak256("\x19Ethereum Signed Message:\n"${message length}${message}).

This gives context to the signed message and prevents signing of transactions.

func TextHash

func TextHash(data []byte) []byte

TextHash is a helper function that calculates a hash for the given message that can be safely used to calculate a signature from.

The hash is calulcated as

keccak256("\x19Ethereum Signed Message:\n"${message length}${message}).

This gives context to the signed message and prevents signing of transactions.

Types

type Account

type Account struct {
	Address address.Address `json:"address"` // Ethereum account address derived from the key
	URL     URL             `json:"url"`     // Optional resource locator within a backend
}

Account represents an Ethereum account located at a specific location defined by the optional URL field.

func StoreKey

func StoreKey(dir, auth string, scryptN, scryptP int) (Account, error)

StoreKey generates a key, encrypts with 'auth' and stores in the given directory

type AmbiguousAddrError

type AmbiguousAddrError struct {
	Addr    address.Address
	Matches []Account
}

AmbiguousAddrError is returned when attempting to unlock an address for which more than one file exists.

func (*AmbiguousAddrError) Error

func (err *AmbiguousAddrError) Error() string

type AuthNeededError

type AuthNeededError struct {
	Needed string // Extra authentication the user needs to provide
}

AuthNeededError is returned by backends for signing requests where the user is required to provide further authentication before signing can succeed.

This usually means either that a password needs to be supplied, or perhaps a one time PIN code displayed by some hardware device.

func (*AuthNeededError) Error

func (err *AuthNeededError) Error() string

Error implements the standard error interface.

type CryptoJSON

type CryptoJSON struct {
	Cipher       string                 `json:"cipher"`
	CipherText   string                 `json:"ciphertext"`
	CipherParams cipherparamsJSON       `json:"cipherparams"`
	KDF          string                 `json:"kdf"`
	KDFParams    map[string]interface{} `json:"kdfparams"`
	MAC          string                 `json:"mac"`
}

CryptoJSON ...

func EncryptDataV3

func EncryptDataV3(data, auth []byte, scryptN, scryptP int) (CryptoJSON, error)

EncryptDataV3 encrypts the data given as 'data' with the password 'auth'.

type DerivationPath

type DerivationPath []uint32

type Key

type Key struct {
	ID uuid.UUID // Version 4 "random" for unique id not derived from key data
	// to simplify lookups we also store the address
	Address address.Address
	// we only store privkey as pubkey/address can be derived from it
	// privkey in this struct is always in plaintext
	PrivateKey *ecdsa.PrivateKey
}

Key struct represents the account Key

func DecryptKey

func DecryptKey(keyjson []byte, auth string) (*Key, error)

DecryptKey decrypts a key from a json blob, returning the private key itself.

func NewKeyForDirectICAP

func NewKeyForDirectICAP(rand io.Reader) *Key

NewKeyForDirectICAP generates a key whose address fits into < 155 bits so it can fit into the Direct ICAP spec. for simplicity and easier compatibility with other libs, we retry until the first byte is 0.

func (*Key) MarshalJSON

func (k *Key) MarshalJSON() (j []byte, err error)

MarshalJSON will marshal the Key object

func (*Key) UnmarshalJSON

func (k *Key) UnmarshalJSON(j []byte) (err error)

UnmarshalJSON will unmarshal a byte array to the Key object

type KeyStore

type KeyStore struct {
	// contains filtered or unexported fields
}

KeyStore manages a key storage directory on disk.

func ForPath

func ForPath(p string) *KeyStore

ForPath return keystore from path

func NewKeyStore

func NewKeyStore(keydir string, scryptN, scryptP int) *KeyStore

NewKeyStore creates a keystore for the given directory.

func (*KeyStore) Accounts

func (ks *KeyStore) Accounts() []Account

Accounts returns all key files present in the directory.

func (*KeyStore) Delete

func (ks *KeyStore) Delete(a Account, passphrase string) error

Delete deletes the key matched by account if the passphrase is correct. If the account contains no filename, the address must match a unique key.

func (*KeyStore) Export

func (ks *KeyStore) Export(a Account, passphrase, newPassphrase string) (keyJSON []byte, err error)

Export exports as a JSON key, encrypted with newPassphrase.

func (*KeyStore) Find

func (ks *KeyStore) Find(a Account) (Account, error)

Find resolves the given account into a unique entry in the keystore.

func (*KeyStore) GetDecryptedKey

func (ks *KeyStore) GetDecryptedKey(a Account, auth string) (Account, *Key, error)

GetDecryptedKey decrypt and return the key for the account.

func (*KeyStore) HasAddress

func (ks *KeyStore) HasAddress(addr address.Address) bool

HasAddress reports whether a key with the given address is present.

func (*KeyStore) Import

func (ks *KeyStore) Import(keyJSON []byte, passphrase, newPassphrase string) (Account, error)

Import stores the given encrypted JSON key into the key directory.

func (*KeyStore) ImportECDSA

func (ks *KeyStore) ImportECDSA(priv *ecdsa.PrivateKey, passphrase string) (Account, error)

ImportECDSA stores the given key into the key directory, encrypting it with the passphrase.

func (*KeyStore) Lock

func (ks *KeyStore) Lock(addr address.Address) error

Lock removes the private key with the given address from memory.

func (*KeyStore) NewAccount

func (ks *KeyStore) NewAccount(passphrase string) (Account, error)

NewAccount generates a new key and stores it into the key directory, encrypting it with the passphrase.

func (*KeyStore) SignHash

func (ks *KeyStore) SignHash(a Account, hash []byte) ([]byte, error)

SignHash calculates a ECDSA signature for the given hash. The produced signature is in the [R || S || V] format where V is 0 or 1.

func (*KeyStore) SignHashWithPassphrase

func (ks *KeyStore) SignHashWithPassphrase(a Account, passphrase string, hash []byte) (signature []byte, err error)

SignHashWithPassphrase signs hash if the private key matching the given address can be decrypted with the given passphrase. The produced signature is in the [R || S || V] format where V is 0 or 1.

func (*KeyStore) SignTx

func (ks *KeyStore) SignTx(a Account, tx *core.Transaction) (*core.Transaction, error)

SignTx signs the given transaction with the requested account.

func (*KeyStore) SignTxWithPassphrase

func (ks *KeyStore) SignTxWithPassphrase(a Account, passphrase string, tx *core.Transaction) (*core.Transaction, error)

SignTxWithPassphrase signs the transaction if the private key matching the given address can be decrypted with the given passphrase.

func (*KeyStore) Subscribe

func (ks *KeyStore) Subscribe(sink chan<- WalletEvent) event.Subscription

Subscribe implements account.Backend, creating an async subscription to receive notifications on the addition or removal of keystore wallets.

func (*KeyStore) TimedUnlock

func (ks *KeyStore) TimedUnlock(a Account, passphrase string, timeout time.Duration) error

TimedUnlock unlocks the given account with the passphrase. The account stays unlocked for the duration of timeout. A timeout of 0 unlocks the account until the program exits. The account must match a unique key file.

If the account address is already unlocked for a duration, TimedUnlock extends or shortens the active unlock timeout. If the address was previously unlocked indefinitely the timeout is not altered.

func (*KeyStore) Unlock

func (ks *KeyStore) Unlock(a Account, passphrase string) error

Unlock unlocks the given account indefinitely.

func (*KeyStore) Update

func (ks *KeyStore) Update(a Account, passphrase, newPassphrase string) error

Update changes the passphrase of an existing account.

func (*KeyStore) Wallets

func (ks *KeyStore) Wallets() []Wallet

Wallets implements account.Backend, returning all single-key wallets from the keystore directory.

type URL

type URL struct {
	Scheme string // Protocol scheme to identify a capable account backend
	Path   string // Path for the backend to identify a unique entity
}

URL represents the canonical identification URL of a wallet or account.

It is a simplified version of url.URL, with the important limitations (which are considered features here) that it contains value-copyable components only, as well as that it doesn't do any URL encoding/decoding of special characters.

The former is important to allow an account to be copied without leaving live references to the original version, whereas the latter is important to ensure one single canonical form opposed to many allowed ones by the RFC 3986 spec.

As such, these URLs should not be used outside of the scope of an Ethereum wallet or account.

func (URL) Cmp

func (u URL) Cmp(url URL) int

Cmp compares x and y and returns:

-1 if x <  y
 0 if x == y
+1 if x >  y

func (URL) MarshalJSON

func (u URL) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaller interface.

func (URL) String

func (u URL) String() string

String implements the stringer interface.

func (URL) TerminalString

func (u URL) TerminalString() string

TerminalString implements the log.TerminalStringer interface.

func (*URL) UnmarshalJSON

func (u *URL) UnmarshalJSON(input []byte) error

UnmarshalJSON parses url.

type Wallet

type Wallet interface {
	// URL retrieves the canonical path under which this wallet is reachable. It is
	// user by upper layers to define a sorting order over all wallets from multiple
	// backends.
	URL() URL

	// Status returns a textual status to aid the user in the current state of the
	// wallet. It also returns an error indicating any failure the wallet might have
	// encountered.
	Status() (string, error)

	// Open initializes access to a wallet instance. It is not meant to unlock or
	// decrypt account keys, rather simply to establish a connection to hardware
	// wallets and/or to access derivation seeds.
	//
	// The passphrase parameter may or may not be used by the implementation of a
	// particular wallet instance. The reason there is no passwordless open method
	// is to strive towards a uniform wallet handling, oblivious to the different
	// backend providers.
	//
	// Please note, if you open a wallet, you must close it to release any allocated
	// resources (especially important when working with hardware wallets).
	Open(passphrase string) error

	// Close releases any resources held by an open wallet instance.
	Close() error

	// Accounts retrieves the list of signing accounts the wallet is currently aware
	// of. For hierarchical deterministic wallets, the list will not be exhaustive,
	// rather only contain the accounts explicitly pinned during account derivation.
	Accounts() []Account

	// Contains returns whether an account is part of this particular wallet or not.
	Contains(account Account) bool

	// Derive attempts to explicitly derive a hierarchical deterministic account at
	// the specified derivation path. If requested, the derived account will be added
	// to the wallet's tracked account list.
	Derive(path DerivationPath, pin bool) (Account, error)

	// SignData requests the wallet to sign the hash of the given data
	// It looks up the account specified either solely via its address contained within,
	// or optionally with the aid of any location metadata from the embedded URL field.
	//
	// If the wallet requires additional authentication to sign the request (e.g.
	// a password to decrypt the account, or a PIN code o verify the transaction),
	// an AuthNeededError instance will be returned, containing infos for the user
	// about which fields or actions are needed. The user may retry by providing
	// the needed details via SignDataWithPassphrase, or by other means (e.g. unlock
	// the account in a keystore).
	SignData(account Account, mimeType string, data []byte) ([]byte, error)

	// SignDataWithPassphrase is identical to SignData, but also takes a password
	// NOTE: there's an chance that an erroneous call might mistake the two strings, and
	// supply password in the mimetype field, or vice versa. Thus, an implementation
	// should never echo the mimetype or return the mimetype in the error-response
	SignDataWithPassphrase(account Account, passphrase, mimeType string, data []byte) ([]byte, error)

	// SignText requests the wallet to sign the hash of a given piece of data, prefixed
	// by the Ethereum prefix scheme
	// It looks up the account specified either solely via its address contained within,
	// or optionally with the aid of any location metadata from the embedded URL field.
	//
	// If the wallet requires additional authentication to sign the request (e.g.
	// a password to decrypt the account, or a PIN code o verify the transaction),
	// an AuthNeededError instance will be returned, containing infos for the user
	// about which fields or actions are needed. The user may retry by providing
	// the needed details via SignHashWithPassphrase, or by other means (e.g. unlock
	// the account in a keystore).
	SignText(account Account, text []byte) ([]byte, error)

	// SignTextWithPassphrase is identical to Signtext, but also takes a password
	SignTextWithPassphrase(account Account, passphrase string, hash []byte) ([]byte, error)

	// SignTx requests the wallet to sign the given transaction.
	//
	// It looks up the account specified either solely via its address contained within,
	// or optionally with the aid of any location metadata from the embedded URL field.
	//
	// If the wallet requires additional authentication to sign the request (e.g.
	// a password to decrypt the account, or a PIN code to verify the transaction),
	// an AuthNeededError instance will be returned, containing infos for the user
	// about which fields or actions are needed. The user may retry by providing
	// the needed details via SignTxWithPassphrase, or by other means (e.g. unlock
	// the account in a keystore).
	SignTx(account Account, tx *core.Transaction) (*core.Transaction, error)

	// SignTxWithPassphrase is identical to SignTx, but also takes a password
	SignTxWithPassphrase(account Account, passphrase string, tx *core.Transaction) (*core.Transaction, error)
}

Wallet represents a software or hardware wallet that might contain one or more accounts (derived from the same seed).

type WalletEvent

type WalletEvent struct {
	Wallet Wallet          // Wallet instance arrived or departed
	Kind   WalletEventType // Event type that happened in the system
}

departure is detected.

type WalletEventType

type WalletEventType int

WalletEventType represents the different event types that can be fired by the wallet subscription subsystem.

const (
	// WalletArrived is fired when a new wallet is detected either via USB or via
	// a filesystem event in the keystore.
	WalletArrived WalletEventType = iota

	// WalletOpened is fired when a wallet is successfully opened with the purpose
	// of starting any background processes such as automatic key derivation.
	WalletOpened

	// WalletDropped ...
	WalletDropped
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL