Skip to content

Latest commit

 

History

History
189 lines (132 loc) · 7.11 KB

File metadata and controls

189 lines (132 loc) · 7.11 KB

ORE-08

The /compromised/pubkeys Endpoint

draft optional

This document defines the /compromised/pubkeys endpoint, which accepts a list of pubkeys and returns compromise records for any of them whose private key is known or suspected to have been compromised.


Background

A Nostr identity is fully controlled by its private key. If a private key is compromised, anyone who obtains it can impersonate that identity indefinitely. There is no revocation mechanism in Nostr; the only recourse is (manual) key rotation.

Some forms of compromise are detectable. A publicly posted nsec can be found by crawling Nostr events and verified cryptographically. Other forms can be inferred from heuristic signals, or attested by third parties using Nostr events. Providers that index Nostr events can surface these signals to clients, enabling them to warn users before they interact with a compromised identity.

Endpoint

POST /compromised/pubkeys

Accepts a list of pubkeys and returns a compromise record for each one that is known or suspected to be compromised. Pubkeys with no known compromise are omitted from the response.

Result Classes

Compromise results fall into two classes depending on the algorithm that produced them.

Confirmed Result

Produced by deterministic algorithms. The compromise is backed by a cryptographic proof that any verifier can check independently.

Field Type Required Description
status string yes Always "confirmed".
detected_at integer no Unix timestamp of when the provider first detected the compromise.
proof string yes A cryptographic proof of the compromise. See The signature-proof Algorithm.
{
  "status": "confirmed",
  "detected_at": 1700000000,
  "proof": "2a9f3c..."
}

Suspected Result

Produced by probabilistic algorithms. The compromise is inferred from heuristic signals without a cryptographic proof.

Field Type Required Description
status string yes Always "suspected".
detected_at integer no Unix timestamp of when the provider first detected the compromise.
confidence number yes A probability between 0.0 and 1.0 expressing the provider's confidence that the key is compromised.
{
  "status": "suspected",
  "detected_at": 1701000000,
  "confidence": 0.87
}

Algorithm Classes

Deterministic Algorithms

Deterministic algorithms MUST only return Confirmed Results. Every result they emit is backed by a verifiable proof. Clients MAY verify each proof independently.

Probabilistic Algorithms

Probabilistic algorithms MAY return both Confirmed Results and Suspected Results. Providers are free to define their own heuristics, signal sources, and confidence thresholds. Clients SHOULD treat Suspected Results as advisory and let users decide how to act on them.

Probabilistic algorithms MAY require a pov pubkey to personalize results. A personalized algorithm can weight signals by how much the point-of-view identity trusts their source, for example, prioritizing compromise attestations made by pubkeys the user follows.

Capability Document

Providers that implement this endpoint MUST advertise it in the capability document as defined in ORE-01. The following example shows a provider offering both the standard signature-proof algorithm and a custom probabilistic algorithm.

{
  "/compromised/pubkeys": [
    {
      "id": "signature-proof",
      "name": "Cryptographic Proof",
      "description": "Returns only confirmed compromises backed by a verifiable Schnorr signature."
    },
    {
      "id": "heuristic-wot-v1",
      "name": "Web of Trust Heuristic Detection",
      "description": "Returns confirmed and suspected compromises using third-party attestations from pubkeys trusted by the provided pov.",
      "pov": true
    }
  ]
}

The signature-proof Algorithm

signature-proof is the standard deterministic algorithm defined by this ORE. All providers that implement it MUST follow the specification below exactly, ensuring that results are interoperable and independently verifiable across providers.

Proof Construction

The proof is a Schnorr signature over a fixed message, produced using the compromised private key. This allows any client to verify the claim using only the public key.

The message to sign is the UTF-8 string:

this-key-was-compromised-<pubkey>

where <pubkey> is the 64-character lowercase hex encoding of the public key corresponding to the compromised private key.

The proof is the resulting 64-byte Schnorr signature, encoded as a 128-character lowercase hex string.

Proof Verification

To verify a proof, a client MUST:

  1. Reconstruct the message: this-key-was-compromised-<pubkey>, using the pubkey from the response key.
  2. Verify the Schnorr signature in proof against that message using the same pubkey.

If verification fails, the client MUST discard the result and SHOULD treat the provider response as untrustworthy.

Providers MUST verify each proof before returning it. Providers MUST NOT emit a result with status: "confirmed" without a valid proof.

Request

Field Type Required Description
pubkeys array of strings yes The pubkeys to check. MUST contain at least one element. Each pubkey MUST follow the format defined in ORE-00.
algorithm string no The algorithm to use. If omitted, the provider MUST use the default algorithm for this endpoint as defined in ORE-01.

Request size

Clients SHOULD NOT send more than 1000 pubkeys in a single request. Providers MAY enforce their own limit and SHOULD respond with 413 Payload Too Large if the request exceeds it.

Example Request

{
  "pubkeys": [
    "a3f9c...",
    "b7e2d...",
    "cc481..."
  ],
  "algorithm": "heuristic-v1"
}

Response

The response is a flat JSON object mapping each pubkey with a known or suspected compromise to its result object. Pubkeys with no known compromise are omitted. If no compromises are known for any of the requested pubkeys, the response MUST be an empty object.

The shape of each result object depends on its status field, as defined in Result Classes.

Example Response

{
  "b7e2d...": {
    "status": "confirmed",
    "detected_at": 1700000000,
    "proof": "2a9f..."
  },
  "cc481...": {
    "status": "suspected",
    "confidence": 0.87
  }
}

Success Codes

Status Description
200 The result is ready and the response body contains the result.
202 The result is not yet available. Clients MUST retry the identical request after the number of seconds indicated by the Retry-After response header.

Error Codes

Status Reason
400 The request body is malformed or not valid JSON.
413 The number of pubkeys in the request exceeds the provider's limit.
422 The pubkeys array is missing or empty.
422 One or more entries in pubkeys are not valid pubkeys.
422 The requested algorithm is not supported by this endpoint.