This document is a working draft.
Last updated: Mar 14 2018, 12:46pm EDT

libVES
Overview
VESvault: Encryption at rest made practical
libVES is a JavaScript interface library to VESvault REST API. Any app or service can integrate libVES to maintain secure storage of encrypted data, while having a safe and reliable way of recovering the data in case if the user loses the encryption key.
The latest source code can be found at the GitHub repository.
Usage
The latest most stable version of libVES can be included or downloaded from https://ves.host/pub/libVES.js.
libVES can be used with any existing VESvault account. For VESvault accounts created using third party authentication, VESvault password needs to be set before using libVES.
Authentication
libVES offers two types of authentication – primary and secondary. Primary authentication provides complete access to a VESvault account, while secondary authentication restricts access to a specific vault compartment controlled by a Secondary Vault Key.
Primary Vault Authentication
Primary Vault authentication provides full access to the entire VESvault account, complete Vault Key management, VESrecovery functions, and Vault Item management for the Primary Vault and all the Secondary Vaults the account owns or has access to.
user String VESvault Account Username, the account holder's email address
passwd String VESvault Account Password
veskey String Primary VESkey
VES = new libVES({"user": "me@domain.com"});	// new instance of libVES
VES.login("myPassword");			// log into VESvault account
VES.unlock("myVESkey");				// unlock the Primary Vault
Secondary Vault Authentication
Secondary Vault authentication provides restricted access to a specific Secondary Vault. Manage the Secondary Vault Key, and Vault Items in the Secondary Vault
domain String App Domain Tag
externalId String Secondary Vault Key External ID, specific to the App Domain
veskey String Secondary VESkey
VES = new libVES({"domain": "myApp", "externalId": "key1234"});	// new instance of libVES
VES.unlock("appVESkey");					// login and unlock the Secondary Vault
External Oauth Authentication
new libVES(options)
Create a new instance of libVES.
options object libVES constructor options user String VESvault account user name (email address). Required to access the Primary Vault domain String App Domain Tag. Required to access the Secondary Vault externalId String External ID. Required to access the Secondary Vault apiUrl String VESvault REST API base URL. Defaults to the official endpoint, https://api.ves.host/v1/. keyAlgo String Default algorithm tag for newly created Vault Keys. Defaults to RSA.
libVES A new instance of libVES
object libVES.Error Inconsistent parameters
VES = new libVES({"user": "me@domain.com"});
VES = new libVES({"domain": "myApp", "externalId": "key1234"});
login(password)
Log in to a primary VESvault account. Applies to the username supplied in the constructor options.
Not applicable to Secondary Vault
password String or Promise VESvault Account Password
Promise(libVES.User) Logged in user
libVES.Error Login failed
VES.login("myPassword").then(function(me) {
    Promise.all([me.getId(),me.getEmail()]).then(function(data) {
	console.log("Logged in as User " + data[0] + " (" + data[1] + ")");
    });
}).catch(function(error) {
    window.alert(error);
});
logout()
Log out of the VESvault account, if logged in. Also locks the Vault if it was unlocked.
(Promise) true Always succeeds
VES.lock();
me()
The owner of the Primary or Secondary Vault
Promise(libVES.User) The owner of the Vault
libVES.Error Error (not authenticated?)
VES.me().then(function(me) {
    Promise.all([me.getId(),me.getEmail()]).then(function(data) {
	console.log("I am User " + data[0] + " (" + data[1] + ")");
    });
}).catch(function(error) {
    window.alert(error);
});
getVaultKey()
Current Vault Key for a Primary Vault, null if not set up. Secondary Vault Key for a Secondary Vault.
Promise(libVES.VaultKey) The active Vault Key
libVES.Error Error (not authenticated?)
VES.getVaultKey().then(function(vaultKey) {
    Promise.all([vaultKey.getId(),vaultKey.getType(),vaultKey.getAlgo()]).then(function(data) {
	console.log("Vault Key #" + data[0] + " type = " + data[1] + ", algo = " + data[2]);
    });
}).catch(function(error) {
    window.alert(error);
});
unlock(veskey)
Unlock the Vault Key. Need to be logged in to VESvault account to unlock the Primary Vault. If the vault is already unlocked, a call without the veskey argument will return the unlocked CryptoKey
If the platform's Web Crypto API lacks support for the key algo, the returned value may be of a custom type different than CryptoKey, but of similar sense
veskey String or Promise VESkey (Vault Key Passphrase)
Promise(CryptoKey) Unlocked CryptoKey
libVES.Error Unlock failed (incorrect VESkey?)
VES.unlock("veskey").then(function(cryptoKey) {
    console.log("VESvault key is unlocked...",cryptoKey);
}).catch(function(error) {
    window.alert(error);
});
lock()
Lock the Vault, if unlocked
Promise(true) Always succeeds
VES.lock();
setVESkey(veskey,lost,options)
Rekey the Vault. Create a new Vault Key with the supplied VESkey as a passphrase.
veskey String or Promise New VESkey
lost boolean Set to true to flag the Current Vault Key as lost, and initiate VESrecovery. Applicable to Primary Vault only.
options object Vault Key Options. Optional.
Promise(libVES.VaultKey) The new Vault Key
libVES.Error Rekey failed
VES.setVESkey("myVESkey",false).then(function(vaultKey) {
    Promise.all([vaultKey.getId(),vaultKey.getType(),vaultKey.getAlgo()]).then(function(data) {
	console.log("Vault Key #" + data[0] + " type = " + data[1] + ", algo = " + data[2]);
    });
}).catch(function(error) {
    window.alert(error);
});
setShadow(friends,options)
Create, replace or remove a Shadow Vault Key, to be used for VESrecovery in case of losing the VESkey. Applicable only to Primary Vault. The Vault must be unlocked prior to this call.
friends Array(…) Array of Vault References. Primary Vaults only. Pass an empty array to remove the Shadow and disable VESrecovery.
options Object Recovery options. v String Recovery algorithm version. Defaults to RDX1.2 n Int Number of Friends needed to assist in VESrecovery. Required.
Promise(libVES.VaultKey) The new Shadow Vault Key, or null if removed
libVES.Error Shadow setup failed
VES.setShadow(["friend1@domain.com","friend2@domain.com","friend3@domain.com"],{"a":"RDX1.2", "n":2}).then(function(vaultKey) {
    Promise.all([vaultKey.getId(),vaultKey.getType(),vaultKey.getAlgo()]).then(function(data) {
	console.log("Vault Key #" + data[0] + " type = " + data[1] + ", algo = " + data[2]);
    });
}).catch(function(error) {
    window.alert(error);
});
getMyRecoveries()
Get info and status of the current VESrecoveries for the User's lost Vault Keys.
Promise(Array(libVES.Recovery)) User's Own Recoveries
libVES.Error Failed.
VES.getMyRecoveries().then(function(recoveries) {
    for (var i = 0; i < recoveries.length; i++)	console.log(recoveries[i]);
}).catch(function(error) {
    window.alert(error);
});
getFriendsRecoveries()
Access the Friends' VESrecoveries the User might be able to assist at.
Promise(Array(libVES.Recovery)) Friends' VESrecoveries
libVES.Error Failed.
VES.getMyRecoveries().then(function(recoveries) {
    for (var i = 0; i < recoveries.length; i++)	console.log(recoveries[i]);
}).catch(function(error) {
    window.alert(error);
});
getValue(fileRef)
Decrypt the value stored in the Vault, identified by the file reference.
fileRef Object File Reference
Promise(…) The decrypted value, formatted according to the type
libVES.Error No such file? No access to the file? Vault is not unlocked?
VES.getValue({"domain":"myDomain","externalId":"myItem1"}).then(function(value) {
    console.log('Value: ' + value);
}).catch(function(error) {
    window.alert(error);
});
putValue(fileRef,value,shareWith)
Deposit the value in the Vault. Create the File entry and associated entries if doesn't exist.
fileRef Object File Reference
value The value to be deposited, formatted according to the type. For existing Vault Item the type of the value must match the type of the item. For a new Vault Item, the type of the Vault Item is autodetected based on the type of the value.
shareWith Array(…) List of Vault References to share with. Optional. For a new item, defaults to the owner's secondary vault within the item file's domain.
Promise(libVES.VaultItem) Vault Item if successful
libVES.Error Incorrect value type? No permission for this file?
VES.putValue({"domain":"myDomain","externalId":"myItem1"},"secret content").then(function(vaultItem) {
    vaultItem.getId().then(function(id) {
	console.log('Vault Item ID: ' + id);
    });
}).catch(function(error) {
    window.alert(error);
});
deleteFile(fileRef)
Delete an external file entry, and any associated items.
fileRef Object File Reference
Promise(true) Deleted
libVES.Error No such file? No access to the file?
VES.deleteFile({"domain":"myDomain","externalId":"myItem1"}).then(function() {
    console.log('deleted');
}).catch(function(error) {
    window.alert(error);
});
libVES.User
Object libVES.User represents a VESvault user account. An interface to REST API call users.
getId()
Promise(Int) VESvault User ID.
getEmail()
Promise(String) User email address.
getFirstName()
Promise(String) User's first name.
getLastName()
Promise(String) User's last name.
getFullName()
Promise(String) User's full name, assembled from the first and last name.
getVaultKeys()
Promise(Array(libVES.VaultKey)) All User's Vault Keys
getCurrentVaultKey()
Promise(libVES.VaultKey) User's current primary Vault Key. null if not set.
libVES.VaultKey
Object libVES.VaultKey represents an asymmetric Vault Key. An interface to REST API call vaultKeys.
Vault Key Types
The following types of Vault Key are supported in VESvault:
current The current Primary Vault Key. The passphrase for the current key is the user's primary VESkey. Only one current key may exist per VESvault account at any moment. When the user sets a new primary VESkey, all the vault entries from the old current Vault Key are rekeyed, and the old current Vault Key is deleted. If the user has lost the VESkey, the current Vault Key changes the type to lost, and the new current key is created for the new VESkey.
temp A temporary Vault Key, created on the behalf of another VESvault user. A temporary key always has a Creator - a VESvault user who created the key. If a temp key has External reference, it is intended to be rekeyed to a Secondary key with same External. A temp key with no External is intended to be rekeyed to the Primary (current) Vault Key. Multiple temp keys may exist per VESvault account, with diferrent Creators and/or Externals. When Alice shares a Vault Item with Bob, and Bob doesn't have a VESvault account, or doesn't have a proper Vault Key set up, Alice creates a temp Vault Key. The owner of the created key is Bob, the creator is Alice. The External reference of the created key is empty if Alice shares with Bob's Primary Vault, or is set accordingly (domain & externalId) if Alice shares with Bob's Secondary Vault. The passphrase for the temp key is a randomly generated string. Alice stores the generated passphrase as a Vault Item in her vault. If Bob already had a current (Primary) Vault Key, and Alice has generated a temp key for a Bob's secondary vault, Alice shares the passphrase Vault Item with Bob's Primary Vault. Otherwise, Alice remains the sole holder of Bob's temp passphrase until Bob sets up his Primary Vault. When Alice unlocks her Vault and detects that Bob has set up his Primary Vault (key type current), Alice shares the temp passphrase with Bob's Primary Vault. Next time Bob unlocks his Primary Vault, the system (libVES or VESvault web interface) creates the missing Secondary Vault Keys, and rekeys all items from the temp keys, using the temp passphrases shared with his Primary Vault. Once done, Bob deletes the temp keys.
secondary A secondary Vault Key. Isentified by the owner and the External reference. The passphrase is called the Secondary VESkey, and is stored as a Vault Item in the owner's Primary Vault. Multiple Secondary keys with different Externals may exist in a User's VESvault. If the user loses the Secondary VESkey, he will need to unlock the Primary Vault to retrieve the stored Secondary VESkey. If the Primary VESkey is also lost, VESrecovery is needed to regain access to the Primary Vault.
lost When a VESvault user loses the Primary VESkey, he creates a new VESkey, and the type of the old current VESkey is changed to lost. At this point, VESrecovery is initiated (if it was set up). Once the recovery is achieved, or the user finds his lost VESkey, all the vault entries are rekeyed from the lost key to the new current key, and the lost key is deleted.
shadow Shadow key allows the user to gain access to encrypted data through VESrecovery process, in case of losing the Primary VESkey. The passphrase to the Shadow key is a randomly generated string, and is referred to as Recovery Secret. When the Shadow key is being created, the Recovery Secret is passed through the Scramble Algorithm that produces multiple Recovery Tokens. The Recovery Secret can be reconstructed from a predefined number of Recovery Tokens. Each Recovery Token is stored as a Vault Item and is shared with a specific friend. All the Vault Items deposited in the user's Primary Vault are reflected on the Shadow Key. When the user indicates the loss of the Primary VESkey, the status of the Shadow Key is changed to recovery, and a new blank Shadow Key with same set of friends is created. Only one Shadow key can exist per VESvault account can exist at a given time.
recovery When the user indicates the loss of the Primary VESkey, the status of the Shadow Key is changed from shadow to recovery. Each friend is prompted to assist – share his Recovery Token back with the User's new Primary Vault. Once the required number of friends have assisted, the VESrecovery is achieved. The Vault Key can be unlocked now, all the items can be rekeyed to the current Primary Vault, and the old key is deleted.
pending Type pending is reserved for background operations in the future implementations. Pending keys are not returned by getVaultKeys(), and can be accessed only by ID. After 7 days, pending key is considered abandoned and may be automatically permanently deleted along with any associated entries.
deleted Type deleted is a proposed experimental safety measure against permanent loss of data in case of incorrect rekeying. Deleted keys are not returned by getVaultKeys(), and can be accessed only by ID. After 7 days, pending key is considered abandoned and may be automatically permanently deleted along with any associated entries.
Vault References
Vault Reference is a convenient way to identify Vault Keys to deposit or share an item with. Vault References are used by sharing functions, such as vaultItem.shareWith() and VES.setShadow().
A Vault Reference may be any of the following:
  • Primary Vault Reference:
    • (String) A properly formatted user's email address. The VESvault user with the specified email will be automatically created if it doesn't exist yet.
    • (object) A user hint object. Either id or email is required: id VESvault User ID. If set, matches a user, throws an error if none matched. email User email address. If set, matches a user, creates a new user if none matched. firstName First name hint. Updated for the matched or created VESvault User is wasn't set before, ignored otherwise. lastName Last name hint. Updated for the matched or created VESvault User is wasn't set before, ignored otherwise.
    • (libVES.User) A VESvault user object
  • Secondary Vault Reference:
    • (object) A Secondary Vault hint object. Both domain and externalId are required: domain App domain tag. externalId External ID. Unique within the app domain. user User hint, optional. May be of any type described in the Primary Vault Reference.
      • If the Secondary Vault Key is matched by external reference (domain & externalId) – the user hint is ignored.
      • Else, if the app domain specific validation is passed, and the user hint matches or creates a valid user – the External reference is created.
      • Otherwise – throws an error.
    • (libVES.VaultKey) A Vault Key, type secondary
    • (libVES.External) An External reference, pointing to a Vault Key type secondary
