Skip to content

Commit

Permalink
3IP: 3ID Library
Browse files Browse the repository at this point in the history
  • Loading branch information
oed committed Jul 15, 2019
1 parent 76dd95b commit e025077
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 2 deletions.
2 changes: 1 addition & 1 deletion 3IPs/3ip-6.md
@@ -1,6 +1,6 @@
---
3ip: 6
title: Authentication methods
title: Authentication Methods
author: oed@3box.io
discussions-to: https://chat.3box.io
status: Draft
Expand Down
138 changes: 138 additions & 0 deletions 3IPs/3ip-7.md
@@ -0,0 +1,138 @@
---
3ip: 7
title: IdentityWallet SDK
author: oed@3box.io
discussions-to: chat.3box.io
status: Draft
created: 2019-06-26
requires: 3, 4, 6
---

## Simple Summary
This 3IP describes the IdentityWallet SDK which is used to create DID compliant identities for 3Box.

## Abstract
The IdentityWallet SDK contains the logic for deriving keys, dealing with authentication, and creating DID documents, it also provides primitives for doing basic access control. This library is intended to be used when interacting with a 3Box, providing functionality for signing updates, encrypting and decrypting data, and signing claims that relates to the users 3Box.

## Motivation
Currently the code for creating and maintaining an identity of a user in 3Box is within the 3box-js library. This was fine for the initial version of 3Box, but as the requirements of different types of wallets and user software varies it's important to be able to separate the code dealing with identity into a separate library. This will for example enable 3Box to be supported more natively by wallets, or be used more easily in an node.js environment where a web3-provider is not available, providing both greater flexibility and better security.

## Specification
Here we separate the specification into two parts, *v0* and *v1*. With *v0* the most critical features are defined, such as HD key derivation, multiple authentication methods, naive signing, and symmetric encryption. Expanding on this *v1* will provide everything needed for a full identity library including DID document creation, asymmetric encryption, and functionality for creating and verifying claims.

### API v0

**constructor ({seed, authSecret, ethereumAddress, authorizeFn })**
The constructor takes optional parameters, however some combination of them are required. When *seed* is passed no additional parameters are required since all keys can be derived using the [HD Path](./3ip-3.md) directly from the seed. If *authSecret* is passed *ethereumAddress* also needs to be passed. The reason for this is that the *ethereumAddress* is used to find the associated 3Box in the network and then the *authSecret* can be used to decrypt the authData. The process is described in greater detail in [Authentication Methods](./3ip-6.md).

**async getAddress ()**
Returns the *ethereumAddress* if it was passed to the constructor, *null* otherwise.

**async authenticate (spaces, { authData })**
This method is called by the 3box-js library to get the public keys associated with a user. The *spaces* parameter is an array of string names of the spaces that are being requested access to. Once it has been called it will remember the spaces that have been authenticated. The format if the return data is the following:

```js
{
ethereumAddress: <the ethereumAddress>
main: {
signingKey: <public signing key>,
encryptionKey: <public encryption key>
},
spaces: {
<space name>: {
signingKey: <public signing key>,
encryptionKey: <public encryption key>
},
}
}
```

If *ethereumAddress* is was not passed to the constructor, a managementKey derived according to the [HD Path](./3ip-3.md) will be returned in it's place.

The optional *authData* parameter is passed along by the 3box-js library if *seed* was not passed to the constructor. The format of this object is an array of encrypted blobs (see [Authentication Methods](./3ip-6.md)).

**async addAuthMethod (authSecret)**
This method can only be called after *authenticate* has been called at least once (i.e. we have access to the decrypted authData). It simply encrypts the authData to the given *authSecret*. If sucessful it also emits an event `'new-auth-method'`.

**signClaim (payload, { DID, space, expiresIn })**
Signs a JWT claim issued by the subDID of the given space. The subDID (see [3ID](./3ip-4.md)) has to be passed since v0 of the IdentityWallet SDK can not generate the DID documents yet.

**encrypt (message, space)**
Encrypts a message with the symmetric encryption key of the given *space*. The *message* needs to be a String.

