2025-03-26 12:05:43 +00:00
2025-03-25 21:20:55 +00:00
2025-03-26 12:05:43 +00:00

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 the content 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
Description
No description provided
Readme 73 KiB