## Modules
Keystore
Keygen
## Typedefs
pubkey : string

Public Key (ALA8dM36QedcUfPTNF7maThtRqHP5xvCqMsYiHUz1Rz7sPfhvCYuo)

wif : string

Wallet Import Format (5JMx76CTUTXxpAbwAqGMMVzSeJaP5UVTT5c2uobcpaMUdLAphSp)

privateKey : object

Private key object from ala-ecc4.

masterPrivateKey : string

Master Private Key. Strong random key used to derive all other key types. Has a 'PW' prefix followed by a valid wif. ('PW' + wif === 'PW5JMx76CTUTXxpAbwAqGMMVzSeJaP5UVTT5c2uobcpaMUdLAphSp')

owner : wif

Cold storage / recovery key. Has authoritiy to do everything including account recovery.

active : wif

Spending key. Has the authority to do everything except account recovery.

parentPrivateKey : masterPrivateKey | wif

Master private key or one of its derived private keys.

auth : object

Signing Keys and(or) Accounts each having a weight that when matched in the signatures should accumulate to meet or exceed the auth's total threshold.

accountPermissions : object

Permissions object from Ala blockchain obtained via get_account.

See chain API get_account => account.permissions.

keyPath : string
keyPathPrivate : object

An expanded version of a private key, a keypath ('active/mypermission'), and its calculated public key (for performance reasons).

minimatch : string