**decrypt (encryptedBlob, space)**
Decrypts a message with the symmetric encryption key of the given *space*. The *encryptedBlob* needs to be an object with the format `{ ciphertext, nonce }` where both are base64 encoded.

**events.on('new-auth-method', callbackFn)**
Registers a callback function for the `'new-auth-method'` event.

### Usage v0
What follows below is a simplified usage description of this library as it would be used from 3box-js. The purpose of this is to give the reader an intuitive understanding of the changes needed to use the IdentityWallet SDK.

1. To create a 3Box instance `Box.open(<identity>)` is called, where `<identity>` is an instance of the IdentityWallet SDK.
2. Check for rootstore address (and DID) on address server from the address returned from `identity.getAddress()`

#### If no rootstore address is found:
1. The *authenticate* method is called without any *authData*, the IdentityWallet SDK thus randomly generates a new seed and uses this to derive the correct keys
2. A new rootstore is now created with this identity

#### If rootstore address:
1. An orbitdb instace without identity is created and synced with the rootstore address
2. Get authData from rootstore
3. The *authenticate* method is called with the authData
4. Rootstore is now reopened with this new identity

### API v1

#### Updated methods

**constructor ({seed, authSecret, ethereumAddress, authorizeFn })**
There is a new parameter *authorizeFn* that can be passed to the constructor. This function will be called anytime authenticate is called to verify that the requesting dapp is authorized to access the requested spaces. By implementing this function a wallet can implement a custom interface for selective disclosure of data.

**async authenticate (spaces, { authData })**
This method now returns the following data:
```js
{
main: <root DID>,
spaces: {
<space name>: <subDID>
}
}
```

**decrypt (encryptedBlob, space)**
This method now also supports decryption of asymmetrically encrypted data blobs (as encrypted by the **encryptTo** method).

**signClaim (payload, { space, expiresIn })**
Signs a JWT claim issued by the subDID of the given space.

#### New methods

**encryptTo (toDID, message, space)**
Encrypts a message to another user/service identified by a DID. As long as the given *toDID* has a valid public encryption key this method should be able to encrypt a message to this DID.

**handleRPCRequest (request)**
This method allows the IdentityWallet to act as an extension of the Ethereum JSON-rpc or similar systems. Essentially allowing wallets to transparently inject IdentityWallet functionality the same way as web3 functionality is injected into web pages today. It will handle the following methods as RPC requests:

* getAddress
* authenticate
* signOrbitDBKey
* encrypt
* encryptTo
* decrypt
* signClaim

### Usage v1
The general usage is similar to v0, however it should be somewhat easier due to DID documents are created by the IdentityWallet SDK itself. The new `handleRPCRequest` method combined with the `authorizeFn` now also allows wallets to easily support 3Box in a similar way to how they support Ethereum, while also giving users greater control over their data. By using the `encryptTo` method securely encrypted communication can be established between two users, which enhances developers ability to build secure an private applications.

## Rationale
The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.

## Backwards Compatibility
The IdentityWallet SDK is not directly backwards compatible with the current way authentication is done in 3Box. To mitigate this at first the IdentityWallet SDK can be used in parallel with the current authentication system for Ethereum Externally Owned Account. The process for how to migrate these accounts to the new HD Path system will be described in an upcoming 3IP.

## Implementation
No implementation is yet available for this 3IP.

## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
3 changes: 2 additions & 1 deletion 3IPs/README.md
Expand Up @@ -22,4 +22,5 @@ Simply copy [3ip-X.md](./3ip-X.md) and start writing. Once your proposal is read
| [3ID HD Path](./3ip-3.md) | Draft |
| [3ID the 3Box Identity System](./3ip-4.md) | Draft |
| [Address Linking](./3ip-5.md) | Draft |
| [Authentication methods](./3ip-6.md) | Draft |
| [Authentication Methods](./3ip-6.md) | Draft |
| [IdentityWallet SDK](./3ip-7.md) | Draft |

0 comments on commit e025077

Please sign in to comment.