mirror of
https://github.com/vacp2p/specs.git
synced 2026-01-08 23:08:09 -05:00
domain separation, remove CID and local storage
This commit is contained in:
@@ -20,6 +20,27 @@ would be nice to have an all-purpose data container that includes a signature of
|
||||
the data, so we can verify that the data came from a specific peer and that it hasn't
|
||||
been tampered with.
|
||||
|
||||
## Domain Separation
|
||||
|
||||
Signatures can be used for a variety of purposes, and a signature made for a
|
||||
specific purpose MUST NOT be considered valid for a different purpose.
|
||||
|
||||
Without this property, an attacker could convince a peer to sign a paylod in one
|
||||
context and present it as valid in another, for example, presenting a signed
|
||||
address record as a pubsub message.
|
||||
|
||||
We separate signatures into "domains" by prefixing the data to be signed with a
|
||||
string unique to each domain. This string is not contained within the payload or
|
||||
the outer envelope structure. Instead, each libp2p subystem that makes use of
|
||||
signed envelopes will provide their own domain string when constructing the
|
||||
envelope, and again when validating the envelope. If the domain string used to
|
||||
validate is different from the one used to sign, the signature validation will
|
||||
fail.
|
||||
|
||||
Domain strings may be any valid UTF-8 string, but MUST NOT contain the `:`
|
||||
character (UTF-8 code point `0x3A`), as this is used to separate the domain
|
||||
string from the content when signing.
|
||||
|
||||
## Wire Format
|
||||
|
||||
Since we already have a [protobuf definition for public keys][peer-id-spec], we
|
||||
@@ -29,10 +50,8 @@ can use protobuf for this as well and easily embed the key in the envelope:
|
||||
```protobuf
|
||||
message SignedEnvelope {
|
||||
PublicKey publicKey = 1; // see peer id spec for definition
|
||||
string purpose = 2; // arbitrary user-defined string for context
|
||||
bytes cid = 3; // CIDv1 of contents
|
||||
bytes contents = 4; // payload
|
||||
bytes signature = 5; // signature of purpose + cid + contents
|
||||
bytes contents = 2; // payload
|
||||
bytes signature = 3; // signature of domain string + contents
|
||||
}
|
||||
```
|
||||
|
||||
@@ -40,27 +59,13 @@ The `publicKey` field contains the public key whose secret counterpart was used
|
||||
to sign the message. This MUST be consistent with the peer id of the signing
|
||||
peer, as the recipient will derive the peer id of the signer from this key.
|
||||
|
||||
The `purpose` field is an aribitrary string that can be used to give some hint
|
||||
as to the contents. For example, if `contents` contains a serialized
|
||||
`AddressState` record, `purpose` might contain the string `"AddressState"`. The
|
||||
contents of the ``purpose`` field are signed alongside `contents` to prevent
|
||||
tampering, and may be empty if desired.
|
||||
|
||||
The `cid` field contains a version 1 [CID][cid] (content id) that corresponds to
|
||||
the `content` field. It's used for retrieving messages from [local
|
||||
storage](#local-storage-of-signed-envelopes), and the embedded multicodec also
|
||||
gives a hint as to the data type of the `contents`. If the user does not specify
|
||||
a multicodec when constructing the envelope, the default will be
|
||||
[`raw`](https://github.com/multiformats/multicodec/blob/master/table.csv#L34)
|
||||
for raw binary.
|
||||
|
||||
## Signature Production / Verification
|
||||
|
||||
When signing, a peer will prepare a buffer by concatenating the following:
|
||||
|
||||
- The string `"libp2p-signed-envelope:"`, encoded as UTF-8
|
||||
- The `purpose` field, encoded as UTF-8
|
||||
- The `cid` field
|
||||
- The [domain separation string](#domain-separation), encoded as UTF-8
|
||||
- The UTF-8 encoded `:` character
|
||||
- The `contents` field
|
||||
|
||||
Then they will sign the buffer according to the rules in the [peer id
|
||||
@@ -70,25 +75,5 @@ To verify, a peer will "inflate" the `publicKey` into a domain object that can
|
||||
verify signatures, prepare a buffer as above and verify the `signature` field
|
||||
against it.
|
||||
|
||||
## Local Storage of Signed Envelopes
|
||||
|
||||
Signed envelopes can be used for ephemeral data, but we may also want to persist
|
||||
them for a while and / or make previously recieved envelopes accesible to
|
||||
various libp2p modules.
|
||||
|
||||
For example, if the envelope contains an [address record][addr-records-rfc],
|
||||
those records might be used to populate a peer store with self-certified
|
||||
records. Rather than requiring the peer store to persist the full envelope, we
|
||||
could have a separate "envelope storage" service that keeps signed messages
|
||||
around for future reference.
|
||||
|
||||
The peer store can then just store the `cid` alongside a flag that indicates
|
||||
that the address came from a trusted source. If we're using a persistent peer
|
||||
store and the process restarts, we can look up the stored `cid` in the envelope
|
||||
storage and verify the signature again.
|
||||
|
||||
If we decide to build this, the storage service should have some kind of garbage
|
||||
collection / TTL scheme to avoid unbounded growth.
|
||||
|
||||
[addr-records-rfc]: ./0003-address-records.md
|
||||
[peer-id-spec]: ../peer-ids/peer-ids.md
|
||||
|
||||
Reference in New Issue
Block a user