mirror of
https://github.com/vacp2p/specs.git
synced 2026-01-08 23:08:09 -05:00
Address PR comments
This commit is contained in:
@@ -18,21 +18,21 @@ scheme is called `libp2p-PeerID`.
|
||||
|
||||
## Parameters
|
||||
|
||||
| Param Name | Description |
|
||||
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| hostname | The server name used in the TLS connection (SNI). |
|
||||
| challenge-server | The random base64 encoded value the client generates to challenge the server to prove its identity |
|
||||
| challenge-client | The random base64 encoded value the server generates to challenge the client to prove its identity |
|
||||
| sig | A base64 encoded signature. |
|
||||
| peer-id | The peer id of the node that set this parameter. Encoding defined by the [Peer ID spec]. |
|
||||
| public-key | A base64 encoded value of peer's public key. The key itself is encoded per the [Peer ID spec]. |
|
||||
| opaque | An base64 encoded opaque to the client blob generated by the server. If a client receives this it must return it. A server may use this to authenticate statelessly. For example, it could store the challenge-client and a expiry time. |
|
||||
| Param Name | Description |
|
||||
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| hostname | The server name used in the TLS connection (SNI). |
|
||||
| challenge-server | The random quoted string value the client generates to challenge the server to prove its identity |
|
||||
| challenge-client | The random quoted string value the server generates to challenge the client to prove its identity |
|
||||
| sig | A base64 encoded signature. |
|
||||
| peer-id | The Peer ID of the node that set this parameter. Encoding defined by the [Peer ID spec]. |
|
||||
| public-key | A base64 encoded value of peer's public key. The key itself is encoded per the [Peer ID spec]. |
|
||||
| opaque | An base64 encoded value opaque to the client blob generated by the server. If a client receives this it must return it. A server may use this to authenticate statelessly. For example, it could store the challenge-client and a expiry time. |
|
||||
|
||||
Params are encoded per [RFC 9110 auth-param's ABNF](https://datatracker.ietf.org/doc/html/rfc9110#name-collected-abnf). Generally it'll be something like: `hostname="example.com", challenge-server=base64EncodedVal`
|
||||
Params are encoded per [RFC 9110 auth-param's ABNF](https://datatracker.ietf.org/doc/html/rfc9110#name-cmaollected-abnf). Generally it'll be something like: `hostname="example.com", challenge-server="challenge-string"`
|
||||
|
||||
## Signing
|
||||
|
||||
Signatures sign some set of parameters. The parameters are sorted
|
||||
Signatures sign some set of parameters prefixed by the string `libp2p-PeerID`. The parameters are sorted
|
||||
alphabetically, prepended with a varint length prefix, and concatenated together
|
||||
to form the data to be signed. The signing algorithm is defined by the key type
|
||||
used. Refer to the [Peer ID
|
||||
@@ -40,10 +40,10 @@ spec] for
|
||||
specifics on the signing algorithm. The set of parameters is prefixed with the auth scheme "libp2p-PeerID"
|
||||
|
||||
As an example, if we wanted to sign the parameters `hostname="example.com",
|
||||
challenge-client=base64String` we would first structure the parameters as a byte
|
||||
challenge-client="<challenge-string>"` we would first structure the parameters as a byte
|
||||
slice containing:
|
||||
```
|
||||
libp2p-PeerID<varintprefix>challenge-client=<base64String><varintprefix>hostname="example.com"
|
||||
libp2p-PeerID<varintprefix>challenge-client="<challenge-string>"<varintprefix>hostname="example.com"
|
||||
```
|
||||
|
||||
Then sign the resulting byte slice. See the test vectors below for a
|
||||
@@ -52,55 +52,56 @@ examples.
|
||||
|
||||
## Base64 Encoding
|
||||
|
||||
The base64 encoding follows Base 64 Encoding with URL and Filename Safe Alphabet
|
||||
from [RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648#section-5). The
|
||||
reason this is not a multibase is to aid clients or servers who can not or
|
||||
prefer not to import a multibase dependency.
|
||||
The base64 encoding follows Base 64 Encoding with URL and Filename Safe
|
||||
Alphabet from [RFC
|
||||
4648](https://datatracker.ietf.org/doc/html/rfc4648#section-5). Padding MAY be
|
||||
omitted. The reason this is not a multibase is to aid clients or servers who
|
||||
can not or prefer not to import a multibase dependency.
|
||||
|
||||
## Mutual Client and Server Peer ID
|
||||
## Mutual Client and Server Peer ID Authentication
|
||||
|
||||
The following protocol allows both the client and server to authenticate each
|
||||
other's peer id by having them each sign a challenge issued by the other. The
|
||||
other's Peer ID by having them each sign a challenge issued by the other. The
|
||||
protocol operates as follows:
|
||||
|
||||
1. The client makes a POST request to the authentication URI.
|
||||
1. The client makes an HTTP request to an authenticated resource.
|
||||
2. The server responds with status code 401 (Unauthorized) and set the header:
|
||||
```
|
||||
WWW-Authenticate: libp2p-PeerID challenge-client=<base64-encoded-challenge>, opaque=<base64-encoded-opaque-value>
|
||||
WWW-Authenticate: libp2p-PeerID challenge-client="<challenge-string>", opaque="<base64-encoded-opaque-value>"
|
||||
```
|
||||
The opaque parameter is opaque to client. The client MUST return the opaque
|
||||
parameter back to the server. The server MAY use the opaque parameter to
|
||||
encode state.
|
||||
3. The client makes another POST request to the authentication URI and sets the header:
|
||||
3. The client makes another HTTP request to the same authenticated resource and sets the header:
|
||||
```
|
||||
Authorization: libp2p-PeerID peer-id=<string-representation-of-client-peer-id>, opaque=<opaque-from-server>, challenge-server=<base64-encoded-challenge-server>, sig=<base64-signature-bytes>
|
||||
Authorization: libp2p-PeerID peer-id="<string-representation-of-client-peer-id>", opaque="<opaque-from-server>", challenge-server="<challenge-string>"[,encoded-public-key="<base64-encoded-public-key-bytes>" ], sig="<base64-signature-bytes>"
|
||||
```
|
||||
|
||||
The `encoded-public-key` param is optional and represents the client's public key. This is only needed when the client's public key is not included in the PeerID (e.g. not using the "identity" multihash).
|
||||
|
||||
The `sig` param represents a signature over the parameters:
|
||||
- `hostname`
|
||||
- `challenge-client` in its base64 encoded form.
|
||||
- `challenge-client`
|
||||
4. The server MUST verify the signature using the server name used in the TLS
|
||||
session. The server MUST return 401 Unauthorized if the server fails to
|
||||
validate the signature. If the signature is valid, the server has
|
||||
authenticated the client's peer id. The server MUST respond with status code
|
||||
200 (OK) and set the headers:
|
||||
authenticated the client's Peer ID. The server SHOULD proceed to serve the HTTP request. The server MUST set the following response headers:
|
||||
```
|
||||
Authentication-Info: libp2p-PeerID peer-id=<server-peer-id-string>, sig=<base64-signature-bytes>
|
||||
Authorization: libp2p-Bearer <base64-encoded-opaque-blob>
|
||||
Authentication-Info: libp2p-PeerID peer-id="<server-peer-id-string>", sig="<base64-signature-bytes>", libp2p-Bearer <base64-encoded-opaque-blob>
|
||||
```
|
||||
The `sig` param represents a signature over the parameters:
|
||||
- `hostname`
|
||||
- `challenge-server` in its base64 encoded form.
|
||||
- `client` the string representation of the client's Peer ID.
|
||||
- `challenge-server`
|
||||
- `client-pubkey` the bytes of the client's public key
|
||||
|
||||
The `libp2p-Bearer` token allows the client to make peer id authenticated
|
||||
The `libp2p-Bearer` token allows the client to make future Peer ID authenticated
|
||||
requests. The value is opaque to the client, and the server may use it to
|
||||
store authentication state such as:
|
||||
- The client's Peer ID.
|
||||
- The `hostname` parameter.
|
||||
- The token creation date (to allow tokens to expire).
|
||||
5. The client MUST verify the signature. After verification the client has
|
||||
authenticated the server's peer id. The client MUST send the `libp2p-Bearer`
|
||||
authenticated the server's Peer ID. The client MUST send the `libp2p-Bearer`
|
||||
token for Peer ID authenticated requests.
|
||||
|
||||
## libp2p Bearer token
|
||||
@@ -131,21 +132,23 @@ id for the authentication endpoint is `/http-peer-id-auth/1.0.0`.
|
||||
* Implementations MUST only authenticate over a secured connection (i.e. TLS).
|
||||
* Implementations SHOULD limit the maximum length of any variable length field.
|
||||
|
||||
## Note on web PKI
|
||||
## Security Considerations
|
||||
|
||||
Protection against man-in-the-middle (mitm) type attacks is through web PKI. If
|
||||
the client is in an environment where web PKI can not be fully trusted (e.g. an
|
||||
Protection against man-in-the-middle (mitm) type attacks is through Web PKI. If
|
||||
the client is in an environment where Web PKI can not be fully trusted (e.g. an
|
||||
enterprise network with a custom enterprise root CA installed on the client),
|
||||
then this authentication scheme can not protect the client from a mitm attack.
|
||||
|
||||
This authentication scheme is also not secure in cases where you do not own your domain name or the certificate. If someone else can get a valid certificate for your domain, you may be vulnerable to a mitm attack.
|
||||
|
||||
## Test Vectors
|
||||
|
||||
### Definitions used
|
||||
|
||||
- zero key: An ED25519 key initialized with zero bytes.
|
||||
- zero peer id: A peer ID derived from the zero key.
|
||||
- zero Peer ID: A Peer ID derived from the zero key.
|
||||
- client key: An ED25519 key with the following marshalled key (refer to the [Peer ID spec] for how to unmarshal): `080112407e0830617c4a7de83925dfb2694556b12936c477a0e1feb2e148ec9da60fee7d1ed1e8fae2c4a144b8be8fd4b47bf3d3b34b871c3cacf6010f0e42d474fce27e`
|
||||
- client peer ID: A peer id derived from the client key.
|
||||
- client Peer ID: A Peer ID derived from the client key.
|
||||
|
||||
### Walkthrough
|
||||
|
||||
@@ -156,35 +159,34 @@ Included is a concrete example of running the protocol. The client uses the Peer
|
||||
1. The clients sends the initial request.
|
||||
2. The server responds with the header:
|
||||
```
|
||||
WWW-Authenticate: libp2p-PeerID challenge-client=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=, opaque=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
||||
WWW-Authenticate: libp2p-PeerID challenge-client="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", opaque="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
|
||||
```
|
||||
3. The client sends another request with the header:
|
||||
```
|
||||
Authorization: libp2p-PeerID peer-id=12D3KooWBtg3aaRMjxwedh83aGiUkwSxDwUZkzuJcfaqUmo7R3pq, opaque=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=, challenge-server=BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=, sig=F5OBYbbMXoIVJNWrW0UANi7rrbj4GCB6kcEceQjajLTMvC-_jpBF9MFlxiaNYXOEiPQqeo_S56YUSNinwl0ZCQ==
|
||||
Authorization: libp2p-PeerID peer-id=12D3KooWBtg3aaRMjxwedh83aGiUkwSxDwUZkzuJcfaqUmo7R3pq, opaque="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", challenge-server="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=", sig="F5OBYbbMXoIVJNWrW0UANi7rrbj4GCB6kcEceQjajLTMvC-_jpBF9MFlxiaNYXOEiPQqeo_S56YUSNinwl0ZCQ=="
|
||||
```
|
||||
4. The server responds with the header:
|
||||
```
|
||||
Authentication-Info: libp2p-PeerID peer-id=12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN, sig=btLFqW200aDTQqpkKetJJje7V-iDknXygFqPsfiegNsboXeYDiQ6Rqcpezz1wfr8j9h83QkN9z78cAWzKzV_AQ==
|
||||
Authorization: libp2p-Bearer <base64-encoded-bearer-token>
|
||||
Authentication-Info: libp2p-PeerID peer-id="12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN", sig="btLFqW200aDTQqpkKetJJje7V-iDknXygFqPsfiegNsboXeYDiQ6Rqcpezz1wfr8j9h83QkN9z78cAWzKzV_AQ==", libp2p-Bearer <base64-encoded-bearer-token>
|
||||
```
|
||||
|
||||
|
||||
The following table lists out all parameters and intermediate values used in the walkthrough above.
|
||||
|
||||
| Parameter | value |
|
||||
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| hostname | example.com |
|
||||
| challenge-client | `AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=` |
|
||||
| challenge-server | `BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=` |
|
||||
| client peer id | `12D3KooWBtg3aaRMjxwedh83aGiUkwSxDwUZkzuJcfaqUmo7R3pq` |
|
||||
| server's peer id | The zero key `12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN` |
|
||||
| The server's opaque blob | Could be anything. In this example we'll use `CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=`. |
|
||||
| What the client will sign (percent encoded) | `libp2p-PeerID=challenge-client=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=%16hostname=%22example.com%22` |
|
||||
| The client's signature | `F5OBYbbMXoIVJNWrW0UANi7rrbj4GCB6kcEceQjajLTMvC-_jpBF9MFlxiaNYXOEiPQqeo_S56YUSNinwl0ZCQ==` |
|
||||
| The client's Authorization header | `Authorization: libp2p-PeerID peer-id=12D3KooWBtg3aaRMjxwedh83aGiUkwSxDwUZkzuJcfaqUmo7R3pq, opaque=CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=, challenge-server=BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=, sig=F5OBYbbMXoIVJNWrW0UANi7rrbj4GCB6kcEceQjajLTMvC-_jpBF9MFlxiaNYXOEiPQqeo_S56YUSNinwl0ZCQ==` |
|
||||
| What the server will sign (percent encoded) | `libp2p-PeerID=challenge-server=BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=%3Bclient=12D3KooWBtg3aaRMjxwedh83aGiUkwSxDwUZkzuJcfaqUmo7R3pq%16hostname=%22example.com%22` |
|
||||
| The server's signature | `btLFqW200aDTQqpkKetJJje7V-iDknXygFqPsfiegNsboXeYDiQ6Rqcpezz1wfr8j9h83QkN9z78cAWzKzV_AQ==` |
|
||||
| The server's Authentication-Info header | `Authentication-Info: libp2p-PeerID peer-id=12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN, sig=btLFqW200aDTQqpkKetJJje7V-iDknXygFqPsfiegNsboXeYDiQ6Rqcpezz1wfr8j9h83QkN9z78cAWzKzV_AQ==` |
|
||||
| Parameter | value |
|
||||
| ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| hostname | example.com |
|
||||
| challenge-client | `"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="` |
|
||||
| challenge-server | `"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="` |
|
||||
| client Peer ID | `12D3KooWBtg3aaRMjxwedh83aGiUkwSxDwUZkzuJcfaqUmo7R3pq` |
|
||||
| server's Peer ID | The zero key `12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN` |
|
||||
| The server's opaque blob | Could be anything. In this example we'll use `CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=`. |
|
||||
| What the client will sign (percent encoded) | `todo` |
|
||||
| The client's signature | `todo` |
|
||||
| The client's Authorization header | `Authorization: libp2p-PeerID peer-id="12D3KooWBtg3aaRMjxwedh83aGiUkwSxDwUZkzuJcfaqUmo7R3pq", opaque="CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=", challenge-server="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=", sig="F5OBYbbMXoIVJNWrW0UANi7rrbj4GCB6kcEceQjajLTMvC-_jpBF9MFlxiaNYXOEiPQqeo_S56YUSNinwl0ZCQ=="` |
|
||||
| What the server will sign (percent encoded) | `todo` |
|
||||
| The server's signature | `todo` |
|
||||
| The server's Authentication-Info header | `Authentication-Info: libp2p-PeerID peer-id="12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN", sig="btLFqW200aDTQqpkKetJJje7V-iDknXygFqPsfiegNsboXeYDiQ6Rqcpezz1wfr8j9h83QkN9z78cAWzKzV_AQ==", libp2p-Bearer <some-opaque-value>` |
|
||||
|
||||
|
||||
[Peer ID spec]: https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md
|
||||
|
||||
Reference in New Issue
Block a user