mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-02-11 21:26:20 +00:00
Correct the maximum DID length defined in "serval_types.h" from 32 to 31. Add a definition of the maximum identity Name length and use it instead of the bare constant 64, eg, in the MDP_DNALOOKUP request handling code. Introduce a dataformats.h function for validating an identity name, and use it to validate the 'name' parameter in the CLI 'keyring set' command. Add 'did' and 'name' parameter validation to the GET /restful/keyring/add and GET /restful/keyring/SID/set requests (#131). Rename keyring_set_did() to keyring_set_did_name() and assert that DID and Name lengths have been validated before storing in the keyring. Update the Keyring REST API tech document.
266 lines
11 KiB
Markdown
266 lines
11 KiB
Markdown
Keyring REST API
|
|
================
|
|
[Serval Project][], December 2017
|
|
|
|
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
|
|
API, client applications can add, remove, unlock, lock, query, and modify
|
|
identities in the keyring.
|
|
|
|
Basic concepts
|
|
--------------
|
|
|
|
### Serval ID
|
|
|
|
Every identity in the [Serval mesh network][] is represented by its **Serval
|
|
ID**, (usually abbreviated to [SID][], and formerly known as “Subscriber ID”),
|
|
which is a unique 256-bit public key in the [Curve25519][] *crypto-box* key
|
|
space. The SID is used:
|
|
|
|
* as the network address in the [Serval Mesh network][]
|
|
* to encrypt [MDP][] messages
|
|
* to identify the senders, recipients and authors of [Rhizome bundles][]
|
|
* to identify the parties in a [MeshMS conversation][]
|
|
|
|
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.
|
|
|
|
### 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
|
|
space that is generated by choosing a *secret signing key* at random when the
|
|
the identity is first created. The Signing ID is used:
|
|
|
|
* to prevent forgery of [Serval Mesh network][] routing messages
|
|
* to authenticate non-encrypted [MDP][] messages
|
|
|
|
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.
|
|
|
|
### DID
|
|
|
|
The **DID** ([Dialled Identity][]) is a telephone number, represented as a
|
|
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.
|
|
|
|
### Name
|
|
|
|
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).
|
|
|
|
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.
|
|
|
|
### Rhizome Secret
|
|
|
|
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.
|
|
|
|
### PIN
|
|
|
|
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.
|
|
|
|
### Identity unlocking
|
|
|
|
All Keyring requests can supply a passphrase using the optional **pin**
|
|
parameter, which unlocks all keyring identities protected by that passphrase,
|
|
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
|
|
---------------------------
|
|
|
|
### GET /restful/keyring/identities.json
|
|
|
|
Returns a list of all currently unlocked identities, one identity per row in
|
|
[JSON table][] format. The following parameters are recognised:
|
|
|
|
* **pin**: see [identity unlocking](#identity-unlocking)
|
|
|
|
The table columns are:
|
|
|
|
| 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 |
|
|
|
|
### GET /restful/keyring/add
|
|
|
|
Creates a new identity with a random [SID](#serval-id). The following
|
|
parameters are recognised:
|
|
|
|
* **pin**: 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**: the DID (phone number); empty or absent to indicate no DID,
|
|
otherwise must conform to the rules for [DID](#did)
|
|
* **name**: the name; empty or absent to specify no name, otherwise must
|
|
conform to the rules for [Name](#name)
|
|
|
|
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
|
|
result](#keyring-json-result) describes the identity that was created.
|
|
|
|
### GET /restful/keyring/SID/remove
|
|
|
|
Removes an existing identity with a given [SID](#serval-id). The following
|
|
parameters are recognised:
|
|
|
|
* **pin**: 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 that was removed.
|
|
|
|
### GET /restful/keyring/SID/set
|
|
|
|
Sets and/or clears the [DID](#did) and/or [Name](#name) of the unlocked
|
|
identity that has the given [SID](#serval-id). The following parameters are
|
|
recognised:
|
|
|
|
* **pin**: see [identity unlocking](#identity-unlocking)
|
|
* **did**: the DID (phone number); empty to clear the DID, otherwise must
|
|
conform to the rules for [DID](#did)
|
|
* **name**: the name; empty to clear the name, otherwise must conform to the
|
|
rules for [Name](#name)
|
|
|
|
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].
|
|
|
|
### GET /restful/keyring/SID/lock
|
|
|
|
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.
|
|
|
|
|
|
-----
|
|
**Copyright 2015 Serval Project Inc.**
|
|
**Copyright 2016-2017 Flinders University**
|
|
![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
|
|
[libsodium]: https://libsodium.org/
|
|
[NaCl]: https://nacl.cr.yp.to/
|
|
[SID]: http://developer.servalproject.org/dokuwiki/doku.php?id=content:tech:sid
|
|
[birthday paradox]: http://en.wikipedia.org/wiki/Birthday_problem
|
|
[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
|
|
[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
|
|
[JSON result]: ./REST-API.md#json-result
|
|
[JSON table]: ./REST-API.md#json-table
|
|
[UTF-8]: https://en.wikipedia.org/wiki/UTF-8
|
|
[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
|