getId()
Promise(Int) Vault Key ID.
getUser()
Promise(libVES.User) The Vault Key owner.
getType()
Promise(String) Vault Key Type.
getAlgo()
Promise(String) Asymmetric Algorithm tag.
getPublicKey()
Promise(String) The public key, PKCS#1 PEM formatted string.
getPrivateKey()
Promise(String) The encrypted private key, PKCS#5 PEM formatted string.
getVaultEntries()
Promise(Array(object)) The vault entries encrypted with the Vault Key. vaultItem object id = VaultItem ID encData String Base64 encoded encrypted VaultItem data
getExternals()
Promise(Array(libVES.External)) The external references. In the current version, no more than 1 external reference is supported per VaultKey. Applicable to type external or temp.
getCreator()
Promise(libVES.User) The key creator. Applicable to type temp.
getVaultItems()
Promise(Array(libVES.VaultItem)) Supplementary Vault Items. Applicable to type temp (passphrase), or shadow/recovery (recovery tokens).
getRecovery()
Promise(libVES.Recovery) The VESrecovery control object. Applicable to type shadow/recovery.
unlock(veskey)
Unlock the Vault Key. If the Vault Key is already unlocked, a call without the veskey argument will return the unlocked CryptoKey
If the platform's Web Crypto API lacks support for the key algo, the returned value may be of a custom type different than CryptoKey, but of similar sense
veskey String or Promise Passphrase
Promise(CryptoKey) Unlocked CryptoKey
libVES.Error Unlock failed (incorrect passphrase?)
lock()
Lock the Vault Key, if unlocked
Promise(true) Always succeeds
getPublicCryptoKey()
Load the Public Key as a CryptoKey object.
If the platform's Web Crypto API lacks support for the key algo, the returned value may be of a custom type different than CryptoKey, but of similar sense
Promise(CryptoKey) Public Key as a CryptoKey
libVES.Error Inalid public key?
getUnlockedPrivateKey()
Get the unencrypted PEM private key. The Vault Key must be unlocked to decrypt the private key.
Promise(String) The unencrypted private key, PKCS#8 PEM formatted.
libVES.Error Vault Key is not unlocked?
encrypt(plainText)
Encrypt raw data. A low level call, use vaultItem.shareWith() for high level.
plainText Uint8Array or ArrayBuffer Raw binary plaintext to encrypt
Promise(String) Base64 encoded ciphertext.
libVES.Error Bad public key?
decrypt(cipherText)
Decrypt raw data. A low level call, use vaultItem.get() for high level.
cipherText String Base64 encoded ciphertext.
Promise(Uint8Array) Raw binary plaintext.
libVES.Error Vault Key is not unlocked?
libVES.VaultItem
Object libVES.VaultItem represents an item stored in VESvault. The Vault Item may be shared with one or more Primary or Secondary Vaults, restriction rules apply based on type. Arbitrary metadata can be stored along with an item. The length of serialized metadata should nexer exceed 65536 bytes. To avoid potential interference with future extensions, use 'x_' prefix on the custom metadata keys.
An interface to REST API call vaultItems.
Vault Item Types
The following types of Vault Items are currently implemented in VESvault:
password A relatively short secret phrase. Might be either an arbitrary password stored in a lockbox, or a stored passphrase to a particular Vault Key, type secondary or temp. The parsed content of the Vault Item is a String.
string An arbitrary secret text, stored in a lockbox. The binary version of the ciphertext should never exceed 65536 bytes, use type file for unlimited size data. The parsed content of the Vault Item is a String.
file The symmetric Item Encryption Key for an arbitrary encrypted file or stream data. Might be either an encrypted file stored in a lockbox (size quotas apply), or stored by an external app outside of VESvault (such as centralized or distributed cloud storage). The parsed content of the Vault Item is a libVES.Cipher. a String Symmetric Cipher algorithm tag.
secret A scrambled Recovery Token, used in VESrecovery. The parsed content of the Vault Item is a following object: meta object Metadata. data Uint8Array Recovery Token. v String Scramble Algorithm version tag. n Int Number of tokens required to unscramble the Recovery Secret and achieve VESrecovery. b Int The base value for the recovery algorithm, distinct for each token in the scrambled Recovery Token set.
getId()
Promise(Int) Vault Item ID.
getType()
Promise(String) Vault Item Type.
getVaultEntries()
Promise(Array(object)) The vault entries that store the ciphertext pertaining to the Vault Item. vaultKey object id = VaultKey ID encData String Base64 encoded encrypted VaultItem data
getMeta()
Promise(object) Vault Item Metadata. Arbitrary key-value pairs, specific keys apply to certain Vault Item Types.
get()
Get the contents of the Vault Item, parsed according to the Type. The Vault Item must have a Vault Entry that pertains to an unlocked Vault Key in order to decrypt the contents.
Promise(…) The decrypted content, parsed according to the Vault Item Type.
libVES.Error Vault Key is not unlocked?
shareWith(vaults,content)
Deposit the content into the Vault Item, or change the sharing.
vaults Array(…) List of Vault References.
content The content to be deposited, formatted according to the Vault Item Type. null to change sharing rights to already deposited content.
Promise(libVES.ValutItem) Self if succeeded.
libVES.Error Malformed content or vault list?
libVES.External
Object libVES.External represents a reference from a VESvault object to some external entity.
getId()
Promise(Int) Vault Item ID.
getDomain()
Promise(String) External Domain Tag.
getExternalId()
Promise(String) External ID Reference.
libVES.Recovery
getFriends()
Get list of VESrecovery Friends. Applicable only to the Owner's Recovery.
Trigger(Array(libVES.User)) List of Friends.
libVES.Error Not the owner of the recovery?
getFriendInfo(user)
Get a Recovery Info for a particular Friend. Applicable to the Owner's Recovery, or to the Friend's Recovery to get the Owner's info.
user libVES.User User to get Recovery Info for..
Trigger(object) Recovery Info obect. user libVES.User A friend who can assist in VESrecovery.
libVES.Error Not a valid friend for this VESrecovery?
getFriendsTotal()
Get total number of Friends who might be able to assist in this VESrecovery. Applicable only to Owner's Recovery.
Trigger(Int) Total number of Friends.
libVES.Error Not the owner of the recovery?
getFriendsRequired()
Get total required number of assistances to achieve VESrecovery.
Trigger(Int) Required total number of Friends to assist.
libVES.Error Not a valid recovery?
getFriendsAssisted()
Get number of Friends who have assisted in this VESrecovery. Applicable only to Owner's Recovery.
Trigger(Int) Number of Friends who have assisted.
libVES.Error Not the owner of the recovery?
getFriendsToGo()
Get number of Friends needed to assist to achieve VESrecovery, in addition to those who have already assisted. Applicable only to Owner's Recovery.
In case of foul assistance, i.e. when one or more Friends have shared invalid token for any reason, the returned value may depend on whether the Vault is unlocked or not. If the number of assisted friends is not less then the required number, the Vault is unlocked, and the VESrecovery cannot be achieved because of inconsistent data, the function will return 1.
Trigger(Int) Number of Friends to assist.
libVES.Error Not the owner of the recovery?
assist()
Provide VESrecovery assistance, i.e. share the Recovery Token back with the friend. Resets the ignore flag if it was set.
Promise(true) Success.
libVES.Error Not a friend?
revoke()
Revoke the VESrecovery provided, e.g. when fraud is suspected.
Not a reliable fraud protection. When in doubt, do not provide assistance at the first place. See security assessment in VES Whitepaper.
Promise(true) Success.
libVES.Error Not a friend?
ignore()
Flag the assistance request as ignored.
Promise(true) Success.
libVES.Error Not a friend?
recover()
Complete the VESrecovery.
The result is a Trigger. Call once, and wait until it resolves to true.
Trigger(true) The trigger resolves to null if recovery is still in progress, resolves to true once the recovery is completed.
libVES.Error Not the owner of the Recovery?
Asymmetric Algorithms
RSA
ECDH
Symmetric Ciphers
AES 256 CTR
AES 256 GCM
VESrecovery Algorithms
RDX 1.2 / Shamir
End To End Notifications
Signal Messenger