{
  "name": "Crypt",
  "what": "AES-256-GCM encryption over HTTP. You get the key, Crypt keeps nothing.",
  "app": "https://achenkunju.com/crypt/",
  "tokenFormat": {
    "key": "AC1.k.<iv>.<ciphertext>",
    "passphrase": "AC1.p.<salt>.<iv>.<ciphertext>",
    "encoding": "base64url, no padding",
    "cipher": "AES-256-GCM, 12 byte IV, tag appended",
    "kdf": "PBKDF2-SHA256, 310000 iterations, 16 byte salt"
  },
  "endpoints": [
    {
      "method": "POST",
      "path": "/api/crypt/key",
      "body": {},
      "returns": [
        "key"
      ]
    },
    {
      "method": "POST",
      "path": "/api/crypt/encrypt",
      "body": {
        "text": "required",
        "key": "optional base64url",
        "passphrase": "optional"
      },
      "returns": [
        "token",
        "key (key mode only)"
      ]
    },
    {
      "method": "POST",
      "path": "/api/crypt/decrypt",
      "body": {
        "token": "required",
        "key": "or passphrase"
      },
      "returns": [
        "text"
      ]
    },
    {
      "method": "POST",
      "path": "/api/crypt/once",
      "body": {
        "token": "a token you already made, preferred",
        "text": "or text for Crypt to encrypt",
        "key": "optional",
        "passphrase": "optional",
        "expiresIn": "seconds, 60 to 604800, default 86400"
      },
      "returns": [
        "id",
        "url",
        "key (when Crypt generated one)"
      ]
    },
    {
      "method": "GET",
      "path": "/api/crypt/once/:id",
      "body": null,
      "returns": [
        "waiting",
        "mode",
        "expiresAt"
      ],
      "note": "a peek, never a burn"
    },
    {
      "method": "POST",
      "path": "/api/crypt/once/:id",
      "body": {},
      "returns": [
        "token"
      ],
      "note": "burns it: the first caller gets the token, everyone after gets a 410"
    }
  ],
  "limits": {
    "textBytes": 65536,
    "minPassphrase": 8,
    "onceTtlSeconds": {
      "min": 60,
      "max": 604800,
      "default": 86400
    }
  },
  "storage": "none, except a one time message's ciphertext until it is read",
  "recovery": "none. A lost key is a lost message."
}