This document details the construction of an BCP compatible keybase system. It describes the core concepts of UserProfiles, Keyrings, and the identity types they contain.
UserProfile
: A collection of User materials. Includes multiplekeyringEntries
associated with aUserProfile
.Keyring
: An object containingkeyringEntry
's.KeyringEntry
: An object which houses ONESeedIdentity
and NPublicIdentities
.SeedIdentity
: Single Private material entry in aKeyringEntry
, used for deriving asecret
to sign transactions and generatePublicIdentities
.PublicIdentities
: Public materials collection. Contains the an array of objects related to aSeedIdentity
.PublicIdentity
: A collection of information derived from asecret
. It includes an address, publicKey, and HD path data which is always defined via the HD specifications. Used for end user queries for balances and transaction histories.
The Keybase includes a fully featured suite of key management. This includes the creation of new seeds, publickeys, and addresses. It also includes the usage of a Hardware Wallet, and various cryptographic algorithms.
The iov-core Keybase will require the ability to generate new seeds from entropy for a user, when needed. This can occur when a UserProfile is made, or later on demand by the User.
Users will also need the ability to Import seeds from other software, and Export Seeds from iov-core for reuse in other software.
The Seeds generated by the Keybase will be used to create new public keys, and addresses for use with blockchain technology. This will be done using standard HD derivation techniques.
These are the two "industry standard" cryptographic algorithms. Both need to be
supported to enable the greatest compatibility. Others can be supported later,
such as bls signatures
or zk-snarks
.
Hardware wallet support is necessary as more users are using these devices and they provide extremely high security for the key material while remaining practical to use. Ledger will be the first device type supported by the Keybase.
The Keybase will have the following features:
- Sign and Verify Transactions
- Sign and Verify Messages
All data entered into a profile is encrypted before it is stored on disk. Additionally, individual KeyringEntries can be encrypted by a separate passphrase.
The Keybase will implement a variety of standards regarding address derivation and timestamp generation. These have been listed here for review.
HD wallets will be created through this standard to yield a master publickey:privatekey pair.
HD Wallets for chain specific support will be created through the following standards for each algorithm.
- BIP43: https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki
- BIP44: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
Seed generation will be performed through the BIP39 specification for HD seeds
Timestamps are generated using a widely known standard to enable deterministic parsing.
- RFC 3339: https://tools.ietf.org/html/rfc3339
The code for keyring management is broken down into logical units, each performing a specific task. The design can be visualized as follows:
UserProfileController (1 UserProfileController)
|
| > UserProfile (1 UserProfile : N Users)
|
| > AddressBook (1 AddressBook : 1 UserProfile)
| | > AddressBookEntries (1 AddressBook : N AddressBookEntries)
|
| > SecurityModel (1 SecurityModel : 1 UserProfile)
|
| > Keyring (1 Keyring : 1 UserProfile)
|
| > keyringEntries (1 Keyring : N KeyringEntries)
|
| > SeedIdentity (1 KeyringEntry : 1 SeedIdentity)
|
| > PublicIdentities (1 SecretIdentity : N PublicIdentities)
The primary purpose of the UserProfileController
is to manage multiple
UserProfile
s. It provides the logic to manipulate UserProfile
s.
The following functions are called by the User
, through the
UserProfileController
- CreateUserProfile: Creates a new user in the
UserProfileController
- LoginUserProfile: Passes
username:password
pair to theUserProfileController
- DeleteUserProfile: Requests deletion of a
UserProfile
to theUserProfileController
- ExportUserProfile: Requests the plaintext export of
UserProfile
details, requires a correctlogin
{
"UserProfiles": []
}
A UserProfile
contains an object called keyring
, an object called
addressBook
, and an object called securityModel
. This is a 1:N
relation,
where N
is each UserProfile
created by the UserProfileController
.
"UserProfile": {
"username": "isabella",
"label": "My Profile",
"created": "1985-04-12T23:20:50.52Z", # RFC 3339
"securityModel": {
"timeout": 3600
},
"keyring": {
"keyringEntries": [],
},
"addressBook": {
"addressBookEntries": []
}
}
Contains a list of addresses a user has interacted with, or added for frequent use.
- AddContact: Adds a contact to a
AddressBook
with the specified information. - DeleteContact: Deletes a contact from a
AddressBook
- GetContact: Returns the
chain:address:humanName
for use in the application. - ExportContact: Returns a
contact
in plain text for import in another iov-core system. - ImportContact: Adds a
contact
from a predefined plain text entry.
"addressBook": {
"addressBookEntries": [
{
"address": "0x52b96095d265a93308fcf5cb9627085f029546be8b3",
"chain": {
"chain": "ETH",
"tickers": ["ETH","ANT"]
},
"created": "1985-04-12T23:20:50.52Z", # RFC 3339
"label": "Friend's Account"
}
]
}
The UserProfile
contains an object called securityModel
. This object defines
the security parameters of the profile. The entries in this object establish
when a profile will lock down through inactivity. This is a 1:1
relation
inside of a UserProfile
.
- GetSecurityDetails: Returns a security information for the
UserProfile
. - ModifySecurityDetails: Changes security information for the
UserProfile
.
"securityModel": {
"timeout": 3600
},
The Keyring
is an object that houses keyringEntries
. This object holds all
of the UserProfile
's KeyringEntry
s. This is a 1:1
relation inside of a
UserProfile
.
- GetKeyringEntry: Returns a requested
KeyringEntry
's details, such asPublicIdentities
. - AddKeyringEntry: Adds a new
KeyringEntry
, with an autogenerated or importedSecretIdentity
to theKeyring
. - DeleteKeyringEntry: Removes an existing
KeyringEntry
from theKeyring
. - ExportKeyringEntry: Exports a
KeyringEntry
in plain text, for use in anotherKeyring
. - ImportKeyringEntry: Imports a whole
KeyringEntry
, complete with aSecretIdentity
and the listPublicIdentities
.
"keyring": {
"keyringEntries": []
},
A KeyringEntry
contains all of the related SeedIdentity
, PublicIdentities
and personality information for an associated SeedIdentity
.
A SeedIdentity
is only an HD Seed value (Mnemonic Passphrase
) or a hardware
device identifier for a Ledger
.
This is a 1:1
relation, where each KeyringEntry
has one SeedIdentity
.
- CreateSeedIdentity: Creates a
SeedIdentity
, if theKeyRingEntry
has none. - RenameSeedIdentity: Changes the label of the
keyringEntry
. - DeleteSeedIdentity: Removes the
SeedIdentity
from thekeyringEntry
. - ExportSeedIdentity: Exports the
SeedIdentity
in plain text. Only the type ofHD
can be exported.
"KeyringEntry": {
"label": "My Account",
"SeedIdentity": {
"seed": "shift nature mean excess demise mule winter between swing success bitter patch",
"type": "HD" || "hardware"
},
"PublicIdentities": [
"PublicIdentity": {}
]
}
A PublicIdentities
are derived from seed:curve
pairs, which are used to
create a PublicIdentity
.
This is a 1:N
relation, where 1 is the SeedIdentity
for which the
PublicIdentity
is related and N are the generated PublicIdentities
.
- GetPublicIdentity: Returns
PublicIdentity
details for a specific algorithm. - CreatePublicIdentity: Creates a
PublicIdentity
from theSeedIdentity
. - DeletePublicIdentity: Removes a
PublicIdentity
fromPublicIdentities
. - ExportPublicIdentity: Exports a
PublicIdentity
in plain text.
"PublicIdentities": [
"PublicIdentity": {
"address": "0x6806ea1d9b2eb59DAc7fdcdf28bf8d5a12AD84Bc",
"label": "Wells Fargo",
"publicKey": {
"algo": ed25519,
"data": "52b96095d265a93308fcf5cb9627085f029546be8b31eccb00bad386a92544d7"
},
"chain": {
"chain": "ETH",
"tickers": ["ETH","ANT"]
},
"path": {
"root": "m",
"purpose": "44'",
"coinType": "60'", # Defined here: https://github.com/satoshilabs/slips/blob/master/slip-0044.md
"account": "0'",
"change": "0'",
"addressIndex": "0"
},
}
]
The following is what a fully initialized profile will look like. This includes one relation of each type.
"UserProfile": {
"username": "isabella",
"label": "My Profile",
"created": "1985-04-12T23:20:50.52Z", # RFC 3339
"securityModel": {
"timeout": 3600
},
"keyring": {
"keyringEntries": [
"KeyringEntry": {
"SeedIdentity": {
"label": "My Account",
"seed": "shift nature mean excess demise mule winter between swing success bitter patch",
"type": "HD" || "hardware"
},
"PublicIdentities": [
"PublicIdentity": {
"address": "0x6806ea1d9b2eb59DAc7fdcdf28bf8d5a12AD84Bc",
"label": "Wells Fargo",
"publicKey": {
"algo": ed25519,
"data": "52b96095d265a93308fcf5cb9627085f029546be8b31eccb00bad386a92544d7"
},
"chain": {
"chain": "ETH",
"tickers": ["ETH","ANT"]
},
"path": {
"root": "m",
"purpose": "44'",
"coinType": "60'", # Defined here: https://github.com/satoshilabs/slips/blob/master/slip-0044.md
"account": "0'",
"change": "0'",
"addressIndex": "0"
}
}
]
}
],
},
"addressBook": {
"addressBookEntries": [
{
"address": "0x52b96095d265a93308fcf5cb9627085f029546be8b3",
"chain": "ETH",
"tickers": ["ETH","ANT"],
"created": "1985-04-12T23:20:50.52Z", # RFC 3339
"label": "Friend's Account"
}
]
}
}
There are a few minor security concerns around Seed management and private key usage, these are addressed here.
Users will be forced to encrypt all HD Seeds kept on disk through their user profile. Users will be given the option of a second layer of security by encrypting each Seed separately.
We can reuse the same seed for each Curve
, and derive different public/private
key pairs using the instructions found in SLIP-0010. Security concerns around
private key reuse are mitigated by using an HMAC-SHA512 pseudo random number
generator. This results in new private keys which are created for each curve.
This method is how Trezor and Ledger derive keys for different curves.