mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-03-30 15:08:28 +00:00
182 lines
6.5 KiB
Markdown
182 lines
6.5 KiB
Markdown
# Identities
|
|
|
|
In OrbitDB, an identity is a cryptographically signed public key which is used to verify write access to a database's operations log and, if allowed, to sign each database update as it is added to the operations log.
|
|
|
|
`Identities` provides methods to manage one or more identities and includes functionality for creating, retrieving, signing and verifying an identity and, internally, it is used to sign and verify database updates.
|
|
|
|
## Creating an identity
|
|
|
|
An identity can be created by using the `createIdentity` function.
|
|
|
|
A root key is used to create a new key with the "id" of the root key's public key. Using the derived private key, the root public key is signed.
|
|
|
|
A new identity is signed using the root key's private key. The identity is consists of the signed message and the derived public key concatenated together ("signed identity")
|
|
|
|
A "signatures object" is then created to hold both the signed message and signed identity.
|
|
|
|
Finally, a new identity consisting of the root public key and derived public key plus the signatures object is generated and stored to the Identities storage.
|
|
|
|
```js
|
|
import { Identities } from '@orbitdb/core'
|
|
|
|
const id = 'userA'
|
|
const identities = await Identities()
|
|
const identity = identities.createIdentity({ id })
|
|
```
|
|
|
|
The `id` parameter that is passed to createIdentity is used to reference the root key pair in the PublicKeyIdentityProvider. The id can be any arbitrary text, e.g. 'bob', 'My-Key-123', etc.
|
|
|
|
The PublicKeyIdentityProvider stores the id and the root keys as a key/value pair in the key store. Other providers may not store root keys in the same manner and so the `id` parameter may not always be required.
|
|
|
|
Once created, `identities` and the associated `id` can be passed to OrbitDB:
|
|
|
|
```js
|
|
const orbitdb = await createOrbitDB({ identities, id: 'userA' })
|
|
```
|
|
|
|
This identity can now be used by OrbitDB to control access to database actions such as write.
|
|
|
|
## Key Store
|
|
|
|
The key store is a local key manager for OrbitDB and is used to store the private keys generated by `Identities.createIdentity`.
|
|
|
|
[PublicKeyIdentityProvider](https://api.orbitdb.org/PublicKeyIdentityProvider) also uses key store to store the root key which is used to sign the identities created with `Identities.createIdentity`.
|
|
|
|
### Specifying a keystore
|
|
|
|
An existing keystore can be passed to `Identities`:
|
|
|
|
```js
|
|
import { Identities, KeyStore } from '@orbitdb/core'
|
|
|
|
const keystore = await KeyStore()
|
|
const id = 'userA'
|
|
const identities = await Identities({ keystore })
|
|
const identity = identities.createIdentity({ id })
|
|
```
|
|
|
|
### Customizing the key store path
|
|
|
|
There are different ways to customize the location of the key store.
|
|
|
|
To change the keystore using `OrbitDB`, pass a custom directory:
|
|
```js
|
|
// This will create a key store under ./different-path/key-store
|
|
const orbitdb = await createOrbitDB({ directory: './different-path' })
|
|
// Be aware that this will change the base path to the database as well.
|
|
```
|
|
|
|
To change the keystore using the KeyStore function, pass a custom path to the `KeyStore` function:
|
|
```js
|
|
// This will create a key store under ./different-key-store.
|
|
const path = './different-key-store'
|
|
const keystore = await KeyStore({ path })
|
|
|
|
// keystore can now be used with other functions, for example:
|
|
const identities = await Identities({ keystore })
|
|
```
|
|
|
|
To specify a different keystore path using `Identities`, pass a custom path to the `Identities` function:
|
|
```js
|
|
/// This will create a KeyStore under ./different-identities-path
|
|
const path = './different-identities-path'
|
|
const identities = await Identities({ path })
|
|
```
|
|
|
|
## Identity as a linked data object
|
|
|
|
The identity object is stored like any other [IPLD data structure](https://ipld.io/docs/) and can therefore be retrieved from IPFS using the identity's hash:
|
|
|
|
```js
|
|
import { createLibp2p } from 'libp2p'
|
|
import { createHelia } from 'helia' from 'ipfs-core'
|
|
import * as Block from 'multiformats/block'
|
|
import { Identities } from '@orbitdb/core'
|
|
import * as dagCbor from '@ipld/dag-cbor'
|
|
import { sha256 } from 'multiformats/hashes/sha2'
|
|
import { base58btc } from 'multiformats/bases/base58'
|
|
import { CID } from 'multiformats/cid'
|
|
import { Libp2pOptions } from './config/libp2p.js'
|
|
|
|
const libp2p = await createLibp2p(Libp2pOptions)
|
|
const ipfs = await createHelia({ libp2p })
|
|
|
|
const identities = await Identities({ ipfs })
|
|
const identity = await identities.createIdentity({ id: 'me' })
|
|
|
|
const cid = CID.parse(identity.hash, base58btc)
|
|
|
|
// Extract the hash from the full db path.
|
|
const bytes = await ipfs.block.get(cid)
|
|
|
|
// Defines how we serialize/hash the data.
|
|
const codec = dagCbor
|
|
const hasher = sha256
|
|
|
|
// Retrieve the block data, decoding it to human-readable JSON text.
|
|
const { value } = await Block.decode({ bytes, codec, hasher })
|
|
|
|
console.log('identity', value)
|
|
```
|
|
|
|
The resulting output is an object containing the identity information:
|
|
|
|
```js
|
|
{
|
|
id: '031a7bf5f233ad9dccb2a305edfd939f0c54f0ed2e270c4ac390d91ecd33d0c28f',
|
|
type: 'publickey',
|
|
publicKey: '02343cbdd3a5deaacc115f8f241db979f59864aad5b4fbf1561e19d5d04d7b1d14',
|
|
signatures: {
|
|
id: '30440220492ed7bc2945bd6859e96fa929870343bcda188b481248dfa51c7dd7a1eb59ef022049542399338e66454f523dc4033723bc4ff4365f17537171361e128f10703be1',
|
|
publicKey: '30450221008291e9e12d586129de2882e731f286b4168cbed43d2ecf90d8ae9c53e15c56110220204ac640b22e75bf6083a6715a7e6c988659fc08f79022fab8af62563e9fdd67'
|
|
}
|
|
}
|
|
```
|
|
|
|
## Custom identity providers
|
|
|
|
A custom identity provider can be used provided the module takes the following form:
|
|
```javascript
|
|
// A unique name for the identity provider
|
|
const type = 'custom'
|
|
|
|
// check whether the identity was signed by the identity's id.
|
|
const verifyIdentity = identity => {
|
|
// ...
|
|
}
|
|
|
|
// The identity provider.
|
|
const MyCustomIdentityProvider = ({ keystore }) => async () => {
|
|
const getId = async ({ id } = {}) => {
|
|
// return the "root" identity managed by the custom identity provider,
|
|
// eg. a public key or a wallet address
|
|
}
|
|
|
|
const signIdentity = async (publicKeyAndIdSignature) => {
|
|
// sign the publicKeyAndIdSignature using the custom identity provider system
|
|
}
|
|
|
|
return {
|
|
type,
|
|
getId,
|
|
signIdentity
|
|
}
|
|
}
|
|
|
|
MyCustomIdentityProvider.verifyIdentity = verifyIdentity
|
|
MyCustomIdentityProvider.type = type
|
|
|
|
export default MyCustomIdentityProvider
|
|
```
|
|
|
|
To use it, add it to the list of known identity providers:
|
|
|
|
```js
|
|
import { addIdentityProvider } from '@orbitdb/core'
|
|
import MyCustomIdentityProvider from 'my-custom-identity-provider'
|
|
addIdentityProvider(MyCustomIdentityProvider)
|
|
const identity = await createIdentity({ provider: MyCustomIdentityProvider(options) })
|
|
```
|
|
|
|
where my-custom-identity-provider is the custom module.
|