Glob matching expressions (active, active/**, owner/*).

keyPathMatcher : minimatch

Key derviation path (owner, active/*, active/**, active/mypermission)

uriData : string

A URI without the prefixing scheme, host, port.

uriMatcher : string

A valid regular expression string. The provided string is modified when it is converted to a RegExp object:

uriMatchers : uriMatcher | Array.<uriMatcher>
uriRule : Object.<keyPathMatcher, uriMatchers>
uriRules : Object.<uriRule>

Define rules that say which private keys may exist within given locations of the application. If a rule is not found or does not match, the keystore will remove the key. The UI can prompt the user to obtain the needed key again.

For any non-trivial configuration, implementions should create a unit test that will test the actual configuration used in the application (see ./uri-rules.test.js for a template).

Paths imply that active is always derived from owner. So, instead of writing owner/active/** the path must be written as active/**.

## Keystore * [Keystore](#module_Keystore) * [~Keystore(accountName, [config], [keepPublicKeys])](#module_Keystore..Keystore) * _static_ * [.wipeAll()](#module_Keystore..Keystore.wipeAll) * _inner_ * [~deriveKeys(params)](#module_Keystore..Keystore..deriveKeys) * [~getKeyPaths()](#module_Keystore..Keystore..getKeyPaths) ⇒ object * [~getPublicKey(path)](#module_Keystore..Keystore..getPublicKey) ⇒ [pubkey](#pubkey) * [~getPublicKeys([keyPathMatcher])](#module_Keystore..Keystore..getPublicKeys) ⇒ [Array.<pubkey>](#pubkey) * [~getPrivateKey(path)](#module_Keystore..Keystore..getPrivateKey) ⇒ [wif](#wif) * [~getPrivateKeys([keyPathMatcher], [pubkeys])](#module_Keystore..Keystore..getPrivateKeys) ⇒ [Array.<wif>](#wif) * [~getKeys(keyPathMatcher)](#module_Keystore..Keystore..getKeys) ⇒ [Array.<keyPathPrivate>](#keyPathPrivate) * [~signSharedSecret(otherPubkey, keyPathMatcher)](#module_Keystore..Keystore..signSharedSecret) ⇒ Promise.<oneTimeSignatures> * [~logout()](#module_Keystore..Keystore..logout) * [~timeUntilExpire()](#module_Keystore..Keystore..timeUntilExpire) ⇒ number * [~keepAlive()](#module_Keystore..Keystore..keepAlive) * [~keyProvider(param)](#module_Keystore..Keystore..keyProvider) ⇒ Array.<(pubkey\|wif)> * [~oneTimeSignatures](#module_Keystore..oneTimeSignatures) : object ### Keystore~Keystore(accountName, [config], [keepPublicKeys]) Provides private key management and storage and tooling to limit exposure of private keys as much as possible. Although multiple root keys may be stored, this key store was designed with the idea that all keys for a given `accountName` are derive from a single root key (the master private key). This keystore does not query the blockchain or any external services. Removing keys here does not affect the blockchain. **Kind**: inner method of [Keystore](#module_Keystore) | Param | Type | Default | Description | | --- | --- | --- | --- | | accountName | string | | Blockchain account name that will act as the container for a key and all derived child keys. | | [config] | object | | | | [config.timeoutInMin] | number | 10 | upon timeout, remove keys matching timeoutKeyPaths. | | [config.timeoutKeyPaths] | number | ['owner', 'owner/**'] | by default, expire only owner and owner derived children. If the default uriRules are used this actually has nothing to delete. | | [config.uriRules] | [uriRules](#uriRules) | | Specify which type of private key will be available on certain pages of the application. Lock it down as much as possible and later re-prompt the user if a key is needed. Default is to allow active (`active`) and all active derived keys (`active/**`) everywhere (`.*`). | | [keepPublicKeys] | boolean | true | Enable for better UX; show users keys they have access too without requiring them to login. Logging in brings a private key online which is not necessary to see public information. The UX should implement this behavior in a way that is clear public keys are cached before enabling this feature. | **Example** ```js config = { uriRules: { 'active': '.*', 'active/**': '.*' }, timeoutInMin: 10, timeoutKeyPaths: [ 'owner', 'owner/**' ], keepPublicKeys: true } ``` * [~Keystore(accountName, [config], [keepPublicKeys])](#module_Keystore..Keystore) * _static_ * [.wipeAll()](#module_Keystore..Keystore.wipeAll) * _inner_ * [~deriveKeys(params)](#module_Keystore..Keystore..deriveKeys) * [~getKeyPaths()](#module_Keystore..Keystore..getKeyPaths) ⇒ object * [~getPublicKey(path)](#module_Keystore..Keystore..getPublicKey) ⇒ [pubkey](#pubkey) * [~getPublicKeys([keyPathMatcher])](#module_Keystore..Keystore..getPublicKeys) ⇒ [Array.<pubkey>](#pubkey) * [~getPrivateKey(path)](#module_Keystore..Keystore..getPrivateKey) ⇒ [wif](#wif) * [~getPrivateKeys([keyPathMatcher], [pubkeys])](#module_Keystore..Keystore..getPrivateKeys) ⇒ [Array.<wif>](#wif) * [~getKeys(keyPathMatcher)](#module_Keystore..Keystore..getKeys) ⇒ [Array.<keyPathPrivate>](#keyPathPrivate) * [~signSharedSecret(otherPubkey, keyPathMatcher)](#module_Keystore..Keystore..signSharedSecret) ⇒ Promise.<oneTimeSignatures> * [~logout()](#module_Keystore..Keystore..logout) * [~timeUntilExpire()](#module_Keystore..Keystore..timeUntilExpire) ⇒ number * [~keepAlive()](#module_Keystore..Keystore..keepAlive) * [~keyProvider(param)](#module_Keystore..Keystore..keyProvider) ⇒ Array.<(pubkey\|wif)> #### Keystore.wipeAll() Erase all traces of this keystore (for all users). **Kind**: static method of [Keystore](#module_Keystore..Keystore) #### Keystore~deriveKeys(params) Login or derive and save private keys. This may be called from a login action. Keys may be removed as during Uri navigation or when calling logout. **Kind**: inner method of [Keystore](#module_Keystore..Keystore) **Throws**: - Error 'invalid login' | Param | Type | Description | | --- | --- | --- | | params | object | | | params.parent | [parentPrivateKey](#parentPrivateKey) | Master password (masterPrivateKey), active, owner, or other permission key. | | [params.saveKeyMatches] | [Array.<keyPathMatcher>](#keyPathMatcher) | These private keys will be saved to disk. (example: `active`). | | [params.accountPermissions] | [accountPermissions](#accountPermissions) | Permissions object from Ala blockchain via get_account. This is used to validate the parent and derive additional permission keys. This allows this keystore to detect incorrect passwords early before trying to sign a transaction. See Chain API `get_account => account.permissions`. | #### Keystore~getKeyPaths() ⇒ object Return paths for all available keys. Empty array is used if there are no keys. **Kind**: inner method of [Keystore](#module_Keystore..Keystore) **Returns**: object - {pubkey: Array, wif: Array} #### Keystore~getPublicKey(path) ⇒ [pubkey](#pubkey) Fetch or derive a public key. **Kind**: inner method of [Keystore](#module_Keystore..Keystore) **Returns**: [pubkey](#pubkey) - or null | Param | Type | | --- | --- | | path | [keyPath](#keyPath) | #### Keystore~getPublicKeys([keyPathMatcher]) ⇒ [Array.<pubkey>](#pubkey) Return public keys for a path or path matcher. **Kind**: inner method of [Keystore](#module_Keystore..Keystore) **Returns**: [Array.<pubkey>](#pubkey) - public keys or empty array | Param | Type | Default | Description | | --- | --- | --- | --- | | [keyPathMatcher] | [keyPath](#keyPath) \| [keyPathMatcher](#keyPathMatcher) | '**' | return all keys | #### Keystore~getPrivateKey(path) ⇒ [wif](#wif) Fetch or derive a private key. **Kind**: inner method of [Keystore](#module_Keystore..Keystore) **Returns**: [wif](#wif) - or null (missing or not available for location) | Param | Type | | --- | --- | | path | [keyPath](#keyPath) | #### Keystore~getPrivateKeys([keyPathMatcher], [pubkeys]) ⇒ [Array.<wif>](#wif) Return private keys for a path matcher or for a list of public keys. If a list of public keys is provided they will be validated ensuring they all have private keys to return. **Kind**: inner method of [Keystore](#module_Keystore..Keystore) **Returns**: [Array.<wif>](#wif) - wifs or empty array **Throws**: - key.pubkey Error `login with your $ key` - key Error `missing public key $` | Param | Type | Default | Description | | --- | --- | --- | --- | | [keyPathMatcher] | [keyPathMatcher](#keyPathMatcher) | '**' | default is to match all | | [pubkeys] | [Array.<pubkey>](#pubkey) | | if specified, filter and require all | #### Keystore~getKeys(keyPathMatcher) ⇒ [Array.<keyPathPrivate>](#keyPathPrivate) Fetch or derive a key pairs. **Kind**: inner method of [Keystore](#module_Keystore..Keystore) **Returns**: [Array.<keyPathPrivate>](#keyPathPrivate) - {path, pubkey, deny, wif} or empty array. Based on the Uri rules and current location, the deny could be set to true and the wif will be null. | Param | Type | Default | | --- | --- | --- | | keyPathMatcher | [keyPath](#keyPath) \| [keyPathMatcher](#keyPathMatcher) | ** | #### Keystore~signSharedSecret(otherPubkey, keyPathMatcher) ⇒ Promise.<oneTimeSignatures> **Kind**: inner method of [Keystore](#module_Keystore..Keystore) | Param | Type | Default | | --- | --- | --- | | otherPubkey | [pubkey](#pubkey) | | | keyPathMatcher | [keyPathMatcher](#keyPathMatcher) | ** | #### Keystore~logout() Removes all saved keys on disk and clears keys in memory. Call only when the user chooses "logout." Do not call when the application exits. Forgets everything allowing the user to use a new password next time. **Kind**: inner method of [Keystore](#module_Keystore..Keystore) #### Keystore~timeUntilExpire() ⇒ number **Kind**: inner method of [Keystore](#module_Keystore..Keystore) **Returns**: number - 0 (expired) or milliseconds until expire #### Keystore~keepAlive() Keep alive (prevent expiration). Called automatically if Uri navigation happens or keys are required. It may be necessary to call this manually. **Kind**: inner method of [Keystore](#module_Keystore..Keystore) #### Keystore~keyProvider(param) ⇒ Array.<(pubkey\|wif)> Integration for 'alaexplorerjs4' .. Call keyProvider with no parameters or with a specific keyPathMatcher pattern to get an array of public keys in this key store. A library like alaexplorerjs4 may be provided these available public keys to alad get_required_keys for filtering and to determine which private keys are needed to sign a given transaction. Call again with the get_required_keys pubkeys array to get the required private keys returned (or an error if any are missing). **Kind**: inner method of [Keystore](#module_Keystore..Keystore) **Returns**: Array.<(pubkey\|wif)> - available pubkeys in the keystore or matching wif private keys for the provided pubkeys argument (also filtered using keyPathMatcher). **Throws**: - path Error `login with your $ key` - key Error `missing public key $` **See**: https://github.com/ALADIN-Network/alaexplorerjs4 | Param | Type | Default | Description | | --- | --- | --- | --- | | param | object | | | | [param.keyPathMatcher] | string | "'**'" | param.keyPathMatcher for public keys | | [param.pubkeys] | [Array.<pubkey>](#pubkey) \| [Set.<pubkey>](#pubkey) | | for fetching private keys | ### Keystore~oneTimeSignatures : object **Kind**: inner typedef of [Keystore](#module_Keystore) **Properties** | Name | Type | Description | | --- | --- | --- | | signatures | Array.<string> | in hex | | oneTimePublic | [pubkey](#pubkey) | | ## Keygen * [Keygen](#module_Keygen) * [~generateMasterKeys([masterPrivateKey])](#module_Keygen..generateMasterKeys) ⇒ Promise.<object> * [~keyPathAuth](#module_Keygen..keyPathAuth) : Object.<keyPath, auth> ### Keygen~generateMasterKeys([masterPrivateKey]) ⇒ Promise.<object> New accounts will call this to create a new keyset.. A password manager or backup should save (at the very minimum) the returned {masterPrivateKey} for later login. The owner and active can be re-created from the masterPrivateKey. It is still a good idea to save all information in the backup for easy reference. **Kind**: inner method of [Keygen](#module_Keygen) **Returns**: Promise.<object> - masterKeys | Param | Type | Default | Description | | --- | --- | --- | --- | | [masterPrivateKey] | [masterPrivateKey](#masterPrivateKey) | | When null, a new random key is created. | **Example** ```js masterKeys = { masterPrivateKey, // <= place in a password input field (password manager) privateKeys: {owner, active}, // <= derived from masterPrivateKey publicKeys: {owner, active} // <= derived from masterPrivateKey } ``` ### Keygen~keyPathAuth : Object.<keyPath, auth> **Kind**: inner typedef of [Keygen](#module_Keygen) ## pubkey : string Public Key (ALA8dM36QedcUfPTNF7maThtRqHP5xvCqMsYiHUz1Rz7sPfhvCYuo) **Kind**: global typedef ## wif : string [Wallet Import Format](https://en.bitcoin.it/wiki/Wallet_import_format) (5JMx76CTUTXxpAbwAqGMMVzSeJaP5UVTT5c2uobcpaMUdLAphSp) **Kind**: global typedef ## privateKey : object Private key object from ala-ecc4. **Kind**: global typedef ## masterPrivateKey : string Master Private Key. Strong random key used to derive all other key types. Has a 'PW' prefix followed by a valid wif. (`'PW' + wif === 'PW5JMx76CTUTXxpAbwAqGMMVzSeJaP5UVTT5c2uobcpaMUdLAphSp'`) **Kind**: global typedef ## owner : [wif](#wif) Cold storage / recovery key. Has authoritiy to do everything including account recovery. **Kind**: global typedef ## active : [wif](#wif) Spending key. Has the authority to do everything except account recovery. **Kind**: global typedef ## parentPrivateKey : [masterPrivateKey](#masterPrivateKey) \| [wif](#wif) Master private key or one of its derived private keys. **Kind**: global typedef ## auth : object Signing Keys and(or) Accounts each having a weight that when matched in the signatures should accumulate to meet or exceed the auth's total threshold. **Kind**: global typedef **Example** ```js required_auth: { threshold: 1, keys: [{ key: 'ALA78Cs5HPKY7HKHrSMnR76uj7yeajPuNwSH1Fsria3sJuufwE3Zd', weight: 1 } ], accounts: [] } ``` ## accountPermissions : object Permissions object from Ala blockchain obtained via get_account. See chain API get_account => account.permissions. **Kind**: global typedef **Example** ```js const accountPermissions = [{ perm_name: 'active', parent: 'owner', required_auth: { threshold: 1, keys: [{ key: 'ALA78Cs5HPKY7HKHrSMnR76uj7yeajPuNwSH1Fsria3sJuufwE3Zd', weight: 1 } ], accounts: [] } },{ perm_name: 'mypermission', parent: 'active', required_auth: { threshold: 1, keys: [{ key: 'ALA78Cs5HPKY7HKHrSMnR76uj7yeajPuNwSH1Fsria3sJuufwE3Zd', weight: 1 } ], accounts: [] } },{ perm_name: 'owner', parent: '', required_auth: { threshold: 1, keys: [{ key: 'ALA78Cs5HPKY7HKHrSMnR76uj7yeajPuNwSH1Fsria3sJuufwE3Zd', weight: 1 } ], accounts: [] } }] ``` ## keyPath : string **Kind**: global typedef **See**: [validate.path(keyPath)](./validate.js) **Example** ```js 'owner', 'active', 'active/mypermission' ``` ## keyPathPrivate : object An expanded version of a private key, a keypath ('active/mypermission'), and its calculated public key (for performance reasons). **Kind**: global typedef **Properties** | Name | Type | | --- | --- | | wif | [wif](#wif) | | pubkey | [pubkey](#pubkey) | | path | [keyPath](#keyPath) | ## minimatch : string Glob matching expressions (`active`, `active/**`, `owner/*`). **Kind**: global typedef **See** - https://www.npmjs.com/package/glob#glob-primer - syntax - https://www.npmjs.com/package/minimatch - implementation ## keyPathMatcher : [minimatch](#minimatch) Key derviation path (`owner`, `active/*`, `active/**`, `active/mypermission`) **Kind**: global typedef ## uriData : string A URI without the prefixing scheme, host, port. **Kind**: global typedef **Example** ```js '/producers', '/account_recovery#name=..' ``` ## uriMatcher : string A valid regular expression string. The provided string is modified when it is converted to a RegExp object: - A start of line match is implied (`^` is always added, do not add one) - Unless the uriPath ends with `$`, automatically matches query parameters and fragment (hash tag info). - The RegExp that is created is always case-insensitive to help a non-canonical path match. Uri paths should be canonical. **Kind**: global typedef **Example** ```js '/(transfer|contracts)', '/bare-uri$' ``` **Example** ```js function createPathMatcher(path) { // Ensure match starts at the begining const prefix = '^' // If path matcher does not end with $, allow Uri query and fragment const suffix = path.charAt(path.length - 1) === '$' ? '' : '\/?([\?#].*)?$' // Path matches are case in-sensitive return new RegExp(prefix + path + suffix, 'i') } ``` ## uriMatchers : [uriMatcher](#uriMatcher) \| [Array.<uriMatcher>](#uriMatcher) **Kind**: global typedef ## uriRule : Object.<keyPathMatcher, uriMatchers> **Kind**: global typedef **Example** ```js { 'owner': '/account_recovery$', // <= $ prevents query or fragment params 'active': ['/transfer', '/contracts'] } ``` ## uriRules : [Object.<uriRule>](#uriRule) Define rules that say which private keys may exist within given locations of the application. If a rule is not found or does not match, the keystore will remove the key. The UI can prompt the user to obtain the needed key again. For any non-trivial configuration, implementions should create a unit test that will test the actual configuration used in the application (see `./uri-rules.test.js` for a template). Paths imply that active is always derived from owner. So, instead of writing `owner/active/**` the path must be written as `active/**`. **Kind**: global typedef **Example** ```js uriRules = { // Hypothetical examples // Allow owner and all derived keys (including active) 'owner': '/account_recovery', // Allow active key (and any derived child) 'active': '/(transfer|contracts)', // Allow keys derived from active (but not active itself) 'active/**': '/producers', // If user-provided or unaudited content could be loaded in a given // page, make sure the root active key is not around on these pages. 'active/**': '/@[\\w\\.]' } ```