| title | Routing V1 HTTP Delegated Routing Reader Privacy Upgrade | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| description | This specification describes Delegated Routing Reader Privacy Upgrade. It's an incremental improvement to HTTP Delegated Routing API and inherits all of its formats and design rationale. | ||||||||||||||||||||
| date | 2023-05-31 | ||||||||||||||||||||
| maturity | reliable | ||||||||||||||||||||
| editors |
|
||||||||||||||||||||
| order | 0 | ||||||||||||||||||||
| tags |
|
This specification describes a new HTTP API for Privacy Preserving Delegated Content Routing provider lookups. It's an extension to HTTP Delegated Routing API and inherits all of its formats and design rationale.
All salts below are 64-bytes long, and represent a string padded with \x00.
SALT_DOUBLEHASH = bytes("CR_DOUBLEHASH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")SALT_ENCRYPTIONKEY = bytes("CR_ENCRYPTIONKEY\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")SALT_NONCE = bytes("CR_NONCE\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
encis AESGCM encryption. The following notation will be used for the rest of the specificationenc(passphrase, nonce, payload).hashis SHA256 hashing.||is concatenation of two values.deriveKeyis deriving a 32-byte encryption key from a passphrase that is done ashash(SALT_ENCRYPTIONKEY || passphrase).Nonceis a 12-byte nonce used as Initialization Vector (IV) for the AESGCM encryption. IPNI expects an explicit instruction to delete a record (comparing to the DHT where records expire). Hence the IPNI server needs to be able to compare encrypted values without having to decrypt them as that would require a key that it is unaware of. That means that the nonce has to be deterministically chosen so thatenc(passphrase, nonce, payload)produces the same output for the samepasspharase+payloadpair. Nonce must be calculated ashash(SALT_NONCE || passphrase || len(payload) || payload)[:12], wherelen(payload)is an 8-byte length of thepayloadencoded in Little Endian format. Choice of nonce is not enforced by the IPNI specification. The described approach will be used while IPNI encrypts Advertisements on behaf of Publishers. However once Writer Privacy is implemented, the choice of nonce will be left up to the Publisher.CIDis the Content IDentifier.MHis the Multihash contained in aCID. It corresponds to the digest of a hash function over some content.MHis represented as a 32-byte array.HASH2is a second hash over the multihash. Second Hashes must be ofMultihashformat withDBL_SHA_256codec. The digest must be calculated ashash(SALT_DOUBLEHASH || MH).ProviderRecordis a Provider Record as described in the HTTP Delegated Routing Specification.ProviderRecordKeyis a concatentation ofpeerID || contextID. There is no need for explicitly encoding lengths as they are already encoded as a part of the multihash format.EncProviderRecordKeyisNonce || enc(deriveKey(multihash), Nonce, ProviderRecordKey).HashProviderRecordKeyis a hash overProviderRecordKeythat must be calculated ashash(SALT_DOUBLEHASH || ProviderRecordKey).Metadatais free form bytes that can represent such information such as IPNI metadata.EncMetadataisNonce || enc(deriveKey(ProviderRecordKey), Nonce, Metadata).
Assembling a full ProviderRecord from the encrypted data will require multiple roundtrips to the server. The first one to fetch a list of EncProviderRecordKeys and then one per
EncProviderRecordKey to fetch EncMetadata. In order to reduce the number of roundtrips to one the client implementation should use the local libp2p peerstore for multiaddress discovery
and libp2p multistream select for protocol negotiation.
200(OK): the response body contains 0 or more records404(Not Found): must be returned if no matching records are found422(Unprocessable Entity): request does not conform to schema or semantic constraints
{
"EncProviderRecordKeys": [
"EBxdYDhd.....",
"IOknr9DK.....",
]
}Where:
EncProviderRecordKeysa list of base58 encodedEncProviderRecordKey;
200(OK): the response body contains 1 record404(Not Found): must be returned if no matching records are found422(Unprocessable Entity): request does not conform to schema or semantic constraints
{
"EncMetadata": "EBxdYDhd....."
}Where:
EncMetadatasis base58 encodedEncMetadata;