Files
cashId/README.md
T

212 lines
9.4 KiB
Markdown
Raw Normal View History

2018-09-21 18:46:37 +00:00
*Status: Incomplete draft*
2018-09-21 17:04:02 +00:00
# Abstract
2018-09-21 16:52:51 +00:00
2018-09-21 17:04:02 +00:00
CashID is an open protocol that allows secure authentication based on the public key cryptography infrastructure that is currently present in the Bitcoin Cash ecosystem. By authentication we mean to prove to a service provider that we control a specific Bitcoin Cash address by signing a challenge request that links the users address and optional metadata to a task or session with the service provider.
2018-09-21 17:04:02 +00:00
# Motivation
Secure authentication and safe storage of credentials is useful for many things, and with added metadata we enable the following usecases:
* Register to a service as a 1-step process.
* Register to a service automatically as part of a payment.
* Authenticate to a service to login without a password.
* Authenticate to a service to act as 2FA complementing existing passwords.
* Provide access control to locks based on payment.
# Rationale
Passwords is an inherently flawed concept (based on sharing secrets) that is increasingly getting hidden away from the users by means of password managers, 'remember me' and single-signon features. Public key cryptography provides a more secure method for authentication where the users secret is never shared.
The problem with public key infrastructure is that managing private keys securely is complex, but this complexity is now being addressed in the cryptocurrency ecosystem which makes it possible to safely implement a better authentication system.
2018-09-21 17:04:02 +00:00
# Specification
## Workflow
When a user needs to access a restricted area (physically or digitally), they are given a challenge request which can either be transmitted via a QR code, NFC or by any other implementation specific transmission method.
2018-09-21 17:04:02 +00:00
## Request
2018-09-21 19:23:21 +00:00
cashid:domain.tld/command?x=[nonce]&a=[addr]&r=[scope]&o=[scope]
### Parameters
Every request must have a **Nonce** parameter and may also have an **Address**, **Required** and **Optional** parameter.
Letter | Name | Description
--- | --- | ---
x | Nonce | Random data identifying the task or session
a | Address | When present, the service will only accept a reply from this identity
r | Required | List of metadata that the service needs to function
o | Optional | List of metadata that the service can use but still works without
### Metadata
The **Required** and **Optional** parameters allow the service to request personal information from the user. In order to do this in the least amount of space, the information is shorthanded by a letter and a string of numbers representing various pieces of personal information. For **Optional** metadata, the numbers after a letter can be omitted to request all fields in that category. The same metadata fields can only be requested in either **Required** or **Optional** scope, not both. The field numbers in each category has to be listed in sorted order, starting with the lowest number.
2018-09-21 18:06:12 +00:00
**Identification** is represented by the letter **i** followed by a list of numbers corresponding to the following table.
Number | Name | Data type | Description
--- | --- | --- | ---
1 | Name | String | The first / given name
2 | Last name | String | The last / family name
~~3~~ | ~~Middle name~~ | ~~String~~ | ~~Extra names~~
4 | Nickname | String | A nickname or username
5 | Picture | String | URL to a profile picture, or Base64 encoded image
6 | Age | Integer | The number of years the person has lived
7 | Gender | ??? | The sex of the person (I would put the type as Boolean :) But considering the times we are living in, it's probably better be a string...
8 | Birthdate | Date | The date of birth... what format? (YYYY-MM-DD?)
~~9~~ | ~~Identification~~ | ~~string~~ | ~~National identification number~~
2018-09-21 18:06:12 +00:00
**Location** is represented by the letter **l** followed by a list of numbers corresponding to the following table.
Number | Name | Data type | Description
--- | --- | --- | ---
1 | Country | String | Name of the nation
2 | State | String | Name of the state or province
3 | City | String | Name of the city
~~4~~ | ~~District~~ | ~~String~~ | ~~Name of the district, region or neighborhood~~
5 | Postal Code | String | ....
6 | Street Name | String | Name of the street, without the street number
7 | Street Number | String | The street number
8 | Apartment | String | Building or apartment number
9 | GPS | String | Comma-separated list of longitude and latitude (not clear, are multiple pairs allowed?)
2018-09-21 18:06:12 +00:00
2018-09-21 18:06:12 +00:00
**Contact information** is represented by the letter **c** followed by a list of numbers corresponding to the following table.
Number | Name | Data type | Description
--- | --- | --- | ---
1 | Email | String | Email address
2 | IM | String | Instant Messenger protocol handle
3 | Social | string | Social media service handle
4 | Mobile phone number | string | Personal cellphone number
5 | Home phone number | string | Residence phone number
6 | Work phone number | string | Work phone number
### Special commands
The nonce can have a few special values that act as commands:
Value | Description
2018-09-22 00:08:05 +03:00
--- | ---
delete/cancel | Requests the service to delete this user account.
void/invalid/revoke/recall | This identity was compromised and must be disabled.
These commands must be supported at the same endpoint specified in URI, and can be sent unsolicited at any time by the user.
2018-09-21 19:23:21 +00:00
### Request examples
**cashid:example.com/signup?x=95261230581&r=i12l1c1&o=i567l3**
The **signup** command at **example.com** requires **Name**, **Last Name**, **Country** and **Email** to work, and will use **Picture**, **Age**, **Gender** and **City** if provided.
2018-09-21 19:41:07 +00:00
**cashid:bankers.net/verify?x=23563567325&a=qqzafeafd...**
The **verify** command (2FA) at **bankers.net** requires that the address **qqzafeafd...** authenticates
**cashid:cashtalk.org/login?x=13534642624&o=i12**
The **login** command at **cashtalk.org** can make use of **Name** and **Last Name**, for example to update user profiles.
**cashid:cashtalk.org/login?x=delete**
2018-09-21 19:41:07 +00:00
Delete all user data from **cashtalk.org**. This is not sent in response to any requests, but initiated by the user instead.
## Response
Upon receiving the CashID URI described above via QR or other method, the Identity Manager app (IM) needs to show to the user what metadata was requested, which fields are required and which are optional, and allow to select an identity to use for authentication.
After the user selects the identity and approves the required/optional fields, the Identity Manager must sign the URI with the Bitcoin Cash address tied to the selected identity, and send a POST response to the connection point provided in the URI (i.e. to https://example.com/signup). Plain HTTP responses are not allowed.
(NOTE: the original spec just dumps all the data into POST, this is not always convenient, so maybe we should change it to url-encoded POST, like I described below)
The POST response should contain a single a valid JSON object:
Member | Data type | Description
--- | --- | ---
uri | String | The original URI requested.
address | String | Native or CashAddr address used to sign the above URI.
signature | String | Hex-encoded signature.
metadata | String | Requested metadata fields encoded as a JSON object
Metadata is stored as a JSON object with property names matching the requested field names. Fields that has multiple values (for example social media accounts) is stored as a JSON object with property names matching their identifier and the data matching the field description.
For example, if the request contains **r=i12&o=c** the metadata part of the request answer would look like this:
```javascript
metadata:
{
'name': 'John',
'last name': 'Doe',
'email': 'johndoe@gmail.com',
'social':
{
'facebook': 'https://facebook.com/johndoe',
'twitter': 'https://twitter.com/johndoe'
}
}
```
*Note that there is two fields for social media presence and no fields for optional contact data the user did not want to supply*
## Confirmation
The server responds to the POST with a valid JSON object:
Member | Data type | Description
--- | --- | ---
error | String | Textual error description, empty if authentication was successful.
code | Integer | One of the codes described below.
### Error codes
Code | Description (same as 'error' member)
--- | ---
0 | Authentication successful.
1 | Malformed request.
2 | Malformed URI.
3 | Timeout (nonce has expired).
4 | Nonce has been already used (not sure...)
5 | Required metadata is missing. (would be nice to also specify which one...)
6 | Metadata format is not supported (again, would be nice to specify the exact problem...)
7 | Busy, try again later (or Service temporary unavailable).
8 | Signature verification failed.
9 | Access denied for this identity. (can be more detailed ban reason...)
10 | This identity was marked as compromised and cannot be used anymore.
Error codes above 100 are available for custom responses, not specified here. If such a response is received, which IM doesn't recognize, it must simply show the textual error to the user.
# Resources (to-do)
2018-09-21 17:04:02 +00:00
Supply a functional regexp!
* 1: that parses the request string
* 2: that parses the metadata scope
* QR code guidelines (case)
* nonce guidelines (probably alphanumeric, need to see what's good for QR, suggestion for length)
* code examples
* a website with interface/workflow example, similar to BitID
* social integration protocol
* interface guidelines (color-coding privacy impact, etc.)
* What about localization? Are local languages allowed for metadata or not?
* favicon or something more advanced to help identify the site in IM (guideline)