HTTP Messages
A specification for sending/receiving HTTP messages (request/response) via a remote server. Header / Body etc are encrypted, either in the content
(small messages) or via a blossom server (larger requests).
Overview
Enables a local client to make and receive http requests (PUT, POST, GET, PATCH etc) from a remote computer. Requires:
- A trusted machine to process the messages (can be a home PC or Raspberry Pi)
- A relay (can be untrusted)
- A blossom server (can be untrusted)
Architecture
Sequence Diagram
The remote server should periodically scan for expired RESPONSE events (and associated blossom blobs) and delete them.
Event Structure
Example request with a small payload. Payload is in content
and P
tag is the npub of the remote HTTP server.
{
"kind": 21120,
"pubkey": "<pubkey>",
"content": "$encryptedPayload",
"tags": [
["p", "<pubkey of remote server>"], // P tag entry, this is a REQUEST
["key","nip44Encrypt($decryptkey)"],
["r", "https://relay.one"],
["expiration",<unix timestamp>]
],
// other fields...
}
Example response with a large payload. Valid JSON is in content
and E
tag is populated. For privacy, the requestor npub is NOT shown - the requestor instead should be fetching the response using the E
tag.
{
"kind": 21120,
"pubkey": "<pubkey>",
"content": "encrypt({'url':'blossom.one','hash':'xx'},$decryptkey)",
"tags": [
["key","nip44Encrypt($decryptkey)"],
["E", "<request event id>"], // E tag entry, this is a RESPONSE
["expiration",<unix timestamp>]
],
// other fields...
}
Explanations:
kind:21120
- BIP39 word #1120 (message), plus 20,000 to be treated as ephemeral (not stored by relays)."content"
- encrypted JSON with location of blob OR the content itself (if under a threshold). NIP-44 is NOT used as the payload may be large, affecting bunker signing stability."p"
- the pubkey of the remote HTTP server. Indicates that this is a REQUEST."key"
- the decryption key for thecontent
field, also the key for the blossom blob (if used)."E"
- ID of the request event. Enables a response to be identified, and fetched."expiration"
- remote servers should not process requests after this time. Relays SHOULD delete events after this time."r"
- (optional) relay on which the response should be sent. For Requests only.
Considerations
This approach only makes sense in cases where privacy and anonymity are important, or if censorship is a concern.
There are a number of drawbacks to the approach:
- Complexity. Many more moving parts than a direct request.
- Speed. Each request/response now requires:
- Encrypting the payload
- Loading to blossom (if large)
- Signing event
- broadcasting event
- remote server fetching event
- remote server decrypting event
- remote server fetching blossom blob (if large)
- remote server decrypting blossom blob (if used)
- making the actual request
And the same flow in reverse.
So why would you use it? Several reasons:
- enables a plethora of open source apps to be made available from inside private networks (localhost) but over nostr
- maximum server privacy (no domain needed, or port forwarding)
- Make regular API calls over Nostr