Keystore

class Keystore()

A Keystore holds an encrypted key pair (an Address and its private key) and is the preferred way to pass addresses and private keys through DCP APIs. Keystores are stored on disk as passphrase-protected Keystore Files, and are the objects returned by wallet.get()/load().

Keystore is an EventEmitter; see Events below for the events it emits.

IdKeystore, AuthKeystore, and BankAccountKeystore are subclasses of Keystore used to represent different kinds of addresses – see Subclasses below. They share this exact constructor and method set.

Constructor

The constructor is async, and always returns a Promise which resolves with a locked Keystore whose address is known. Any form may trigger exports.passphrasePrompt to solicit a passphrase from the user.

Form 1

new Keystore();

Generates a random private key and prompts the user for a passphrase to encrypt it with.

Form 2

new Keystore(privateKey);

Arguments:

  • privateKey (string|object) - A private key, in hex string format or anything else accepted by the PrivateKey constructor.

Uses the given private key, prompting the user for a passphrase to encrypt it with.

Form 3

new Keystore(privateKey, passphrase);

Arguments:

  • privateKey (string|object) - As in Form 2.

  • passphrase (string|false) - Passphrase to encrypt the private key with. Pass false to use the empty passphrase.

Uses the given private key, encrypted with the given passphrase.

Form 4

new Keystore(foreignKeystoreObject, passphrase);

Arguments:

  • foreignKeystoreObject (object) - A keystore object from a third party, such as MyEtherWallet, geth, or Web3.

  • passphrase (string) - Optional. If omitted, the empty passphrase is tried first, then the user is prompted.

Parses a third-party keystore object. Rejects with an Error if the object can’t be parsed. toJSON() on the resulting Keystore returns the original object, stringified.

Form 5

new Keystore(jsonString, passphrase);

Identical to Form 4, except jsonString is a JSON-encoded string (parsed with JSON.parse() before proceeding as in Form 4). toJSON() on the resulting Keystore returns the original string, unaltered.

Form 6

new Keystore(keystoreObject);

Arguments:

  • keystoreObject (Keystore) - An existing Keystore object.

Copies another Keystore. The new object shares the same encrypted secret as keystoreObject, so it unlocks with the same passphrase.

Form 7

new Keystore(null, passphrase);

Arguments:

  • passphrase (string) - The passphrase used to encrypt the newly generated private key.

Generates a random private key, encrypted with the given passphrase (no prompt).

Note

Forms 2-5’s argument descriptions above intentionally depart slightly from this class’s own source comments, which describe Forms 2 and 3 as also accepting “an Ethereum v3 Keystore object” – that phrasing appears to be copied in error from Forms 4/5 and doesn’t match the constructor’s actual branching logic (checked against dcpEth.PrivateKey(arguments[0], true)), which only accepts private-key-like values there.

Properties

address

Keystore.address
Type:

Address

The (public) address represented by this Keystore.

label

Keystore.label
Type:

string

When set, used to build the message shown to the user when prompting for a passphrase (see unlock()).

Methods

toJSON

toJSON()

Serializes the Keystore to a plain object suitable for writing to a Keystore File or sending to a third party, without leaking the decrypted private key.

Return type:

object

Note

The returned object also carries two properties not present in the originally-imported/generated keystore data: timestamp (the result of String(new Date()) at serialization time) and process (the invoking process’s name on Node.js, or the calling script/page’s origin+pathname in a browser). These are added fresh on every call to toJSON(), so two serializations of the same Keystore moments apart will differ in these two fields even though the encrypted secret is identical.

unlock

unlock(passphrase, lockTimerDuration, autoReset)

Unlocks the Keystore for a given amount of time so that getPrivateKey() and related operations don’t need to ask for a passphrase. This is an async method that returns a Promise.

Arguments:
  • passphrase (string) – Optional. If omitted, exports.passphrasePrompt is invoked to solicit it from the user, unless the keystore is already unlocked.

  • lockTimerDuration (number) – Number of seconds to stay unlocked for. If omitted, the keystore re-locks immediately after the next call to getPrivateKey().

  • autoReset (boolean) – When true, a subsequent call to getPrivateKey() resets and restarts the unlock timer.

