Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ If you are wishing to make a new TEP, please consider our TEP Template: [TEP 0](
|Number|Type|Title|Owner|Type|Status|
|:-:|:-|:-|:-|:-|:-|
[0](/TEP-0000.md)||TEP Template|Constantin Bosse|Process|Active|
[1](/TEP-0001.md)||TEP Purpose and Guidelines|Constantin Bosse|Process|Active|
[1](/TEP-0001.md)||TEP Purpose and Guidelines|Constantin Bosse|Process|Active|
[12](/TEP-0012.md)|Index|One-Sided Passkey Authentication|Cameron Garnham|Standards Track|Draft|
281 changes: 281 additions & 0 deletions TEP-0012.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
|TEP: 00012|One-Sided Passkey Authentication|
|-:|:---|
|__Layer:__|Index|
|__Authors:__|Cameron Garnham|
|__Status:__|Draft|
|__Discussion:__||
|__Type:__|Standards Track|
|__Created:__|2022-08-22|
|__Updated:__||
|__Resolution:__||

# Introduction

## Abstract

This document proposes the use of asymmetric cryptography for user accounts and their authentication.

## Copyright

This document is licensed under the 2-clause BSD licence.

## Motivation

Currently Torrust uses traditional password-username based authentication:

* For every user the server stores a username, salt, and hashed password.
* To login, the client sends their username and password to the server.
* The server looks up the username and gets the salt, salts and hashes the supplied password, and compares it with the hashed password on record.
* If matching, the client is authenticated as that user.

Asymmetric authentication has a number of advantages when compared to password authentication, (assuming the client software is honest):

* No need to send any secret data to the server. In contrast, (hashed and salted) passwords that have to be protected from leakage and misuse.
* Synchronization of user-accounts in a group of federated servers becomes much safer: Instead of sharing hashed-passwords between the servers, (or using some centralized authentication service), the servers only need to synchronise the public-keys, without the risk of leaking secret-data.

The disadvantage:

* The user no longer picks their own password, instead a private key is generated for the user's client software, this key is 32-bytes long and impossible to remember. If the user looses this code, they loose access to their account.

This disadvantage is mitigated by providing the user with a 'backup seed' when they generate their private key, that the user can use to recover their private key.

# Design

We first describe the database and user-structure, and general protocols, then we specify clients generating new private keys, and finally describe the public key authentication protocol.

## Overview

New Users:

1. Client generates secret keys, and derives public key.
2. Client and server preform the Diffie-Hellman authentication protocol.
3. Client creates username, and the public key is associated the username.

Existing Users:

1. Client and server preform the Diffie-Hellman authentication protocol.
2. Client selects username that it wishes to login with.

(There may be more than one username that is associated with the same public key).

## Users

A username is the unique key in the database retaining to the actions of a user. Public keys are associated with users, for a particular purpose. Every public-key-purpose combination has a set of timed status.

```Text
[user]
(PK. String) username

[purposed_public_key]
(PK. public_key || purpose)
(Enum.) purpose
(Binary.) 32-byte-public_key

[status_timed]
(PK. Unique Hashed)
(Enum.) status
(Date-Time. Optional.) beginning
(Date-Time. Optional.) end

[user] many-many [purposed_public_key]

[user][purposed_public_key] many [status_timed]
```

_"Users and Purposed-Public-Keys have a many-many association, each association may associate many timed statuses.":_

* Each _user_ may look up what _purposed public keys_ it is associated with.</br>
Likewise, Each _purposed public key_ may look up what _users_ it is associated with.
* Each _(user <> purposed public key)_ link can look up it's associated _timed statuses_.

### Purposes

In this document we only use the `A` for "Authentication".</br>In the future we may propose additional purposes.

```Text
Purposes (enum):

A: Authentication
```

### Status Validity

If revocation does not specify a beginning, it is for all time periods.</br>
`Active` has the lowest priority: The key must be `created`, and not `expired`, and not `revoked`.

```Text
Status (enum):

A: Active
C: Created
E: Expired
R: Revoked
```

#### Status Validity Table

|status|beginning|end|
|:-|:-|:-|
|active|must|must|
|created|must|none|
|expired|must|none|
|revoked|optional|none|

# Specification

The server maintains a list of public keys that may be used for authentication for each user. A user may propose a new public key be added to their list of authentication keys, or may revoke or expire an existing key.

* To add, or expire, or increase the active period a public key, the user must first authenticate with this new key to prove ownership.
* To revoke, the user may authenticate with the key they wish to revoke.</br>
Or some other form of authentication should be used in the case that the user no-longer has access to their secret key, such as verification by a moderator.

Users who do not have any public key associated, for example new users, or when transitioning from password based authentication should first authenticate with their public key, then preform the association with the user account.

## Mnemonic Codes

Clients generate a mnemonic code according to: [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki).

The seed words are prefixed with an additional `"torrust"` word, and displayed to the user. The 'torrust' seed word is not included in the checksum calculation, however must be present when the user enters their seed in recovery.

Clients must provide an option for the user to give a seed-password in generation and recovery.

### Storage of Mnemonic Code

The client should delete from memory the recovery seed once the user has confirmed that they have backed up the seed, and their key-pair(s) have been generated.

This gives the user some forward security. In the future the user may wish to use the same seed to rotate their keys (for example, when logging in on a new computer). Because the seed is not saved in the client, if the users' client is compromised at a later date, the seed itself remains secret.

## Public and Private Key Derivation

Deriving the keys according to: [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki).

We use the following hardened derivation path:</br>The index is increased in the case the user has rotated their keys, for the moment we only use zero:

```Text
m / purpose' / version' / torrust-purpose' / index'

m / "torrust" / 0 / "authentication" / 0
```

The resulting node is a private-public secp256k1 key-pair. (the same elliptical-curve as is used in bitcoin).

___Note:__ as an extension, the future client may choose to derive and register a series of public keys with the server, i.e. indexes: 0, 1, 2, 3, etc, but delete all except the current key from memory.</br>
This will allow for easier key-rotation in the future, as additional keys cannot be predicted because we use hardened derivation._

### Storage of Derived Keys

In general, it is _not recommended_ that a general user would interact with any derived key material, such as the encoded login credentials. It is recommended that clients store this private data in their (long-term) _localStorage_.

* The client should provide an option to not use any long-term storage, but instead only use their (temporary) _sessionStorage_.
* The client should provide an option to view, backup and manually manage their derived keys.

There are three main reasons why we wish to provide these possibilities to the user:

1. _Public or Shared Computer Login:_ At internet café's or other places with shared computers.
2. _Multi-User-Account:_ Some users may wish to switch accounts on the same computer.
3. _Password-Manager Support:_ Some users prefer to use a password-manager.

## Login Credential Encoding

For encoding the secp256k1, we use [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) encoding, 32-bytes for public keys.</br>
For displaying the login credentials, we use [BIP-350](https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki), 'Bech32m' encoding.

We use the following "Human Readable Parts", or "hrp":

|hrp|description|
|:-|:-|
|"torrust"|for public keys|
|"torrust_secret"|for secret keys|

Upon generation the public and secret keys are stored in the application (either the temporary _sessionStorage_ or the long-term _localStorage_) and may optionally be displayed to the user.

_If displayed to the user, the user should be encouraged to save them in their password manager._

```Text
Login ID: bech32m("torrust",32-byte-public-key)
Login Code: bech32m("torrust_secret",32-byte-private-key)
```

While technically only the private key is needed, we require both as the public key acts as checksum for the private key. This makes it more comfortable for users that are used to traditional password-username based authentication.

## Authentication

The server and client preform Elliptical Curve Diffie-Hellman over the secp256k1 curve to authenticate:

_We use the `secp256k1_ecdh` as defined in [secp256k1_ecdh.h](https://github.com/bitcoin-core/secp256k1/blob/master/include/secp256k1_ecdh.h), see example: [examples/ecdh.c](https://github.com/bitcoin-core/secp256k1/blob/master/examples/ecdh.c)._

___Note:__ This scheme assumes that the client has authenticated the servers' domain using TLS._

* _This scheme is not secure against domain spoofing attacks._

### Protocol

1. Client receives the Server Ephemeral Public Key:</br>
`E_server`

2. Client derives the Ephemeral Common Key using ECDH:</br>
`E_server (dh) e_client = e_common`

3. Client tweaks their User Authentication Keypair with the Ephemeral Common Key:</br>
`A_user + e_common = A'_user`</br>
`a_user + e_common = a'_user`

4. Client derives the Tweaked Common Authentication Key using ECDH:</br>
`E_server (dh) a'_user = a'_common`

5. Client mixes the Servers URI into the Tweaked Authentication Code:</br>
`a'_common (hash) URI_server = A'_auth`

6. Server receives the Client Ephemeral Public Key, Tweaked User Authentication Public Key, Tweaked Authentication Code, and the URI:</br>
`E_client`</br>
`A'_user`</br>
`A'_auth`</br>
`URI_server`

7. Server derives the Common Ephemeral Key using ECDH:</br>
`E_client (dh) e_server = e_common`

8. Server derives the Tweaked Common Authentication Key using ECDH:</br>
`A'_user (dh) e_server = a'_common`

9. Server checks the Tweaked Authentication Code:</br>
`A'_auth == a'_common (hash) URI_server`

10. Server checks the URI:</br>
`URI_server == URI_server`

11. Server untweaks the Tweaked User Authentication Public Key and finds the User Authentication Public Key in its database to confirm the authentication:</br>
`A'_user - e_common = A_user`</br>
`if "A_user" is good, authenticate for the client: "E_client"`

_The server now can issue a session token to the client._

## Security Analysis

This scheme is strong against the passive observer, observable information:

* Existence of the scheme. (Eve can observe that this scheme is happening.)
* The URI of server according to the client. (This could be easily encrypted as an enhancement.)

This scheme is strong against the passive proxy attack:

* If user has the wrong URI according to the server, the authentication will not be successful.

This scheme is strong against man-in-the-middle attacks, except for:

* Leaked User Authentication Public Key. (Malory can trick Alice into revealing her User Authentication Public Key.)
* False Authentication. (Malory can fool Alice into thinking that she has been successfully authenticated.)

Malory is unable to succeed with the man-in-the-middle attack, while he is able to impersonate Bob, he is unable to impersonate Alice, because Bob has a record of Alice's Public Key.

# Compatibility

The updated client will support both login in with the new authentication scheme, and transferring existing users with password authentication to the new scheme.

# Reference Implementations

## Similar Implementations

This scheme is so simple that I guess there should be!

However, the common ones that I have found are far-more complex than what we use here, (such as getting a CA involved with the authentication).