2016-02-22 07:11:49 +00:00
|
|
|
Keyring REST API
|
|
|
|
================
|
2017-12-19 02:09:29 +00:00
|
|
|
[Serval Project][], December 2017
|
2016-02-22 07:11:49 +00:00
|
|
|
|
|
|
|
Introduction
|
|
|
|
------------
|
|
|
|
|
|
|
|
The [Serval Mesh network][] is based on [cryptographic identities][] that can
|
|
|
|
easily be created by any node at any time. Each [Serval DNA][] daemon that
|
|
|
|
runs on a node in the network stores its own identities in the [Keyring][], an
|
|
|
|
encrypted store protected by passwords, and gives applications access to the
|
|
|
|
Keyring via the **Keyring REST API** described in this document. Using this
|
2016-11-04 06:30:40 +00:00
|
|
|
API, client applications can add, remove, unlock, lock, query, and modify
|
|
|
|
identities in the keyring.
|
2016-02-22 07:11:49 +00:00
|
|
|
|
2016-11-04 06:30:40 +00:00
|
|
|
Basic concepts
|
|
|
|
--------------
|
2016-02-22 07:11:49 +00:00
|
|
|
|
2016-11-04 06:30:40 +00:00
|
|
|
### Serval ID
|
2016-02-22 07:11:49 +00:00
|
|
|
|
|
|
|
Every identity in the [Serval mesh network][] is represented by its **Serval
|
|
|
|
ID**, (usually abbreviated to [SID][], and formerly known as “Subscriber ID”),
|
2016-11-04 06:30:40 +00:00
|
|
|
which is a unique 256-bit public key in the [Curve25519][] *crypto-box* key
|
2017-11-22 03:25:35 +00:00
|
|
|
space. The SID is used:
|
2016-02-22 07:11:49 +00:00
|
|
|
|
|
|
|
* as the network address in the [Serval Mesh network][]
|
2016-11-04 06:30:40 +00:00
|
|
|
* to encrypt [MDP][] messages
|
2016-02-22 07:11:49 +00:00
|
|
|
* to identify the senders, recipients and authors of [Rhizome bundles][]
|
|
|
|
* to identify the parties in a [MeshMS conversation][]
|
|
|
|
|
2017-11-22 03:25:35 +00:00
|
|
|
The Serval ID public key is derived from the *Serval ID secret key*, which is
|
|
|
|
generated when the identity is first created, and stored in the keyring. The
|
|
|
|
original implementation of [Serval DNA][] generated the *Serval ID secret key*
|
|
|
|
at random, but since the introduction of [combined IDs](#combined-ids), the
|
|
|
|
secret key is derived from the [Serval Signing ID](#serval-signing-id) secret
|
|
|
|
key.
|
|
|
|
|
2016-11-04 06:30:40 +00:00
|
|
|
### Serval Signing ID
|
|
|
|
|
|
|
|
Every identity in the [Serval mesh network][] has a **Serval Signing ID**,
|
|
|
|
which is a unique 256-bit public key in the [Curve25519][] *crypto-sign* key
|
2017-11-22 03:25:35 +00:00
|
|
|
space that is generated by choosing a *secret signing key* at random when the
|
|
|
|
the identity is first created. The Signing ID is used:
|
2016-11-04 06:30:40 +00:00
|
|
|
|
|
|
|
* to prevent forgery of [Serval Mesh network][] routing messages
|
|
|
|
* to authenticate non-encrypted [MDP][] messages
|
|
|
|
|
2017-11-22 03:25:35 +00:00
|
|
|
The large size of the key space means that, as long as the secret key choice
|
|
|
|
is truly random, the [probability of two identities having the same
|
|
|
|
ID][birthday paradox] is negligible, even if billions of identities are
|
|
|
|
generated.
|
|
|
|
|
|
|
|
### Combined IDs
|
|
|
|
|
|
|
|
Since July 2016, [Serval DNA][] generates [Serval ID](#serval-id)s by deriving
|
|
|
|
them from the [Serval Signing ID](#serval-signing-id), so when creating a new
|
|
|
|
identity, only a single secret key is generated at random instead of two. This
|
|
|
|
change was made possible by replacing the [NaCl][] cryptographic library with
|
|
|
|
[libsodium][], which provides a primitive to map keys from the *crypto-sign*
|
|
|
|
key space to the *crypto-box* key space (but not vice versa, which is
|
|
|
|
mathematically impossible).
|
|
|
|
|
|
|
|
These related keys are called *combined IDs*.
|
|
|
|
|
|
|
|
Eventually, the [Serval ID](#serval-id) will be replaced by the [Serval Signing
|
|
|
|
ID](#serval-signing-id) throughout the Serval software and protocols, but will
|
|
|
|
still be called “Serval ID”. The encryption key (in the *crypto-box* key
|
|
|
|
space) will be derived from the signing key on the fly whenever needed, so there
|
|
|
|
will only be one kind of Serval ID, which will be a great simplification.
|
|
|
|
|
2016-11-04 06:30:40 +00:00
|
|
|
### DID
|
|
|
|
|
|
|
|
The **DID** ([Dialled Identity][]) is a telephone number, represented as a
|
2017-12-19 02:09:29 +00:00
|
|
|
string of between 5 and 31 ASCII characters from the set `123456789#0*`. It is
|
|
|
|
used by the [DNA][] protocol to allow [Serval mesh network][] users to discover
|
|
|
|
each other by telephone number; the first step in establishing a mesh voice
|
|
|
|
call.
|
2016-11-04 06:30:40 +00:00
|
|
|
|
|
|
|
### Name
|
|
|
|
|
2017-12-19 02:09:29 +00:00
|
|
|
The **Name** is a short, unstructured string between 1 and 63 bytes in length,
|
|
|
|
assigned by a human user to an identity. It is used to represent the identity
|
|
|
|
to human users, as it is more recognisable than a hexadecimal [SID](#serval-id)
|
|
|
|
or a [DID](#did) (telephone number).
|
2016-11-04 06:30:40 +00:00
|
|
|
|
2017-12-19 02:09:29 +00:00
|
|
|
Serval DNA does not interpret the name, merely stores it, so the name may use
|
|
|
|
any encoding on which all clients agree, such as ASCII or [UTF-8][]. Since it
|
|
|
|
is intended for human consumption, it is recommended that it contain only
|
|
|
|
printable characters, that it contain no carriage-motion characters (eg, TAB
|
|
|
|
U+0009 or LF U+0010), and that it not start or end with white space, but Serval
|
|
|
|
DNA does not enforce any such rules. The only restriction enforced by Serval
|
|
|
|
DNA is that it contain no zero bytes.
|
2016-11-04 06:30:40 +00:00
|
|
|
|
|
|
|
### Rhizome Secret
|
2016-02-22 07:11:49 +00:00
|
|
|
|
|
|
|
The *Rhizome Secret* is a secret key, separate from the [SID](#serval-id)
|
|
|
|
secret, that is generated randomly for each new identity, and stored in the
|
|
|
|
keyring as part of the identity. The Rhizome Secret is used to securely encode
|
|
|
|
the [Bundle Secret][] of a bundle into its [manifest][], in the form of the
|
|
|
|
[Bundle Key][], thus relieving [Rhizome][] applications of the burden of having
|
|
|
|
to store and protect Bundle Secrets themselves.
|
|
|
|
|
2016-11-04 06:30:40 +00:00
|
|
|
### PIN
|
2016-02-22 07:11:49 +00:00
|
|
|
|
|
|
|
When an identity is created, it can optionally be given a PIN (passphrase). If
|
|
|
|
the PIN is *empty* then the identity is permanently unlocked (visible).
|
|
|
|
|
|
|
|
Identities with a non-empty PIN are stored encrypted in the keyring file.
|
|
|
|
Inspection of the keyring file will not reveal their presence unless the
|
|
|
|
correct PIN is supplied, because all unused entries in the keyring file are
|
|
|
|
filled with pseudo-random content that is indistinguishable from encrypted
|
|
|
|
identities.
|
|
|
|
|
|
|
|
If a PIN is lost and forgotten, then the identity (identities) it unlocks will
|
|
|
|
remain locked and unusable forever. There is no “master PIN” or back-door.
|
|
|
|
|
2016-11-04 06:30:40 +00:00
|
|
|
### Identity unlocking
|
2016-02-22 07:11:49 +00:00
|
|
|
|
2016-11-04 06:30:40 +00:00
|
|
|
All Keyring requests can supply a passphrase using the optional **pin**
|
2017-12-19 02:09:29 +00:00
|
|
|
parameter, which unlocks all keyring identities protected by that passphrase,
|
2016-11-04 06:30:40 +00:00
|
|
|
prior to performing the request. Serval DNA caches every PIN it receives until
|
|
|
|
the PIN is revoked using the [lock request](#get-restful-keyring-lock), so once
|
|
|
|
an identity is unlocked, it remains visible until explicitly locked.
|
|
|
|
|
|
|
|
Keyring REST API common features
|
|
|
|
--------------------------------
|
|
|
|
|
|
|
|
### Keyring JSON result
|
|
|
|
|
|
|
|
All Keyring requests relating to a single identity that do not produce a
|
|
|
|
special response content for the outcome, return the following augmented [JSON
|
|
|
|
result][] object as the HTTP response content:
|
|
|
|
|
|
|
|
{
|
|
|
|
"http_status_code": ...,
|
|
|
|
"http_status_message": "...",
|
|
|
|
"identity": {
|
|
|
|
"sid": "<hex64>",
|
|
|
|
"identity": "<hex64>",
|
|
|
|
"did": "...",
|
|
|
|
"name": "..."
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
* the `sid` field is the [SID](#serval-id); a string containing 64 uppercase
|
|
|
|
hexadecimal digits
|
|
|
|
* the `identity` field is the [Signing Id](#serval-signing-id); a string
|
|
|
|
containing 64 uppercase hexadecimal digits
|
|
|
|
* the `did` field is the string [DID](#did); omitted if the identity has no DID
|
|
|
|
* the `name` field is the string [Name](#name); omitted if the identity has no
|
|
|
|
name
|
|
|
|
|
|
|
|
Keyring REST API operations
|
|
|
|
---------------------------
|
2016-02-22 07:11:49 +00:00
|
|
|
|
|
|
|
### GET /restful/keyring/identities.json
|
|
|
|
|
2017-12-19 02:09:29 +00:00
|
|
|
Returns a list of all currently unlocked identities, one identity per row in
|
|
|
|
[JSON table][] format. The following parameters are recognised:
|
|
|
|
|
2018-03-08 00:25:36 +00:00
|
|
|
* **pin** (optional) = a passphrase to unlock identities prior to listing;
|
|
|
|
see [identity unlocking](#identity-unlocking)
|
2017-12-19 02:09:29 +00:00
|
|
|
|
2016-02-22 07:11:49 +00:00
|
|
|
The table columns are:
|
|
|
|
|
2017-12-19 02:09:29 +00:00
|
|
|
| heading | content |
|
|
|
|
|:---------- |:------------------------------------------------------------------------- |
|
|
|
|
| `sid` | the [SID](#serval-id), a string of 64 uppercase hex digits |
|
|
|
|
| `identity` | the [Signing ID](#serval-signing-id), a string of 64 uppercase hex digits |
|
|
|
|
| `did` | the optional [DID](#did) (telephone number); `null` if none is assigned |
|
|
|
|
| `name` | the optional string [Name](#name); `null` if none is assigned |
|
2016-02-22 07:11:49 +00:00
|
|
|
|
2018-03-08 00:25:36 +00:00
|
|
|
### POST /restful/keyring/add
|
2016-02-22 07:11:49 +00:00
|
|
|
|
2018-03-08 00:25:36 +00:00
|
|
|
Creates a new identity with a random [SID](#serval-id). This request does not
|
|
|
|
accept parameters in the request body (eg, using a [Content-Type][] of
|
|
|
|
[multipart/form-data][]), but does accept the following [query parameters][] in
|
|
|
|
the *path*:
|
2017-12-19 02:09:29 +00:00
|
|
|
|
2018-03-08 00:25:36 +00:00
|
|
|
* **pin** (optional) = the passphrase for the new identity; if present, then
|
|
|
|
the new identity is protected by the given passphrase; see [identity
|
|
|
|
unlocking](#identity-unlocking) -- note that the newly created identity is
|
|
|
|
already unlocked when this request returns, because the passphrase has been
|
|
|
|
added to the PIN cache
|
|
|
|
|
|
|
|
* **did** (optional) = the [DID](#did) of the new identity; empty or absent
|
|
|
|
to indicate no DID, otherwise must be valid
|
|
|
|
|
|
|
|
* **name** (optional) = the [Name](#name) of the new identity; empty or
|
|
|
|
absent to specify no name, otherwise must be valid
|
2016-02-22 07:11:49 +00:00
|
|
|
|
2017-12-19 02:09:29 +00:00
|
|
|
If any parameter contains an invalid value then the request returns [400 Bad
|
|
|
|
Request][400]. Returns [201 Created][201] if an identity is created; the [JSON
|
2016-11-04 06:30:40 +00:00
|
|
|
result](#keyring-json-result) describes the identity that was created.
|
|
|
|
|
2018-03-08 00:25:36 +00:00
|
|
|
### GET /restful/keyring/SID
|
|
|
|
|
|
|
|
Return the details of an existing unlocked identity with a given
|
|
|
|
[SID](#serval-id). The following [query parameters][] are recognised:
|
|
|
|
|
|
|
|
* **pin** (optional) = a passphrase to unlock the identity prior to querying
|
|
|
|
it; see [identity unlocking](#identity-unlocking)
|
|
|
|
|
|
|
|
If there is no unlocked identity with the given SID, this request returns [404
|
|
|
|
Not Found][404]. Otherwise it returns [200 OK][200] and the [JSON
|
|
|
|
result](#keyring-json-result) describes the identity.
|
|
|
|
|
|
|
|
### DELETE /restful/keyring/SID
|
2016-11-04 06:30:40 +00:00
|
|
|
|
2018-03-08 00:25:36 +00:00
|
|
|
Removes an existing unlocked identity with a given [SID](#serval-id). The
|
|
|
|
following [query parameters][] are recognised:
|
2017-12-19 02:09:29 +00:00
|
|
|
|
2018-03-08 00:25:36 +00:00
|
|
|
* **pin** (optional) = a passphrase to unlock the identity prior to deleting
|
|
|
|
it; see [identity unlocking](#identity-unlocking)
|
2016-11-04 06:30:40 +00:00
|
|
|
|
|
|
|
If there is no unlocked identity with the given SID, this request returns [404
|
|
|
|
Not Found][404]. Otherwise it returns [200 OK][200] and the [JSON
|
|
|
|
result](#keyring-json-result) describes the identity that was removed.
|
|
|
|
|
2018-03-08 00:25:36 +00:00
|
|
|
### PATCH /restful/keyring/SID
|
2016-02-22 07:11:49 +00:00
|
|
|
|
2017-12-19 02:09:29 +00:00
|
|
|
Sets and/or clears the [DID](#did) and/or [Name](#name) of the unlocked
|
2018-03-08 00:25:36 +00:00
|
|
|
identity that has the given [SID](#serval-id). The following [query
|
|
|
|
parameters][] are recognised:
|
|
|
|
|
|
|
|
* **pin** (optional) = a passphrase to unlock the identity prior to deleting
|
|
|
|
it; see [identity unlocking](#identity-unlocking)
|
|
|
|
|
|
|
|
* **did** (optional) = the [DID](#did) to assign to the identity; empty to
|
|
|
|
clear the DID, otherwise must be valid
|
2016-02-22 07:11:49 +00:00
|
|
|
|
2018-03-08 00:25:36 +00:00
|
|
|
* **name** (optional) = the [Name](#name) to assign to the identity; empty to
|
|
|
|
clear the name, otherwise must be valid
|
2016-02-22 07:11:49 +00:00
|
|
|
|
2016-10-25 05:46:08 +00:00
|
|
|
If a parameter is missing, then the corresponding field of the identity is left
|
|
|
|
unchanged. If a parameter is set to an empty string, then the corresponding
|
|
|
|
field of the identity is erased.
|
|
|
|
|
2017-12-19 02:09:29 +00:00
|
|
|
If any parameter contains an invalid value then the request returns [400 Bad
|
|
|
|
Request][400]. If there is no unlocked identity with the given SID, this
|
|
|
|
request returns [404 Not Found][404].
|
2016-02-22 07:11:49 +00:00
|
|
|
|
2018-03-08 00:25:36 +00:00
|
|
|
### PUT /restful/keyring/SID/lock
|
2016-11-04 06:30:40 +00:00
|
|
|
|
|
|
|
Locks an existing identity with a given [SID](#serval-id).
|
|
|
|
|
|
|
|
If there is no unlocked identity with the given SID, this request returns [404
|
|
|
|
Not Found][404]. Otherwise it returns [200 OK][200] and the [JSON
|
|
|
|
result](#keyring-json-result) describes the identity that was locked.
|
|
|
|
|
2016-02-22 07:11:49 +00:00
|
|
|
|
|
|
|
-----
|
|
|
|
**Copyright 2015 Serval Project Inc.**
|
2018-03-08 00:25:36 +00:00
|
|
|
**Copyright 2016-2018 Flinders University**
|
2016-02-22 07:11:49 +00:00
|
|
|
![CC-BY-4.0](./cc-by-4.0.png)
|
|
|
|
Available under the [Creative Commons Attribution 4.0 International licence][CC BY 4.0].
|
|
|
|
|
|
|
|
|
|
|
|
[Serval Project]: http://www.servalproject.org/
|
|
|
|
[CC BY 4.0]: ../LICENSE-DOCUMENTATION.md
|
|
|
|
[Serval Mesh network]: http://developer.servalproject.org/dokuwiki/doku.php?id=content:tech:mesh_network
|
|
|
|
[Serval DNA]: ../README.md
|
|
|
|
[REST-API]: ./REST-API.md
|
|
|
|
[Keyring]: http://developer.servalproject.org/dokuwiki/doku.php?id=content:tech:keyring
|
|
|
|
[cryptographic identities]: http://developer.servalproject.org/dokuwiki/doku.php?id=content:tech:security_framework
|
|
|
|
[Curve25519]: https://en.wikipedia.org/wiki/Curve25519
|
2017-11-22 03:25:35 +00:00
|
|
|
[libsodium]: https://libsodium.org/
|
|
|
|
[NaCl]: https://nacl.cr.yp.to/
|
2016-02-22 07:11:49 +00:00
|
|
|
[SID]: http://developer.servalproject.org/dokuwiki/doku.php?id=content:tech:sid
|
2017-11-22 03:25:35 +00:00
|
|
|
[birthday paradox]: http://en.wikipedia.org/wiki/Birthday_problem
|
2016-11-04 06:30:40 +00:00
|
|
|
[Dialled Identity]: http://developer.servalproject.org/dokuwiki/doku.php?id=content:tech:did
|
|
|
|
[DNA]: http://developer.servalproject.org/dokuwiki/doku.php?id=content:tech:dna
|
|
|
|
[MDP]: ./Mesh-Datagram-Protocol.md
|
2016-02-22 07:11:49 +00:00
|
|
|
[Rhizome]: ./REST-API-Rhizome.md
|
|
|
|
[Rhizome bundles]: ./REST-API-Rhizome.md#bundle
|
|
|
|
[manifest]: ./REST-API-Rhizome.md#manifest
|
|
|
|
[Bundle Secret]: ./REST-API-Rhizome.md#bundle-secret
|
|
|
|
[Bundle Key]: ./REST-API-Rhizome.md#bundle-key
|
|
|
|
[MeshMS conversation]: ./REST-API-MeshMS.md#conversation
|
2016-11-04 06:30:40 +00:00
|
|
|
[JSON result]: ./REST-API.md#json-result
|
2016-02-22 07:11:49 +00:00
|
|
|
[JSON table]: ./REST-API.md#json-table
|
2016-11-04 06:30:40 +00:00
|
|
|
[UTF-8]: https://en.wikipedia.org/wiki/UTF-8
|
2016-02-22 07:11:49 +00:00
|
|
|
[200]: ./REST-API.md#200-ok
|
|
|
|
[201]: ./REST-API.md#201-created
|
|
|
|
[202]: ./REST-API.md#202-accepted
|
|
|
|
[400]: ./REST-API.md#400-bad-request
|
|
|
|
[404]: ./REST-API.md#404-not-found
|
|
|
|
[419]: ./REST-API.md#419-authentication-timeout
|
|
|
|
[422]: ./REST-API.md#422-unprocessable-entity
|
|
|
|
[423]: ./REST-API.md#423-locked
|
|
|
|
[500]: ./REST-API.md#500-server-error
|