Throws:

An error with code DCP_WA:UNLOCKX if the keystore could not be unlocked (e.g. wrong passphrase).

While the unlock timer is running, calling unlock again to extend it requires a passphrase check; if the new duration is longer than one previously set with autoReset, the autoReset duration itself is increased so future calls to getPrivateKey keep resetting to at least that length.

lock

lock()

Locks the Keystore immediately, discarding the decrypted private key from memory.

isLocked

isLocked()
Return type:

boolean

isUnlocked

isUnlocked()
Return type:

boolean

getPrivateKey

getPrivateKey()

Returns the decrypted private key, unlocking the Keystore (prompting for a passphrase if necessary) as needed. This is an async method that returns a Promise.

Return type:

PrivateKey

Note

If you find yourself reaching for this, consider whether makeSignedMessage(), makeSignedMessageObject(), or makeSignature() already do what you need without handling the raw key yourself.

testPassphrase

testPassphrase(passphrase)

Checks whether a passphrase unlocks this Keystore’s private key, without actually unlocking it. This is an async method that returns a Promise.

Arguments:
  • passphrase (string) – The passphrase to test.

Return type:

boolean

makeSignedMessage

makeSignedMessage(messageBody)

Signs messageBody with this Keystore’s private key, implementing Connection.Message.sign (see the Protocol API). This is an async method that returns a Promise.

Arguments:
  • messageBody (object) – The message to sign.

Return type:

Promise<string>

makeSignedMessageObject

makeSignedMessageObject(messageBody)

Like makeSignedMessage(), but returns the object { owner, signature, body } instead of a string. This is an async method that returns a Promise.

Arguments:
  • messageBody (object) – The message to sign.

Return type:

Promise<object>

makeSignedLightWeightMessageObject

makeSignedLightWeightMessageObject(messageLightWeight, messageBody)

Like makeSignedMessageObject(), except the signature is computed only over messageLightWeight, so large messageBody payloads don’t need to be hashed in full. Returns { owner, signature, auth: messageLightWeight, body }. This is an async method that returns a Promise.

Arguments:
  • messageLightWeight (object) – The (small) portion of the message to actually sign.

  • messageBody (object) – The full message body to attach, unsigned.

Return type:

Promise<object>

makeSignature

makeSignature(messageBody)

Creates a raw signature for messageBody, implementing Connection.Request.authorize (see the Protocol API). This is an async method that returns a Promise.

Arguments:
  • messageBody (object) – The message to sign. Non-string values are serialized with JSON.stringify() first.

Return type:

Promise<object>

Note

Passing undefined throws synchronously ('tried to make a signature for undefined') rather than signing the string "undefined".

Events

Keystore is an EventEmitter. Handlers are attached the usual way, for example, keystore.on('lock', () => { ... }).

  • lock - emitted immediately after the Keystore becomes locked, whether via an explicit call to lock() or because an unlock timer expired.

  • unlock - emitted immediately after the Keystore successfully unlocks.

Subclasses

IdKeystore, AuthKeystore, and BankAccountKeystore all extend Keystore with the exact same constructor forms and methods described above – they exist to label why a given Keystore is being used, not to change its behaviour.

  • IdKeystore - Represents an identity, such as the Scheduler, the Portal, or an end user. Messages signed with an identity’s private key carry the same access privileges as that user’s Portal login.

  • AuthKeystore - Represents authorization granted to a third party (for example, to withdraw or escrow funds up to some limit). wallet.get() and load() return AuthKeystore objects.

  • BankAccountKeystore - Represents a bank account directly. Knowing the private key is sufficient to withdraw or escrow funds from the account.

Example

const wallet = require('dcp/wallet');

// Create a brand new keystore, encrypted with an explicit passphrase (Form 3),
// and write it out as a Keystore File.
const ks = await new wallet.Keystore(null, 'correct horse battery staple');
require('fs').writeFileSync('./my.keystore', JSON.stringify(ks));

// ... later, or in a different process ...

// Load it back, unlock it, and sign a message with it.
const { keystore } = await wallet.load('./my.keystore');
await keystore.unlock('correct horse battery staple');
const signedMessage = await keystore.makeSignedMessage({ hello: 'world' });