{
  "openapi": "3.1.1",
  "info": {
    "title": "Cryptography & security tools API",
    "version": "1.0.0",
    "summary": "Deterministic tools for people and AI agents.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://crypto.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/tools": {
      "get": {
        "operationId": "listTools",
        "summary": "Catalog of all tools",
        "responses": {
          "200": {
            "description": "Tool list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/{id}": {
      "get": {
        "operationId": "getTool",
        "summary": "Definition of one tool",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "crypto-kitchen",
                "hash-hmac-calculator",
                "key-derivation-lab",
                "file-encryption-studio",
                "password-generator",
                "private-breach-checker",
                "rsa-ecc-key-inspector",
                "shamir-secret-sharing",
                "tls-cipher-suite-simulator",
                "x509-certificate-inspector"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/crypto-kitchen/calculate": {
      "post": {
        "operationId": "calculateCryptoKitchen",
        "summary": "CyberChef-style recipes: chain encodings, compression, hashes, AES, JWT and more, step by step.",
        "description": "Write a recipe of operations, one per line, and run text or a file (up to 10 MB) through it: base64/32/58, hex, URL, HTML entities, Punycode and quoted-printable, gzip/deflate/brotli, hashes and HMAC, AES-GCM/CBC/CTR, XOR, ROT13/Caesar/Vigenère, JWT decode and verify, UUID/ULID parsing, timestamps, JSON, regex extraction, text case, byte swap, entropy and a Magic auto-decoder. Every intermediate result is shown; binary output can be downloaded.\n\nMethodology:\n- The input (pasted text, hex, base64 or an uploaded file) becomes a byte string; each recipe line is an operation that maps bytes to bytes. Text operations decode as UTF-8. The table shows every intermediate result; on an error the pipeline stops and reports the failing step.\n- Cryptography uses Node.js crypto (OpenSSL): AES-GCM appends/verifies the 16-byte tag, CBC uses PKCS#7 padding, CTR is a stream mode. You must supply key and IV, so results are reproducible; never reuse a GCM nonce with the same key.\n- JWT decode never checks signatures. jwt-verify supports HS256/384/512 (secret), RS*/PS* (RSA), ES256/384/512 (raw r||s signatures as in RFC 7518) and EdDSA with a PEM, certificate or JWK key, and refuses tokens whose header alg differs from the expected one.\n- Decompression stops at 50 MB of output to defuse decompression bombs; regex extraction runs in an isolated VM context with a 1-second limit.\n- Magic checks for gzip/zlib headers, JWTs, UUIDs/ULIDs, timestamps, JSON, percent-encoding, HTML entities, hex, base64/base64url, base32 and quoted-printable, and applies the most plausible decoder repeatedly while the output stays readable or reveals another known format.\n\nData and keys are processed on the server for this request only. Do not paste production secrets.",
        "tags": [
          "crypto"
        ],
        "x-mcp-tool": "crypto_kitchen",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CryptoKitchenInput"
              },
              "examples": {
                "example1": {
                  "summary": "Base64 → gunzip → pretty JSON",
                  "value": {
                    "input": "H4sIAAAAAAACA6tWKi1OLVKyUkpMSVTSUSrKz0ktVrKKVkpMyc3MU9JRSkktU4rVUUpMLsksS1WyKikqTa0FAJsiBuU0AAAA",
                    "recipe": "from-base64\ngunzip\njson-pretty"
                  }
                },
                "example2": {
                  "summary": "AES-256-GCM round trip with entropy check",
                  "value": {
                    "input": "Attack at dawn",
                    "recipe": "aes-encrypt mode=gcm key=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f iv=cafebabefacedbaddecaf888\nentropy\naes-decrypt mode=gcm key=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f iv=cafebabefacedbaddecaf888"
                  }
                },
                "example3": {
                  "summary": "Verify an HS256 JWT",
                  "value": {
                    "input": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
                    "recipe": "jwt-verify key=@key alg=HS256",
                    "key": "your-256-bit-secret"
                  }
                },
                "example4": {
                  "summary": "Magic: auto-detect and decode",
                  "value": {
                    "input": "H4sIAAAAAAACA6tWKi1OLVKyUkpMSVTSUSrKz0ktVrKKVkpMyc3MU9JRSkktU4rVUUpMLsksS1WyKikqTa0FAJsiBuU0AAAA",
                    "recipe": "magic"
                  }
                },
                "example5": {
                  "summary": "HMAC-SHA256 and hash of a file-like input",
                  "value": {
                    "input": "The quick brown fox jumps over the lazy dog",
                    "recipe": "hmac alg=sha256 key=key"
                  }
                },
                "example6": {
                  "summary": "Regex extract e-mail domains, then upper case",
                  "value": {
                    "input": "ada@example.org, bob@test.dev; eve@example.org",
                    "recipe": "regex-extract pattern=\"@([a-z0-9.-]+)\" group=1\ntext-case mode=upper"
                  }
                },
                "example7": {
                  "summary": "Gzip to binary (download)",
                  "value": {
                    "input": "hello hello hello hello",
                    "recipe": "gzip level=9"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CryptoKitchenResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/hash-hmac-calculator/calculate": {
      "post": {
        "operationId": "calculateHashHmacCalculator",
        "summary": "MD5, SHA-2, SHA-3, BLAKE2, CRC32 and HMAC of text or files, with checksum compare.",
        "description": "Computes MD5, SHA-1, SHA-224/256/384/512, SHA3-256/512, BLAKE2b-512, BLAKE2s-256 and CRC-32 of text or a file, or an HMAC with your key, in hex or Base64, and checks a published checksum against all of them. With JavaScript on, files and keys are hashed locally in your browser.\n\nMethodology:\n- The input bytes are the file as uploaded, or the text decoded as UTF-8, hex or Base64. Text is hashed exactly as entered: no newline is appended (unlike `echo` without `-n`).\n- Digests come from OpenSSL via Node.js crypto (MD5, SHA-1, SHA-2, SHA-3, BLAKE2b-512, BLAKE2s-256) and zlib (CRC-32, IEEE polynomial, shown big-endian as in `crc32`/`cksum -a crc32b`).\n- With a key, HMAC (RFC 2104) is computed for every selected hash; CRC-32 has no HMAC. SHA-3 HMACs use the SHA-3 rate as block size (NIST), BLAKE2 HMACs the BLAKE2 block size, as OpenSSL does.\n- The comparison accepts hex (any case, optional spaces or colons) or Base64 and reports which algorithm matches.\n- With JavaScript on, the browser computes everything locally: SHA-1/2 via WebCrypto, MD5, SHA-224, SHA-3, BLAKE2 and CRC-32 via small built-in JavaScript implementations. Files and keys never leave your device.\n\nMD5, SHA-1 and CRC-32 must not be used where an attacker could craft collisions. To store passwords use a password hash (Argon2id, scrypt, bcrypt), not a plain hash.",
        "tags": [
          "crypto"
        ],
        "x-mcp-tool": "hash_hmac_calculator",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HashHmacCalculatorInput"
              },
              "examples": {
                "example1": {
                  "summary": "Hashes of \"hello world\"",
                  "value": {
                    "text": "hello world"
                  }
                },
                "example2": {
                  "summary": "HMAC-SHA256 (RFC 4231 test case 2)",
                  "value": {
                    "text": "what do ya want for nothing?",
                    "hmacKey": "Jefe",
                    "algorithms": [
                      "sha256",
                      "sha512"
                    ]
                  }
                },
                "example3": {
                  "summary": "Verify a SHA-256 checksum of a small file",
                  "value": {
                    "file": {
                      "filename": "readme.txt",
                      "contentType": "text/plain",
                      "contentBase64": "dXNlZnVsd2ViLnNpdGUgY2hlY2tzdW0gZGVtbwo="
                    },
                    "algorithms": [
                      "sha256",
                      "sha3-256",
                      "crc32"
                    ],
                    "expected": "CFA892AD DD30FF8C 6453D2F3 B44C88C3 63B38A3F B5113357 39A5067F 555BE6C0"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HashHmacCalculatorResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/key-derivation-lab/calculate": {
      "post": {
        "operationId": "calculateKeyDerivationLab",
        "summary": "Derive keys with PBKDF2, scrypt, Argon2id and HKDF; compare costs with OWASP advice.",
        "description": "Derives keys from a password and salt with PBKDF2 (SHA-1/256/512), scrypt, Argon2id and HKDF using the parameters you choose, and compares their memory and work settings with the OWASP Password Storage recommendations. With JavaScript on, PBKDF2, HKDF and scrypt run locally in your browser and show real timings.\n\nMethodology:\n- PBKDF2 (RFC 8018) repeats HMAC with the chosen hash; its cost is the iteration count and it needs almost no memory, so GPUs attack it efficiently.\n- scrypt (RFC 7914) needs about 128 × N × r bytes of memory per derivation, which makes large-scale guessing expensive. Argon2id (RFC 9106, winner of the Password Hashing Competition) is configured by memory m, passes t and lanes p; OWASP recommends it first.\n- HKDF (RFC 5869) extracts and expands keys from input that is already random (for example a Diffie–Hellman secret); it is fast and must not be used to hash passwords.\n- \"Meets OWASP\" compares your parameters with the minimums of the OWASP Password Storage Cheat Sheet (Argon2id m/t combinations; scrypt N×r ≥ 2^17×8; PBKDF2 1,300,000 / 600,000 / 210,000 iterations for SHA-1 / SHA-256 / SHA-512).\n- Server and API results contain no timings, so the same input always gives the same result. With JavaScript on, the page derives PBKDF2 and HKDF with WebCrypto and scrypt with a built-in JavaScript implementation in your browser and shows how long each took on your device. Argon2 is not available in browsers, so it needs the server (you are asked first).\n\nNever reuse the example salts. For real password storage use a maintained library that encodes parameters and salt (e.g. the PHC string format).",
        "tags": [
          "crypto"
        ],
        "x-mcp-tool": "key_derivation_lab",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KeyDerivationLabInput"
              },
              "examples": {
                "example1": {
                  "summary": "OWASP defaults: PBKDF2-SHA-256, scrypt, Argon2id, HKDF",
                  "value": {
                    "password": "correct horse battery staple",
                    "salt": "c2FsdHNhbHRzYWx0c2FsdA==",
                    "saltFormat": "base64"
                  }
                },
                "example2": {
                  "summary": "RFC 7914 scrypt test vector (N = 1024, r = 8, p = 16)",
                  "value": {
                    "password": "password",
                    "salt": "NaCl",
                    "algorithms": [
                      "scrypt"
                    ],
                    "scryptLogN": 10,
                    "scryptR": 8,
                    "scryptP": 16,
                    "keyLength": 64
                  }
                },
                "example3": {
                  "summary": "PBKDF2 with too few iterations (RFC 7914 §11 vector)",
                  "value": {
                    "password": "passwd",
                    "salt": "salt",
                    "algorithms": [
                      "pbkdf2-sha256"
                    ],
                    "pbkdf2Iterations": 1,
                    "keyLength": 64
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeyDerivationLabResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/file-encryption-studio/calculate": {
      "post": {
        "operationId": "calculateFileEncryptionStudio",
        "summary": "Encrypt and decrypt files with AES-256-GCM and a password, locally in your browser.",
        "description": "Encrypts any file up to 100 MB with AES-256-GCM, using a password (PBKDF2-SHA-256, at least 600,000 iterations) or a raw 256-bit key, and decrypts it again. The output is a small documented container. With JavaScript on, everything runs in your browser via WebCrypto and the file never leaves your device.\n\nMethodology:\n- Encryption: AES-256 in GCM mode (authenticated encryption) with a random 96-bit IV. The 16-byte authentication tag detects a wrong key and any modification of the file or its header.\n- Password mode: the key is PBKDF2-HMAC-SHA-256(password in Unicode NFC, UTF-8; random 16-byte salt; ≥ 600,000 iterations; 32 bytes). Raw-key mode uses your 32-byte key directly (or a random one generated for you).\n- Container \"UWFE\" v1, all integers big-endian: bytes 0–3 \"UWFE\"; 4 version (1); 5 KDF (1 = PBKDF2-SHA-256, 0 = raw key); 6–9 iterations (0 for raw key); 10 salt length S; then S salt bytes; then IV length (12) and the IV; then ciphertext followed by the 16-byte tag. The whole header is authenticated as GCM additional data.\n- With JavaScript on, the browser does everything with WebCrypto (crypto.subtle: PBKDF2, AES-GCM) and offers the result as a local download; the file and password never leave your device.\n- Without JavaScript or via the API/MCP, the server performs the same steps with Node.js crypto. It then receives the file and the password; the output is kept as a download for about 2 hours and then deleted.\n\nIf you forget the password or lose the key, the file cannot be recovered. Keep an unencrypted backup until you have tested decryption.",
        "tags": [
          "crypto"
        ],
        "x-mcp-tool": "file_encryption_studio",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FileEncryptionStudioInput"
              },
              "examples": {
                "example1": {
                  "summary": "Encrypt a text file with a password (demo seed)",
                  "value": {
                    "action": "encrypt",
                    "file": {
                      "filename": "notes.txt",
                      "contentType": "text/plain",
                      "contentBase64": "TWVldGluZyBub3RlczogdGhlIHNwYXJlIGtleSBpcyB1bmRlciB0aGUgYmx1ZSBmbG93ZXJwb3QuCg=="
                    },
                    "keyMode": "password",
                    "password": "correct horse battery staple",
                    "seed": "demo"
                  }
                },
                "example2": {
                  "summary": "Decrypt the demo file",
                  "value": {
                    "action": "decrypt",
                    "file": {
                      "filename": "notes.txt.uwenc",
                      "contentType": "application/octet-stream",
                      "contentBase64": "VVdGRQEBAAknwBDpZOKuJvfa5dh6b4uQWgxhDBz+qzPNLpyER5uJf0+lqHctv57Gg4dAu9etoo9XyTMcu4qngNaolW3xIPUsAFquU/AQK9yw1zMFh2AKPSCkQVO45yYcipxdJ/Geh65IpBMyFXIxSia1"
                    },
                    "keyMode": "password",
                    "password": "correct horse battery staple"
                  }
                },
                "example3": {
                  "summary": "Encrypt with a raw AES-256 key",
                  "value": {
                    "action": "encrypt",
                    "file": {
                      "filename": "data.csv",
                      "contentType": "text/csv",
                      "contentBase64": "aWQsYW1vdW50CjEsNDIK"
                    },
                    "keyMode": "rawkey",
                    "rawKey": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
                    "seed": "raw-demo"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileEncryptionStudioResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/password-generator/calculate": {
      "post": {
        "operationId": "calculatePasswordGenerator",
        "summary": "Strong random passwords and passphrases, made in your browser, with exact entropy.",
        "description": "Generates random passwords (length, character sets, no look-alike characters, at least one of each class) or passphrases from a 2048-word list with separators and capitalisation. Shows the exact entropy in bits and how long guessing would take. With JavaScript on, everything is generated locally in your browser.\n\nMethodology:\n- Random password: every character is drawn uniformly from the selected sets with an unbiased random integer (rejection sampling, no modulo bias). \"At least one of each set\" regenerates the whole password until the rule holds, which keeps all valid passwords equally likely.\n- Entropy is exact: log2 of the number of possible passwords. With \"at least one of each set\" the count is computed by inclusion–exclusion, so it is slightly lower than length × log2(pool size).\n- Passphrase: words are drawn uniformly from a bundled list of 2048 common English words (4–8 letters), so each word adds exactly 11 bits. Random capitalisation adds 1 bit per word; an appended digit adds log2(10 × words) bits.\n- Guessing times assume the attacker knows exactly how the password was generated (the worst case) and finds it on average after trying half of all possibilities.\n- In the browser, passwords are generated locally with crypto.getRandomValues and never sent anywhere. Without JavaScript (and via the API/MCP), the server generates them with Node.js crypto.randomInt and sends them back over HTTPS without storing them.\n\nUse a password manager and a different password for every account. Seeded output is for demos only.",
        "tags": [
          "crypto"
        ],
        "x-mcp-tool": "password_generator",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasswordGeneratorInput"
              },
              "examples": {
                "example1": {
                  "summary": "5 passwords, 20 characters, all sets (demo seed)",
                  "value": {
                    "mode": "password",
                    "length": 20,
                    "count": 5,
                    "seed": "demo"
                  }
                },
                "example2": {
                  "summary": "6-word passphrase, Title Case, with a digit (demo seed)",
                  "value": {
                    "mode": "passphrase",
                    "words": 6,
                    "capitalization": "title",
                    "includeNumber": true,
                    "count": 3,
                    "seed": "demo"
                  }
                },
                "example3": {
                  "summary": "12 characters, letters and digits, no look-alikes (demo seed)",
                  "value": {
                    "mode": "password",
                    "length": 12,
                    "charsets": [
                      "lower",
                      "upper",
                      "digits"
                    ],
                    "excludeAmbiguous": true,
                    "count": 3,
                    "seed": "example"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PasswordGeneratorResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/private-breach-checker/calculate": {
      "post": {
        "operationId": "calculatePrivateBreachChecker",
        "summary": "Check if a password appears in known breaches without revealing it (k-anonymity).",
        "description": "Checks a password against the Have I Been Pwned Pwned Passwords collection using k-anonymity: your browser hashes the password with SHA-1 and sends only the first 5 of 40 hex characters; the match is done locally. The server and API accept only a SHA-1 hash or 5-character prefix, never a password.\n\nMethodology:\n- The password is hashed with SHA-1 (uppercase hex). Only the first 5 hex characters (20 bits) are sent to https://api.pwnedpasswords.com/range/<prefix>; the service returns every known hash suffix with that prefix (typically 800–1,000) and how often each appeared in breaches.\n- Requests use the Add-Padding header, so the response contains random zero-count entries and its size reveals nothing; padding entries are ignored.\n- With JavaScript on, hashing, the range request and the comparison all happen in your browser; our server is not involved. If your browser cannot reach the service directly, the page asks our API for the same 5-character range and still compares locally.\n- The server path (no JavaScript, API, MCP) accepts only a 40-character SHA-1 hash or a 5-character prefix and rejects anything else, so a password can never be submitted by mistake. With a full hash, the server sees the hash (not the password) and sends only the prefix onwards.\n- Not found does not prove a password is strong: it only means it is not in this breach corpus.\n\nIf a password appears in a breach, stop using it everywhere and change it. Use a password manager and unique passwords.",
        "tags": [
          "crypto"
        ],
        "x-mcp-tool": "private_breach_checker",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrivateBreachCheckerInput"
              },
              "examples": {
                "example1": {
                  "summary": "SHA-1 of the password \"password\"",
                  "value": {
                    "hash": "5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8"
                  }
                },
                "example2": {
                  "summary": "Range lookup for prefix 21BD1 (k-anonymity)",
                  "value": {
                    "hash": "21BD1"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrivateBreachCheckerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/rsa-ecc-key-inspector/calculate": {
      "post": {
        "operationId": "calculateRsaEccKeyInspector",
        "summary": "Inspect PEM, DER, JWK or OpenSSH keys: type, size, curve, fingerprints, thumbprint and weaknesses.",
        "description": "Paste an RSA, EC (P-256/P-384/P-521, secp256k1, brainpool), Ed25519/Ed448 or X25519 key as PEM, base64/hex DER, JWK or OpenSSH line. Shows key type, size or curve, public exponent, SHA-256 SPKI and OpenSSH fingerprints, the RFC 7638 JWK thumbprint, detects encrypted private keys and their KDF, rates the key against current guidance and converts the PUBLIC key between PEM, JWK and OpenSSH formats.\n\nMethodology:\n- The format is detected from the text: PEM labels (PUBLIC KEY, RSA PUBLIC KEY, PRIVATE KEY, RSA/EC PRIVATE KEY, ENCRYPTED PRIVATE KEY, OPENSSH PRIVATE KEY, CERTIFICATE, CERTIFICATE REQUEST), JSON JWK / JWK sets, OpenSSH authorized_keys lines and RFC 4716 SSH2 blocks; anything else is tried as base64 or hex DER (SPKI, PKCS#8, PKCS#1, SEC1).\n- Keys are imported with Node.js crypto (OpenSSL); the size, exponent and curve come from the key object, the algorithm identifiers from a DER parse of the SubjectPublicKeyInfo.\n- Fingerprints: SHA-256 over the DER SubjectPublicKeyInfo (hex and base64, the pin-sha256 format), OpenSSH SHA256:/MD5: over the SSH wire encoding, and the RFC 7638 JWK thumbprint (SHA-256 over the required members in lexicographic order).\n- Encrypted keys are recognised without a passphrase: PKCS#8 EncryptedPrivateKeyInfo (PBES2 with PBKDF2 or scrypt parameters), legacy Proc-Type: 4,ENCRYPTED PEM and openssh-key-v1 cipher/KDF. The OpenSSH public key is read from the unencrypted file header.\n- Ratings follow NIST SP 800-57 Part 1 Rev. 5 (RSA-2048 = 112-bit security, acceptable until 2030; ≥3072 bits = 128-bit), FIPS 186-5 (DSA no longer approved for signing) and common TLS/SSH support.\n- Conversions only ever output the PUBLIC key (SPKI PEM, JWK, OpenSSH). Private key material is never echoed back.\n\nKeys are processed on the server for this request and not stored. Do not paste production private keys into any web tool; with JavaScript enabled this page converts private keys to public keys locally before sending.",
        "tags": [
          "crypto"
        ],
        "x-mcp-tool": "rsa_ecc_key_inspector",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RsaEccKeyInspectorInput"
              },
              "examples": {
                "example1": {
                  "summary": "RSA-2048 public key (PEM)",
                  "value": {
                    "key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh3BIrCB410mLVroKIYbJ\nUPfbt6YGNqOyz/2j7yyi5kOjNVVbFPp02sqjt6i+ZEDvaH5kJIU4P+25V330U0h4\nmXfqN+0yDClu7yxsDLdbVBT7HZHWRuasFoR1ZoZCtlQDg7yP/ubHuWTIVPRHMzRm\n45s7+nUnziEXCDIUhwSxLLTu1Nbo8YfmJEFDKVW+hY8AjlrR6HmNKqjMqiVT+R0U\nVNpB0Y3+koWbPs6WWW0xNpzER2ffGS3IPT0sD++SChsbbZYXJ9gVockGuNifXk1J\n+O/wdXu1FFp9oIua/h2pMwfCYOTci7NZsY4P1dcELAF/+Q/bIz//QMgW+QyGVk9c\nEwIDAQAB\n-----END PUBLIC KEY-----"
                  }
                },
                "example2": {
                  "summary": "P-256 public JWK (RFC 7515 example key)",
                  "value": {
                    "key": "{\"kty\":\"EC\",\"crv\":\"P-256\",\"x\":\"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU\",\"y\":\"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0\",\"kid\":\"rfc7515-example\"}"
                  }
                },
                "example3": {
                  "summary": "OpenSSH Ed25519 public key",
                  "value": {
                    "key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKFvjbb92spN+tAd+TaDJCCyEIYO+d8Lh2R2llUEcjt0 demo@example",
                    "showAsn1": false
                  }
                },
                "example4": {
                  "summary": "Weak RSA-512 key",
                  "value": {
                    "key": "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMQNesk/E6YVJmHFkvS8JJe4DuE3aZT9\nK2uFLODY5xxa8f1udg9uMFVCO5o6UizhNXQczysSbTxp1Bk5shU1ZncCAwEAAQ==\n-----END PUBLIC KEY-----"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RsaEccKeyInspectorResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/shamir-secret-sharing/calculate": {
      "post": {
        "operationId": "calculateShamirSecretSharing",
        "summary": "Split a secret into n shares so any k recover it, and combine shares, locally.",
        "description": "Splits a secret (recovery code, password, key) into n shares with a threshold k using Shamir's scheme over GF(256): any k shares reconstruct it, fewer reveal nothing. Combines and verifies shares with an optional checksum. With JavaScript on, splitting and combining happen in your browser.\n\nMethodology:\n- Each byte of the secret is the constant term of its own random polynomial of degree k−1 over GF(2^8) (field polynomial x^8+x^4+x^3+x+1, as in AES). Share i holds the value of every polynomial at x = i (i = 1…n), so a share is as long as the secret.\n- Combining uses Lagrange interpolation at x = 0. Any k shares give the secret; with k−1 or fewer, every possible secret is equally consistent with the shares (information-theoretic security).\n- Optional checksum: the first 4 bytes of SHA-256(secret) are appended before splitting. After combining, a wrong share or too few shares are detected with probability 1 − 2^−32.\n- Shares are written as \"<index>-<data>\" in hex or Base64. The format is not interchangeable with other tools (e.g. ssss-split, which uses a larger field).\n- With JavaScript on, the page splits and combines in your browser with crypto.getRandomValues; the secret is not sent to the server. Without JavaScript or via the API the server does it with Node.js crypto and does not store anything.\n\nStore shares in different places and test recovery before relying on them. Anyone holding k shares can recover the secret.",
        "tags": [
          "crypto"
        ],
        "x-mcp-tool": "shamir_secret_sharing",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShamirSecretSharingInput"
              },
              "examples": {
                "example1": {
                  "summary": "Split a recovery code into 5 shares, any 3 recover it (demo seed)",
                  "value": {
                    "action": "split",
                    "secret": "correct horse battery staple",
                    "shares": 5,
                    "threshold": 3,
                    "seed": "demo"
                  }
                },
                "example2": {
                  "summary": "Combine 3 shares",
                  "value": {
                    "action": "combine",
                    "format": "hex",
                    "threshold": 3,
                    "sharesInput": "1-ee23a34dc787be4d8af7916bb9d669417a54d63602154ed4db2ff116b421013a\n3-ac721e5b9f43f6ca6776a86e6d38d61c86b773028d0747eaa1987125c62a63f5\n5-7d88d2da6b481f3783705eb5cd759e8f3433ca98f8ca8b277b7e58092ea75c9d"
                  }
                },
                "example3": {
                  "summary": "Split into 3 Base64 shares, 2 needed (demo seed)",
                  "value": {
                    "action": "split",
                    "secret": "vault unseal key 42",
                    "shares": 3,
                    "threshold": 2,
                    "format": "base64",
                    "seed": "example"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShamirSecretSharingResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/tls-cipher-suite-simulator/calculate": {
      "post": {
        "operationId": "calculateTlsCipherSuiteSimulator",
        "summary": "See which TLS version, cipher and group browsers, Android, Java and OpenSSL get from your server.",
        "description": "Pick a Mozilla server preset (modern, intermediate, old) or paste your own cipher list in OpenSSL or IANA names, and see what 34 recorded clients (browsers, Android, Java, OpenSSL, plus curl) would negotiate: protocol version, cipher suite, key-exchange group, signature algorithm, forward secrecy and AEAD, or why the handshake fails. Includes an IANA ↔ OpenSSL name table and a configuration grade. Offline simulation from documented data, no connection is made.\n\nMethodology:\n- Client data: the ClientHello bytes SSL Labs records for its handshake simulation (cipher suites in order, supported_versions, supported_groups, key_share, signature_algorithms), decoded by our own parser, plus SSL Labs’ DH-size limits. GREASE values and pre-standard TLS 1.3 draft versions (e.g. the draft-28 version sent by Firefox 62) are ignored. curl profiles reuse the default hello of the OpenSSL version curl is linked against (an approximation: curl distributions may set their own cipher lists).\n- Server data: Mozilla Server Side TLS guidelines 6.0 (modern, intermediate) and 5.7 (old, removed from 6.0): protocols, cipher suites, TLS 1.3 suites, curves, certificate types and DH size. Custom lists accept OpenSSL names, IANA names or hex codes.\n- Negotiation follows OpenSSL server behaviour: the highest common protocol version wins; TLS 1.3 chooses a shared suite and group (a missing key share costs a HelloRetryRequest) and needs ecdsa_secp256r1_sha256 or rsa_pss_rsae_* signatures. TLS ≤ 1.2 picks the first shared suite in client order (or server order if enabled) whose authentication matches the certificate and whose key exchange is possible (ECDHE needs a shared curve). Clients that reject large or small DH groups fail like they do in reality.\n- Grade: our own simple scale (A+ to F), not the SSL Labs rating: SSL 3.0, RC4, export, NULL, anonymous or DES suites → F; 3DES → C; TLS 1.0/1.1 or static RSA → B; CBC suites → A-; no TLS 1.3 → A.\n- Limitations: no real network connection is made; extensions such as ALPN, session resumption, OCSP stapling, Encrypted Client Hello and certificate chain validation are not simulated; client behaviour can differ by OS build and configuration.\n\nSimulation from recorded and documented data. Test your real server with a live scanner before relying on it.",
        "tags": [
          "crypto"
        ],
        "x-mcp-tool": "tls_cipher_suite_simulator",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TlsCipherSuiteSimulatorInput"
              },
              "examples": {
                "example1": {
                  "summary": "Mozilla intermediate against all clients",
                  "value": {
                    "serverPreset": "intermediate"
                  }
                },
                "example2": {
                  "summary": "Mozilla modern (TLS 1.3 only)",
                  "value": {
                    "serverPreset": "modern"
                  }
                },
                "example3": {
                  "summary": "Mozilla old with RSA certificate",
                  "value": {
                    "serverPreset": "old",
                    "clients": [
                      "java-6u45",
                      "ie-8-xp",
                      "android-2.3.7",
                      "android-4.4.2",
                      "chrome-131-win-10",
                      "curl-openssl-1.0.2"
                    ]
                  }
                },
                "example4": {
                  "summary": "Custom OpenSSL list without ECDHE, server order",
                  "value": {
                    "serverPreset": "custom",
                    "customSuites": "DHE-RSA-AES256-GCM-SHA384:AES128-SHA:DES-CBC3-SHA",
                    "customProtocols": [
                      "TLSv1",
                      "TLSv1.1",
                      "TLSv1.2"
                    ],
                    "certificate": "rsa",
                    "dhBits": 2048
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TlsCipherSuiteSimulatorResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tools/x509-certificate-inspector/calculate": {
      "post": {
        "operationId": "calculateX509CertificateInspector",
        "summary": "Decode X.509 certificates, chains and CSRs: SANs, usages, CT SCTs, chain order and an ASN.1 tree.",
        "description": "Paste or upload a PEM/DER certificate, a whole chain or a PKCS#10 certificate signing request. Shows subject, issuer, validity and expiry warnings, SANs, key usage and EKU, basic constraints, AIA (OCSP, CA issuers), CRL distribution points, policies, embedded Certificate Transparency SCTs, fingerprints and the signature algorithm, checks the chain order with real signature verification, and includes a generic ASN.1 DER tree viewer with OID names.\n\nMethodology:\n- Input may hold several PEM blocks (CERTIFICATE, CERTIFICATE REQUEST) or one base64/hex/binary DER object. Each certificate is parsed twice: by Node.js crypto.X509Certificate (OpenSSL) for fingerprints, keys and signature checks, and by an in-house DER parser for the exact fields and extensions.\n- Decoded extensions: subjectAltName, keyUsage, extKeyUsage, basicConstraints, authorityInfoAccess (OCSP, caIssuers), cRLDistributionPoints, certificatePolicies (with CPS URIs), the CT SignedCertificateTimestampList (RFC 6962: version, log id, timestamp, algorithms), key identifiers and TLS Feature (OCSP Must-Staple). Others are listed with OID name and criticality.\n- Chain order: each certificate must be issued by the next one (issuer name = next subject, and the signature verifies with X509Certificate.verify). A suggested leaf → root order is derived from the verified issuer links. Trust in a root store is NOT evaluated, and revocation (OCSP/CRL) is not checked.\n- Warnings: expired / not yet valid / expiring within 30 days (relative to the time of the request), SHA-1/MD5 signatures, RSA keys under 2048 bits, TLS server certificates without SAN or valid for more than 398 days (CA/Browser Forum Baseline Requirements), issuers without CA:TRUE.\n- CSR (PKCS#10, RFC 2986): subject, public key, attributes and requested extensions; the self-signature is verified (RSA PKCS#1 v1.5, RSA-PSS, ECDSA, Ed25519/Ed448). Challenge passwords are never shown.\n- The ASN.1 viewer prints tag, header and value lengths and values (integers, OIDs with names from a bundled map, strings, times) and descends into BIT/OCTET STRINGs that contain DER, like openssl asn1parse. At most 400 rows are shown.\n\nStructural inspection only: trust-store membership and revocation are not checked.",
        "tags": [
          "crypto"
        ],
        "x-mcp-tool": "x509_certificate_inspector",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/X509CertificateInspectorInput"
              },
              "examples": {
                "example1": {
                  "summary": "Leaf + intermediate + root chain",
                  "value": {
                    "input": "-----BEGIN CERTIFICATE-----\nMIIDLjCCAtOgAwIBAgICEAIwCgYIKoZIzj0EAwIwPjELMAkGA1UEBhMCREUxEzAR\nBgNVBAoMCkRlbW8gVHJ1c3QxGjAYBgNVBAMMEURlbW8gSXNzdWluZyBDQSAxMB4X\nDTI2MDYwMTAwMDAwMFoXDTI3MDYwMTAwMDAwMFowGzEZMBcGA1UEAwwQd3d3LmV4\nYW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLwflXvmcWBlNNt6\nEWqg80zBOiPnUnG7MCWhlhismwZ/YOljyr8K/UdAkXf6Llf4v0sLnpdbZT4Wq/N0\nslgndbajggHiMIIB3jAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAdBgNV\nHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwLwYDVR0RBCgwJoIQd3d3LmV4YW1w\nbGUudGVzdIIMZXhhbXBsZS50ZXN0hwTAAAIKMB0GA1UdDgQWBBQuMUVbXfDHZsLe\nFlEHnSrL0bMh6TAfBgNVHSMEGDAWgBT7k5kCNLbFwA6mVAlV3zaBislI5zBhBggr\nBgEFBQcBAQRVMFMwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmV4YW1wbGUudGVz\ndDArBggrBgEFBQcwAoYfaHR0cDovL3BraS5leGFtcGxlLnRlc3QvaW50LmNydDAw\nBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vY3JsLmV4YW1wbGUudGVzdC9pbnQuY3Js\nMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcGCSsGAQQBho0fATAqMCgGCCsGAQUFBwIB\nFhxodHRwczovL3BraS5leGFtcGxlLnRlc3QvY3BzMEsGCisGAQQB1nkCBAIEPQQ7\nADkANwBnVrBBAcvljHomKVT/KjJqZk7slVSrrLJc04j+mfiyCAAAAZt22qgAAAAE\nAwAIMAYCAQECAQEwCgYIKoZIzj0EAwIDSQAwRgIhAItLxsx9fdGDv8VcEjutYufp\njl9EzIv0BlAgbWaiomqCAiEAwQYOJuXmHyQW8aDAxDiNkkai45zfZvGmiA50yQXd\nSf0=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICQDCCAeagAwIBAgICEAEwCgYIKoZIzj0EAwIwOTELMAkGA1UEBhMCREUxEzAR\nBgNVBAoMCkRlbW8gVHJ1c3QxFTATBgNVBAMMDERlbW8gUm9vdCBDQTAeFw0yNTA2\nMDEwMDAwMDBaFw0zMDA2MDEwMDAwMDBaMD4xCzAJBgNVBAYTAkRFMRMwEQYDVQQK\nDApEZW1vIFRydXN0MRowGAYDVQQDDBFEZW1vIElzc3VpbmcgQ0EgMTBZMBMGByqG\nSM49AgEGCCqGSM49AwEHA0IABEeQba6KBaWI+q0HmTqVHbgwBicTYshVrCnuRh2I\nt0rWsnpnzmAAmP+d20u1KBqraNtyLkOUAx8dyPGKAZ9F2SWjgdgwgdUwEgYDVR0T\nAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFPuTmQI0tsXA\nDqZUCVXfNoGKyUjnMB8GA1UdIwQYMBaAFB0fhulA+MOuxtHtcfIPvu4E5yXVMDEG\nA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9jcmwuZXhhbXBsZS50ZXN0L3Jvb3QuY3Js\nMDwGCCsGAQUFBwEBBDAwLjAsBggrBgEFBQcwAoYgaHR0cDovL3BraS5leGFtcGxl\nLnRlc3Qvcm9vdC5jcnQwCgYIKoZIzj0EAwIDSAAwRQIhAPWRqATEpNCkoptvt2IM\nDLnTCwZtRwLGaoj/eIQ0G6dQAiB9z4wjtixhRaGoTuoCmQBt4Qaq+qxKrOjr9rYh\nriUr2g==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIBpDCCAUqgAwIBAgICEAAwCgYIKoZIzj0EAwIwOTELMAkGA1UEBhMCREUxEzAR\nBgNVBAoMCkRlbW8gVHJ1c3QxFTATBgNVBAMMDERlbW8gUm9vdCBDQTAeFw0yNTAx\nMDEwMDAwMDBaFw0zNTAxMDEwMDAwMDBaMDkxCzAJBgNVBAYTAkRFMRMwEQYDVQQK\nDApEZW1vIFRydXN0MRUwEwYDVQQDDAxEZW1vIFJvb3QgQ0EwWTATBgcqhkjOPQIB\nBggqhkjOPQMBBwNCAATTrpHwl14fB2G9rruBlIhJYzEoxeDEB+dK/BTnA5rmGLpo\ncUF66cgob5+4knEsMCj0DBKDbsXXZdT0LCStDhRQo0IwQDAPBgNVHRMBAf8EBTAD\nAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUHR+G6UD4w67G0e1x8g++7gTn\nJdUwCgYIKoZIzj0EAwIDSAAwRQIhAKFCNk4jPJLSLSZW/h594Y5s9ASp/10vVZgG\nANqkwaj+AiBmcW2LQn8vPqusJpwbtGMmubShkGp6/gME7qX/EJny7g==\n-----END CERTIFICATE-----"
                  }
                },
                "example2": {
                  "summary": "Chain in the wrong order",
                  "value": {
                    "input": "-----BEGIN CERTIFICATE-----\nMIICQDCCAeagAwIBAgICEAEwCgYIKoZIzj0EAwIwOTELMAkGA1UEBhMCREUxEzAR\nBgNVBAoMCkRlbW8gVHJ1c3QxFTATBgNVBAMMDERlbW8gUm9vdCBDQTAeFw0yNTA2\nMDEwMDAwMDBaFw0zMDA2MDEwMDAwMDBaMD4xCzAJBgNVBAYTAkRFMRMwEQYDVQQK\nDApEZW1vIFRydXN0MRowGAYDVQQDDBFEZW1vIElzc3VpbmcgQ0EgMTBZMBMGByqG\nSM49AgEGCCqGSM49AwEHA0IABEeQba6KBaWI+q0HmTqVHbgwBicTYshVrCnuRh2I\nt0rWsnpnzmAAmP+d20u1KBqraNtyLkOUAx8dyPGKAZ9F2SWjgdgwgdUwEgYDVR0T\nAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFPuTmQI0tsXA\nDqZUCVXfNoGKyUjnMB8GA1UdIwQYMBaAFB0fhulA+MOuxtHtcfIPvu4E5yXVMDEG\nA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9jcmwuZXhhbXBsZS50ZXN0L3Jvb3QuY3Js\nMDwGCCsGAQUFBwEBBDAwLjAsBggrBgEFBQcwAoYgaHR0cDovL3BraS5leGFtcGxl\nLnRlc3Qvcm9vdC5jcnQwCgYIKoZIzj0EAwIDSAAwRQIhAPWRqATEpNCkoptvt2IM\nDLnTCwZtRwLGaoj/eIQ0G6dQAiB9z4wjtixhRaGoTuoCmQBt4Qaq+qxKrOjr9rYh\nriUr2g==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIDLjCCAtOgAwIBAgICEAIwCgYIKoZIzj0EAwIwPjELMAkGA1UEBhMCREUxEzAR\nBgNVBAoMCkRlbW8gVHJ1c3QxGjAYBgNVBAMMEURlbW8gSXNzdWluZyBDQSAxMB4X\nDTI2MDYwMTAwMDAwMFoXDTI3MDYwMTAwMDAwMFowGzEZMBcGA1UEAwwQd3d3LmV4\nYW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLwflXvmcWBlNNt6\nEWqg80zBOiPnUnG7MCWhlhismwZ/YOljyr8K/UdAkXf6Llf4v0sLnpdbZT4Wq/N0\nslgndbajggHiMIIB3jAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAdBgNV\nHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwLwYDVR0RBCgwJoIQd3d3LmV4YW1w\nbGUudGVzdIIMZXhhbXBsZS50ZXN0hwTAAAIKMB0GA1UdDgQWBBQuMUVbXfDHZsLe\nFlEHnSrL0bMh6TAfBgNVHSMEGDAWgBT7k5kCNLbFwA6mVAlV3zaBislI5zBhBggr\nBgEFBQcBAQRVMFMwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmV4YW1wbGUudGVz\ndDArBggrBgEFBQcwAoYfaHR0cDovL3BraS5leGFtcGxlLnRlc3QvaW50LmNydDAw\nBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vY3JsLmV4YW1wbGUudGVzdC9pbnQuY3Js\nMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcGCSsGAQQBho0fATAqMCgGCCsGAQUFBwIB\nFhxodHRwczovL3BraS5leGFtcGxlLnRlc3QvY3BzMEsGCisGAQQB1nkCBAIEPQQ7\nADkANwBnVrBBAcvljHomKVT/KjJqZk7slVSrrLJc04j+mfiyCAAAAZt22qgAAAAE\nAwAIMAYCAQECAQEwCgYIKoZIzj0EAwIDSQAwRgIhAItLxsx9fdGDv8VcEjutYufp\njl9EzIv0BlAgbWaiomqCAiEAwQYOJuXmHyQW8aDAxDiNkkai45zfZvGmiA50yQXd\nSf0=\n-----END CERTIFICATE-----"
                  }
                },
                "example3": {
                  "summary": "Certificate signing request (CSR)",
                  "value": {
                    "input": "-----BEGIN CERTIFICATE REQUEST-----\nMIIBETCBuQIBADAbMRkwFwYDVQQDDBB3d3cuZXhhbXBsZS50ZXN0MFkwEwYHKoZI\nzj0CAQYIKoZIzj0DAQcDQgAEvB+Ve+ZxYGU023oRaqDzTME6I+dScbswJaGWGKyb\nBn9g6WPKvwr9R0CRd/ouV/i/Swuel1tlPhar83SyWCd1tqA8MDoGCSqGSIb3DQEJ\nDjEtMCswKQYDVR0RBCIwIIIQd3d3LmV4YW1wbGUudGVzdIIMZXhhbXBsZS50ZXN0\nMAoGCCqGSM49BAMCA0cAMEQCIFtTQ9UikF+QEnE0FX4KHx4jk3b74Ew2lN553z5v\n3MFGAiBW7CE8br3gqLDcD1/wPXz8IHyjuWK2QjNKZhQsvNnO3Q==\n-----END CERTIFICATE REQUEST-----",
                    "showAsn1": true
                  }
                },
                "example4": {
                  "summary": "Expired RSA-1024 / SHA-1 self-signed certificate",
                  "value": {
                    "input": "-----BEGIN CERTIFICATE-----\nMIIB9TCCAV6gAwIBAgICEAMwDQYJKoZIhvcNAQEFBQAwHjEcMBoGA1UEAwwTbGVn\nYWN5LmV4YW1wbGUudGVzdDAeFw0xNTAxMDEwMDAwMDBaFw0xNjAxMDEwMDAwMDBa\nMB4xHDAaBgNVBAMME2xlZ2FjeS5leGFtcGxlLnRlc3QwgZ8wDQYJKoZIhvcNAQEB\nBQADgY0AMIGJAoGBAPyMD7pOdLS7ntcFc5YcdDO0zS5FPXfbvww24wPO4b/K7jFC\ngz8cC/zhpQKOUMvkjNFoNW6dLXFHo8y50lc94kEVdt2O82fPabfD1Hk19tIffrpv\nipz/AJ0IrrZ3wryQA+TokA5RncLWc3b455ARW4rqTNVRmi7Jc1E5lz5xOLZnAgMB\nAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQW\nBBS2i8s2jp7EU8BH+Pq3UpA2pOk4yzANBgkqhkiG9w0BAQUFAAOBgQAwV9Okxj1W\nNP8Lv0C7LxFOB6+bvSbTSczP3uJeiOvCz8BcnYhabLtzk1Ul0roX+DLlcO+2klLS\nLmrC5oJwIOxfkNeNtZHizwhfvMq6eT5SpNn4+XSFo+9uhlfPZE8MDbESWPfxj8u7\nOkW0Y8FMiV/RfTHKKJO1429e59BVufKvoA==\n-----END CERTIFICATE-----"
                  }
                },
                "example5": {
                  "summary": "Generic ASN.1 tree of a certificate",
                  "value": {
                    "input": "-----BEGIN CERTIFICATE-----\nMIIBpDCCAUqgAwIBAgICEAAwCgYIKoZIzj0EAwIwOTELMAkGA1UEBhMCREUxEzAR\nBgNVBAoMCkRlbW8gVHJ1c3QxFTATBgNVBAMMDERlbW8gUm9vdCBDQTAeFw0yNTAx\nMDEwMDAwMDBaFw0zNTAxMDEwMDAwMDBaMDkxCzAJBgNVBAYTAkRFMRMwEQYDVQQK\nDApEZW1vIFRydXN0MRUwEwYDVQQDDAxEZW1vIFJvb3QgQ0EwWTATBgcqhkjOPQIB\nBggqhkjOPQMBBwNCAATTrpHwl14fB2G9rruBlIhJYzEoxeDEB+dK/BTnA5rmGLpo\ncUF66cgob5+4knEsMCj0DBKDbsXXZdT0LCStDhRQo0IwQDAPBgNVHRMBAf8EBTAD\nAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUHR+G6UD4w67G0e1x8g++7gTn\nJdUwCgYIKoZIzj0EAwIDSAAwRQIhAKFCNk4jPJLSLSZW/h594Y5s9ASp/10vVZgG\nANqkwaj+AiBmcW2LQn8vPqusJpwbtGMmubShkGp6/gME7qX/EJny7g==\n-----END CERTIFICATE-----",
                    "mode": "asn1"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/X509CertificateInspectorResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows": {
      "get": {
        "operationId": "listWorkflows",
        "summary": "Multi-tool workflows",
        "responses": {
          "200": {
            "description": "Workflow list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "CryptoKitchenInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "input": {
            "title": "Input",
            "type": "string",
            "maxLength": 2000000
          },
          "inputFile": {
            "title": "Or upload a file",
            "description": "Any file up to 10 MB, processed as raw bytes. Upload as {filename, contentType?, contentBase64}. Max 10240 KiB. Accepts */*.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "inputEncoding": {
            "title": "Pasted input is",
            "type": "string",
            "enum": [
              "text",
              "hex",
              "base64"
            ],
            "default": "text"
          },
          "recipe": {
            "title": "Recipe (one operation per line)",
            "description": "Syntax: op-id name=value name=\"value with spaces\". Operations: to-base64, from-base64, to-base64url, to-base32, from-base32, to-base58, from-base58, to-hex (separator?), from-hex, to-hexdump, url-encode (all?), url-decode (plus?), html-encode (nonAscii?), html-decode, punycode-encode, punycode-decode, qp-encode, qp-decode, gzip (level?), gunzip, deflate, inflate, deflate-raw, inflate-raw, brotli-compress (quality?), brotli-decompress, hash (alg?, format?), hmac (alg?, key, format?), crc32, aes-encrypt (mode?, key, iv, aad?, padding?), aes-decrypt (mode?, key, iv, tag?, aad?, padding?), xor (key), rot13, caesar (shift?), vigenere-encode (key), vigenere-decode (key), jwt-decode, jwt-verify (key, alg?), uuid-parse, ulid-parse, timestamp (unit?), json-pretty (indent?, sortKeys?), json-minify, regex-extract (pattern, flags?, group?), text-case (mode?), reverse (unit?), byte-swap (width?), entropy, magic (depth?). Byte arguments accept hex:, b64: or utf8: prefixes. Use @key to insert the secret field.",
            "type": "string",
            "maxLength": 20000,
            "default": "from-base64\ngunzip\njson-pretty"
          },
          "key": {
            "title": "Secret / key (referenced as @key)",
            "description": "Optional: HMAC/JWT secret or a PEM/JWK public key for jwt-verify. Hidden in the results.",
            "type": "string",
            "maxLength": 20000
          },
          "outputFormat": {
            "title": "Show output as",
            "type": "string",
            "enum": [
              "auto",
              "text",
              "hex",
              "base64"
            ],
            "default": "auto"
          }
        },
        "required": []
      },
      "CryptoKitchenResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "inputBytes",
              "recipe",
              "steps",
              "failed",
              "output",
              "artifact"
            ],
            "properties": {
              "inputBytes": {
                "type": "integer"
              },
              "recipe": {
                "type": "string"
              },
              "steps": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "index",
                    "op",
                    "label",
                    "args",
                    "bytes",
                    "kind",
                    "preview",
                    "notes",
                    "error"
                  ],
                  "properties": {
                    "index": {
                      "type": "integer"
                    },
                    "op": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    },
                    "args": {
                      "type": "string",
                      "description": "Arguments as given; secret values are hidden."
                    },
                    "bytes": {
                      "type": "integer"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "text",
                        "binary"
                      ]
                    },
                    "preview": {
                      "type": "string"
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "error": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              },
              "failed": {
                "type": "boolean"
              },
              "output": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "bytes",
                  "kind",
                  "text",
                  "hex",
                  "base64",
                  "sha256",
                  "truncated"
                ],
                "properties": {
                  "bytes": {
                    "type": "integer"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "text",
                      "binary"
                    ]
                  },
                  "text": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "hex": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "base64": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "sha256": {
                    "type": "string"
                  },
                  "truncated": {
                    "type": "boolean",
                    "description": "true if text/hex/base64 were cut to 100,000 characters (download the artifact for everything)"
                  }
                }
              },
              "artifact": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "artifactId",
                  "filename",
                  "mime",
                  "bytes",
                  "sha256",
                  "path"
                ],
                "properties": {
                  "artifactId": {
                    "type": "string"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "mime": {
                    "type": "string"
                  },
                  "bytes": {
                    "type": "integer"
                  },
                  "sha256": {
                    "type": "string"
                  },
                  "path": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "HashHmacCalculatorInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "text": {
            "title": "Text",
            "description": "Hashed exactly as entered (no trailing newline is added). Leave empty when you choose a file.",
            "type": "string",
            "maxLength": 1000000
          },
          "textFormat": {
            "title": "Text is",
            "type": "string",
            "enum": [
              "utf8",
              "hex",
              "base64"
            ],
            "default": "utf8"
          },
          "file": {
            "title": "Or a file",
            "description": "Any file up to 100 MB. With JavaScript on it is hashed in your browser and never uploaded. Upload as {filename, contentType?, contentBase64}. Max 102400 KiB. Accepts */*.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "algorithms": {
            "title": "Algorithms",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "md5",
                "sha1",
                "sha224",
                "sha256",
                "sha384",
                "sha512",
                "sha3-256",
                "sha3-512",
                "blake2b512",
                "blake2s256",
                "crc32"
              ]
            },
            "default": [
              "md5",
              "sha1",
              "sha256",
              "sha512",
              "sha3-256",
              "blake2b512",
              "crc32"
            ]
          },
          "hmacKey": {
            "title": "HMAC key (optional)",
            "description": "With a key, an HMAC (RFC 2104) is computed instead of a plain hash.",
            "type": "string",
            "maxLength": 4096
          },
          "hmacKeyFormat": {
            "title": "Key is",
            "type": "string",
            "enum": [
              "utf8",
              "hex",
              "base64"
            ],
            "default": "utf8"
          },
          "outputEncoding": {
            "title": "Output",
            "type": "string",
            "enum": [
              "hex",
              "base64"
            ],
            "default": "hex"
          },
          "expected": {
            "title": "Expected hash to compare (optional)",
            "description": "Paste a published checksum (hex or Base64); it is compared with every computed value.",
            "type": "string",
            "maxLength": 300
          }
        },
        "required": []
      },
      "HashHmacCalculatorResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "source",
              "inputBytes",
              "mode",
              "encoding",
              "digests",
              "comparison"
            ],
            "properties": {
              "source": {
                "type": "string",
                "enum": [
                  "text",
                  "file"
                ]
              },
              "filename": {
                "type": "string"
              },
              "inputBytes": {
                "type": "integer"
              },
              "mode": {
                "type": "string",
                "enum": [
                  "hash",
                  "hmac"
                ]
              },
              "encoding": {
                "type": "string",
                "enum": [
                  "hex",
                  "base64"
                ]
              },
              "digests": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "algorithm",
                    "label",
                    "bits",
                    "hex",
                    "base64",
                    "note"
                  ],
                  "properties": {
                    "algorithm": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    },
                    "bits": {
                      "type": "integer"
                    },
                    "hex": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "base64": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "note": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              },
              "comparison": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "expected",
                  "format",
                  "matched"
                ],
                "properties": {
                  "expected": {
                    "type": "string"
                  },
                  "format": {
                    "type": "string"
                  },
                  "matched": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "KeyDerivationLabInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "password": {
            "title": "Password or input key material",
            "type": "string",
            "maxLength": 1024
          },
          "passwordFormat": {
            "title": "Password is",
            "type": "string",
            "enum": [
              "utf8",
              "hex",
              "base64"
            ],
            "default": "utf8"
          },
          "salt": {
            "title": "Salt",
            "description": "Use a random, unique salt of 16 bytes per password in real systems.",
            "type": "string",
            "maxLength": 1024
          },
          "saltFormat": {
            "title": "Salt is",
            "type": "string",
            "enum": [
              "utf8",
              "hex",
              "base64"
            ],
            "default": "utf8"
          },
          "algorithms": {
            "title": "Functions",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "pbkdf2-sha1",
                "pbkdf2-sha256",
                "pbkdf2-sha512",
                "scrypt",
                "argon2id",
                "hkdf-sha256",
                "hkdf-sha512"
              ]
            },
            "default": [
              "pbkdf2-sha256",
              "scrypt",
              "argon2id",
              "hkdf-sha256"
            ]
          },
          "keyLength": {
            "title": "Output length",
            "type": "integer",
            "minimum": 16,
            "maximum": 128,
            "default": 32,
            "x-unit": "bytes"
          },
          "pbkdf2Iterations": {
            "title": "PBKDF2 iterations",
            "description": "Empty = OWASP value for each hash (SHA-1 1,300,000; SHA-256 600,000; SHA-512 210,000).",
            "type": "integer",
            "minimum": 1,
            "maximum": 5000000
          },
          "scryptLogN": {
            "title": "scrypt cost N = 2^…",
            "type": "integer",
            "minimum": 1,
            "maximum": 20,
            "default": 17
          },
          "scryptR": {
            "title": "scrypt block size r",
            "type": "integer",
            "minimum": 1,
            "maximum": 32,
            "default": 8
          },
          "scryptP": {
            "title": "scrypt parallelism p",
            "type": "integer",
            "minimum": 1,
            "maximum": 16,
            "default": 1
          },
          "argon2MemoryKiB": {
            "title": "Argon2 memory",
            "type": "integer",
            "minimum": 8,
            "maximum": 262144,
            "default": 19456,
            "x-unit": "KiB"
          },
          "argon2Passes": {
            "title": "Argon2 passes (t)",
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "default": 2
          },
          "argon2Parallelism": {
            "title": "Argon2 parallelism (p)",
            "type": "integer",
            "minimum": 1,
            "maximum": 8,
            "default": 1
          },
          "hkdfInfo": {
            "title": "HKDF info (context)",
            "type": "string",
            "maxLength": 1024
          },
          "outputEncoding": {
            "title": "Output",
            "type": "string",
            "enum": [
              "hex",
              "base64"
            ],
            "default": "hex"
          }
        },
        "required": [
          "password",
          "salt"
        ]
      },
      "KeyDerivationLabResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "passwordBytes",
              "saltBytes",
              "keyLength",
              "encoding",
              "argon2Available",
              "derivations"
            ],
            "properties": {
              "passwordBytes": {
                "type": "integer"
              },
              "saltBytes": {
                "type": "integer"
              },
              "keyLength": {
                "type": "integer"
              },
              "encoding": {
                "type": "string",
                "enum": [
                  "hex",
                  "base64"
                ]
              },
              "argon2Available": {
                "type": "boolean"
              },
              "derivations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "algorithm",
                    "label",
                    "parameters",
                    "memoryBytes",
                    "meetsOwasp",
                    "owasp",
                    "hex",
                    "base64",
                    "note"
                  ],
                  "properties": {
                    "algorithm": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    },
                    "parameters": {
                      "type": "string"
                    },
                    "memoryBytes": {
                      "type": "integer",
                      "description": "Approximate working memory the function needs."
                    },
                    "meetsOwasp": {
                      "type": [
                        "boolean",
                        "null"
                      ],
                      "description": "Parameters at or above the OWASP minimum (null = not a password hash)."
                    },
                    "owasp": {
                      "type": "string"
                    },
                    "hex": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "base64": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "note": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "FileEncryptionStudioInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "action": {
            "title": "Action",
            "type": "string",
            "enum": [
              "encrypt",
              "decrypt"
            ],
            "default": "encrypt"
          },
          "file": {
            "title": "File",
            "description": "Up to 100 MB. With JavaScript on, the file is processed in your browser and never uploaded. Upload as {filename, contentType?, contentBase64}. Max 102400 KiB. Accepts */*.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "keyMode": {
            "title": "Key",
            "type": "string",
            "enum": [
              "password",
              "rawkey"
            ],
            "default": "password"
          },
          "password": {
            "title": "Password",
            "description": "Use a long passphrase. It cannot be recovered: without it the file is lost.",
            "type": "string",
            "maxLength": 1024
          },
          "rawKey": {
            "title": "Raw key (64 hex or 44 Base64 characters)",
            "description": "Raw-key mode. Leave empty when encrypting to generate a random key (shown once).",
            "type": "string",
            "maxLength": 200
          },
          "iterations": {
            "title": "PBKDF2 iterations (encrypt)",
            "description": "At least 600,000 (OWASP 2023 recommendation for PBKDF2-HMAC-SHA-256). Decryption reads the value from the file.",
            "type": "integer",
            "minimum": 600000,
            "maximum": 10000000,
            "default": 600000
          },
          "seed": {
            "title": "Demo seed (optional; fixes salt and IV — never for real files)",
            "description": "Only for reproducible demos. Reusing a salt/IV with the same password breaks AES-GCM security.",
            "type": "string",
            "maxLength": 200
          }
        },
        "required": [
          "file"
        ]
      },
      "FileEncryptionStudioResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "action",
              "format",
              "kdf",
              "iterations",
              "saltHex",
              "ivHex",
              "headerBytes",
              "inputBytes",
              "outputBytes",
              "generatedKeyHex",
              "seeded",
              "artifact"
            ],
            "properties": {
              "action": {
                "type": "string",
                "enum": [
                  "encrypt",
                  "decrypt"
                ]
              },
              "format": {
                "type": "string",
                "description": "Container format id."
              },
              "kdf": {
                "type": "string",
                "enum": [
                  "pbkdf2-sha256",
                  "raw-key"
                ]
              },
              "iterations": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "saltHex": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "ivHex": {
                "type": "string"
              },
              "headerBytes": {
                "type": "integer"
              },
              "inputBytes": {
                "type": "integer"
              },
              "outputBytes": {
                "type": "integer"
              },
              "generatedKeyHex": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Only when a random raw key was generated for you."
              },
              "seeded": {
                "type": "boolean"
              },
              "artifact": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "artifactId",
                  "filename",
                  "mime",
                  "bytes",
                  "sha256",
                  "path"
                ],
                "properties": {
                  "artifactId": {
                    "type": "string"
                  },
                  "filename": {
                    "type": "string"
                  },
                  "mime": {
                    "type": "string"
                  },
                  "bytes": {
                    "type": "integer"
                  },
                  "sha256": {
                    "type": "string"
                  },
                  "path": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "PasswordGeneratorInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "mode": {
            "title": "Type",
            "type": "string",
            "enum": [
              "password",
              "passphrase"
            ],
            "default": "password"
          },
          "length": {
            "title": "Password length",
            "description": "Random password only. 16+ characters are recommended; 20+ for important accounts.",
            "type": "integer",
            "minimum": 4,
            "maximum": 128,
            "default": 20,
            "x-unit": "characters"
          },
          "charsets": {
            "title": "Character sets",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "lower",
                "upper",
                "digits",
                "symbols"
              ]
            },
            "default": [
              "lower",
              "upper",
              "digits",
              "symbols"
            ]
          },
          "excludeAmbiguous": {
            "title": "Avoid look-alike characters (I l 1 O 0 o | ` ' \")",
            "type": "boolean",
            "default": false
          },
          "requireEach": {
            "title": "Include at least one character from each selected set",
            "type": "boolean",
            "default": true
          },
          "words": {
            "title": "Number of words",
            "description": "Passphrase only. Each word adds 11 bits of entropy.",
            "type": "integer",
            "minimum": 3,
            "maximum": 20,
            "default": 6
          },
          "separator": {
            "title": "Word separator",
            "type": "string",
            "enum": [
              "hyphen",
              "space",
              "period",
              "underscore",
              "none"
            ],
            "default": "hyphen"
          },
          "capitalization": {
            "title": "Capitalisation",
            "type": "string",
            "enum": [
              "lower",
              "title",
              "upper",
              "random"
            ],
            "default": "lower"
          },
          "includeNumber": {
            "title": "Append a random digit to one random word",
            "type": "boolean",
            "default": false
          },
          "count": {
            "title": "How many",
            "type": "integer",
            "minimum": 1,
            "maximum": 20,
            "default": 5
          },
          "seed": {
            "title": "Demo seed (optional, makes output reproducible — never for real passwords)",
            "description": "Leave empty for real use. With a seed, anyone who knows it can regenerate the same passwords.",
            "type": "string",
            "maxLength": 200
          }
        },
        "required": []
      },
      "PasswordGeneratorResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "mode",
              "passwords",
              "entropyBits",
              "strength",
              "poolSize",
              "length",
              "words",
              "wordlist",
              "seeded",
              "crackTimes"
            ],
            "properties": {
              "mode": {
                "type": "string",
                "enum": [
                  "password",
                  "passphrase"
                ]
              },
              "passwords": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "entropyBits": {
                "type": "number",
                "description": "Entropy of each generated password in bits (log2 of the number of equally likely outputs)."
              },
              "strength": {
                "type": "string",
                "enum": [
                  "weak",
                  "fair",
                  "strong",
                  "very strong"
                ]
              },
              "poolSize": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Characters in the pool (password mode)."
              },
              "length": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "words": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "wordlist": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "id",
                  "size"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "size": {
                    "type": "integer"
                  }
                }
              },
              "seeded": {
                "type": "boolean"
              },
              "crackTimes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "scenario",
                    "guessesPerSecond",
                    "averageSeconds"
                  ],
                  "properties": {
                    "scenario": {
                      "type": "string"
                    },
                    "guessesPerSecond": {
                      "type": "number"
                    },
                    "averageSeconds": {
                      "type": "number"
                    }
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "PrivateBreachCheckerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "hash": {
            "title": "SHA-1 hash or 5-character prefix",
            "description": "Hex only. Never enter a password here. With JavaScript on, use the password box above: it is hashed in your browser.",
            "type": "string",
            "maxLength": 64
          }
        },
        "required": [
          "hash"
        ]
      },
      "PrivateBreachCheckerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "prefix",
              "mode",
              "found",
              "breachCount",
              "rangeEntries",
              "paddingEntries",
              "suffixes",
              "retrievedAt"
            ],
            "properties": {
              "prefix": {
                "type": "string",
                "description": "The only part of the hash sent to Have I Been Pwned."
              },
              "mode": {
                "type": "string",
                "enum": [
                  "full-hash",
                  "prefix-only"
                ]
              },
              "found": {
                "type": [
                  "boolean",
                  "null"
                ],
                "description": "null when only a prefix was given."
              },
              "breachCount": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "How often the password appears in the breach corpus (0 = not found)."
              },
              "rangeEntries": {
                "type": "integer",
                "description": "Real hash suffixes returned for the prefix."
              },
              "paddingEntries": {
                "type": "integer",
                "description": "Fake zero-count entries added by Add-Padding."
              },
              "suffixes": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "Prefix-only mode: all suffixes with counts so the caller can match locally.",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "suffix",
                    "count"
                  ],
                  "properties": {
                    "suffix": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    }
                  }
                }
              },
              "retrievedAt": {
                "type": "string"
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "RsaEccKeyInspectorInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "key": {
            "title": "Key (PEM, base64/hex DER, JWK or OpenSSH)",
            "description": "Public keys are best. Never paste production private keys into any web tool. With JavaScript on, private keys are converted to their public key in your browser before anything is sent.",
            "type": "string",
            "maxLength": 200000
          },
          "showAsn1": {
            "title": "Show the ASN.1 structure of the public key",
            "type": "boolean",
            "default": true
          }
        },
        "required": [
          "key"
        ]
      },
      "RsaEccKeyInspectorResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "inputFormat",
              "keyType",
              "isPrivate",
              "encrypted",
              "encryption",
              "sizeBits",
              "curve",
              "publicExponent",
              "comment",
              "fingerprints",
              "publicJwk",
              "publicPem",
              "opensshPublic",
              "rating",
              "findings"
            ],
            "properties": {
              "inputFormat": {
                "type": "string"
              },
              "keyType": {
                "type": "string"
              },
              "isPrivate": {
                "type": "boolean"
              },
              "encrypted": {
                "type": "boolean"
              },
              "encryption": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sizeBits": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "curve": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "publicExponent": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "comment": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "fingerprints": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "spkiSha256Hex",
                  "spkiSha256Base64",
                  "opensshSha256",
                  "opensshMd5",
                  "jwkThumbprint"
                ],
                "properties": {
                  "spkiSha256Hex": {
                    "type": "string"
                  },
                  "spkiSha256Base64": {
                    "type": "string",
                    "description": "base64 SHA-256 of the SPKI (HPKP / pin-sha256 format)"
                  },
                  "opensshSha256": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "opensshMd5": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "jwkThumbprint": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "RFC 7638, SHA-256, base64url"
                  }
                }
              },
              "publicJwk": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": {
                  "type": "string"
                }
              },
              "publicPem": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "opensshPublic": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "rating": {
                "type": "string",
                "enum": [
                  "good",
                  "ok",
                  "weak",
                  "critical",
                  "unknown"
                ]
              },
              "findings": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "level",
                    "text"
                  ],
                  "properties": {
                    "level": {
                      "type": "string",
                      "enum": [
                        "good",
                        "ok",
                        "info",
                        "weak",
                        "critical"
                      ]
                    },
                    "text": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "ShamirSecretSharingInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "action": {
            "title": "Action",
            "type": "string",
            "enum": [
              "split",
              "combine"
            ],
            "default": "split"
          },
          "secret": {
            "title": "Secret (split)",
            "description": "Text up to 10,000 characters (UTF-8).",
            "type": "string",
            "maxLength": 10000
          },
          "shares": {
            "title": "Number of shares (n)",
            "type": "integer",
            "minimum": 2,
            "maximum": 255,
            "default": 5
          },
          "threshold": {
            "title": "Threshold (k shares needed)",
            "description": "Split: any k shares recover the secret. Combine: used to check extra shares for consistency.",
            "type": "integer",
            "minimum": 2,
            "maximum": 255,
            "default": 3
          },
          "format": {
            "title": "Share format",
            "type": "string",
            "enum": [
              "hex",
              "base64"
            ],
            "default": "hex"
          },
          "checksum": {
            "title": "Add a 4-byte SHA-256 checksum so wrong or too few shares are detected",
            "type": "boolean",
            "default": true
          },
          "sharesInput": {
            "title": "Shares (combine), one per line",
            "type": "string",
            "maxLength": 200000
          },
          "seed": {
            "title": "Demo seed (optional, reproducible — never for real secrets)",
            "description": "Split only. With a seed the shares are predictable; leave empty for real use.",
            "type": "string",
            "maxLength": 200
          }
        },
        "required": []
      },
      "ShamirSecretSharingResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "action",
              "format",
              "checksum"
            ],
            "properties": {
              "action": {
                "type": "string",
                "enum": [
                  "split",
                  "combine"
                ]
              },
              "format": {
                "type": "string",
                "enum": [
                  "hex",
                  "base64"
                ]
              },
              "checksum": {
                "type": "boolean"
              },
              "shareCount": {
                "type": "integer"
              },
              "threshold": {
                "type": "integer"
              },
              "secretBytes": {
                "type": "integer"
              },
              "shareBytes": {
                "type": "integer"
              },
              "shares": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "seeded": {
                "type": "boolean"
              },
              "sharesUsed": {
                "type": "array",
                "items": {
                  "type": "integer"
                }
              },
              "secretText": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Recovered secret as UTF-8 text (null if not valid UTF-8)."
              },
              "secretHex": {
                "type": "string"
              },
              "checksumValid": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "consistent": {
                "type": [
                  "boolean",
                  "null"
                ],
                "description": "Extra shares beyond the threshold lie on the same polynomial (null if not checkable)."
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "TlsCipherSuiteSimulatorInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "serverPreset": {
            "title": "Server configuration",
            "type": "string",
            "enum": [
              "modern",
              "intermediate",
              "old",
              "custom"
            ],
            "default": "intermediate"
          },
          "customSuites": {
            "title": "Custom cipher suites (in server preference order)",
            "description": "OpenSSL names (ECDHE-RSA-AES128-GCM-SHA256), IANA names (TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) or hex codes (0xC02F), separated by colons, commas or new lines. OpenSSL keywords like HIGH or !aNULL are not expanded. Used only with \"Custom cipher list\".",
            "type": "string",
            "maxLength": 20000
          },
          "customProtocols": {
            "title": "Custom: enabled protocol versions",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "SSLv3",
                "TLSv1",
                "TLSv1.1",
                "TLSv1.2",
                "TLSv1.3"
              ]
            },
            "default": [
              "TLSv1.2",
              "TLSv1.3"
            ]
          },
          "customGroups": {
            "title": "Custom: key-exchange groups",
            "description": "Curve/group names in preference order, e.g. X25519MLKEM768, X25519, prime256v1, secp384r1, ffdhe2048.",
            "type": "string",
            "default": "X25519, prime256v1, secp384r1"
          },
          "certificate": {
            "title": "Server certificate",
            "type": "string",
            "enum": [
              "preset",
              "ecdsa",
              "rsa",
              "both"
            ],
            "default": "preset"
          },
          "rsaBits": {
            "title": "RSA key size",
            "type": "integer",
            "minimum": 512,
            "maximum": 16384,
            "default": 2048,
            "x-unit": "bits"
          },
          "dhBits": {
            "title": "DHE parameter size",
            "description": "Optional. Defaults to the preset value (old: 1024, intermediate: 2048) or 2048 for custom lists.",
            "type": "integer",
            "minimum": 512,
            "maximum": 8192,
            "x-unit": "bits"
          },
          "order": {
            "title": "Cipher order",
            "type": "string",
            "enum": [
              "preset",
              "server",
              "client"
            ],
            "default": "preset"
          },
          "clients": {
            "title": "Clients to simulate",
            "description": "Leave empty to simulate all clients.",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "android-2.3.7",
                "android-4.4.2",
                "android-5.0.0",
                "android-7.0",
                "android-8.1",
                "android-9.0",
                "chrome-49-xp-sp3",
                "chrome-70-win-10",
                "chrome-80-win-10",
                "chrome-131-win-10",
                "firefox-31.3.0-esr-win-7",
                "firefox-62-win-7",
                "firefox-73-win-10",
                "firefox-135-win-10",
                "edge-15-win-10",
                "edge-131-win-10",
                "ie-8-xp",
                "ie-11-win-7",
                "ie-11-win-10",
                "safari-9-ios-9",
                "safari-10-os-x-10.12",
                "safari-12.1.2-macos-10.14.6-beta",
                "safari-12.1.1-ios-12.3.1",
                "java-6u45",
                "java-7u25",
                "java-8u31",
                "java-8u161",
                "java-11.0.3",
                "java-12.0.1",
                "openssl-0.9.8y",
                "openssl-1.0.1l",
                "openssl-1.0.2s",
                "openssl-1.1.0k",
                "openssl-1.1.1c",
                "curl-openssl-1.1.1",
                "curl-openssl-1.0.2"
              ]
            }
          }
        },
        "required": []
      },
      "TlsCipherSuiteSimulatorResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "server",
              "grade",
              "gradeReasons",
              "clientsSimulated",
              "handshakesOk",
              "handshakesFailed",
              "results",
              "unknownSuites",
              "suiteTable",
              "datasetDate"
            ],
            "properties": {
              "server": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "label",
                  "protocols",
                  "suites12",
                  "suites13",
                  "groups",
                  "certificates",
                  "rsaBits",
                  "dhBits",
                  "serverOrder"
                ],
                "properties": {
                  "label": {
                    "type": "string"
                  },
                  "protocols": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "suites12": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "suites13": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "groups": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "certificates": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "rsaBits": {
                    "type": "integer"
                  },
                  "dhBits": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "serverOrder": {
                    "type": "boolean"
                  }
                }
              },
              "grade": {
                "type": "string"
              },
              "gradeReasons": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "clientsSimulated": {
                "type": "integer"
              },
              "handshakesOk": {
                "type": "integer"
              },
              "handshakesFailed": {
                "type": "integer"
              },
              "results": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "client",
                    "clientId",
                    "ok",
                    "protocol",
                    "cipher",
                    "cipherOpenssl",
                    "keyExchange",
                    "group",
                    "signature",
                    "certificate",
                    "forwardSecrecy",
                    "aead",
                    "helloRetry",
                    "failure",
                    "notes"
                  ],
                  "properties": {
                    "client": {
                      "type": "string"
                    },
                    "clientId": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "protocol": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "cipher": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "cipherOpenssl": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "keyExchange": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "group": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "signature": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "certificate": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "forwardSecrecy": {
                      "type": [
                        "boolean",
                        "null"
                      ]
                    },
                    "aead": {
                      "type": [
                        "boolean",
                        "null"
                      ]
                    },
                    "helloRetry": {
                      "type": "boolean"
                    },
                    "failure": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              },
              "unknownSuites": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "suiteTable": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "code",
                    "iana",
                    "openssl",
                    "keyExchange",
                    "auth",
                    "aead",
                    "forwardSecrecy",
                    "minVersion",
                    "ianaRecommended",
                    "weakness"
                  ],
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "iana": {
                      "type": "string"
                    },
                    "openssl": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "keyExchange": {
                      "type": "string"
                    },
                    "auth": {
                      "type": "string"
                    },
                    "aead": {
                      "type": "boolean"
                    },
                    "forwardSecrecy": {
                      "type": "boolean"
                    },
                    "minVersion": {
                      "type": "string"
                    },
                    "ianaRecommended": {
                      "type": "string"
                    },
                    "weakness": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              },
              "datasetDate": {
                "type": "string"
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "X509CertificateInspectorInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "input": {
            "title": "Certificate, chain or CSR (PEM, base64 or hex DER)",
            "type": "string",
            "maxLength": 1000000
          },
          "file": {
            "title": "Or upload a file",
            "description": "PEM or binary DER, up to 1 MB. Upload as {filename, contentType?, contentBase64}. Max 977 KiB. Accepts .pem,.crt,.cer,.der,.csr,.p7b,.txt,application/x-x509-ca-cert,application/pkix-cert.",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "filename",
              "contentBase64"
            ],
            "properties": {
              "filename": {
                "type": "string"
              },
              "contentType": {
                "type": "string"
              },
              "contentBase64": {
                "type": "string"
              }
            }
          },
          "mode": {
            "title": "Mode",
            "type": "string",
            "enum": [
              "auto",
              "asn1"
            ],
            "default": "auto"
          },
          "showAsn1": {
            "title": "Include the ASN.1 tree of the first object",
            "type": "boolean",
            "default": false
          }
        },
        "required": []
      },
      "X509CertificateInspectorResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "kind",
              "objectCount",
              "certificates",
              "chain",
              "csr",
              "asn1"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "certificate",
                  "chain",
                  "csr",
                  "asn1"
                ]
              },
              "objectCount": {
                "type": "integer"
              },
              "certificates": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "index",
                    "subject",
                    "issuer",
                    "serialNumber",
                    "version",
                    "notBefore",
                    "notAfter",
                    "validityDays",
                    "daysRemaining",
                    "status",
                    "signatureAlgorithm",
                    "publicKey",
                    "publicKeyBits",
                    "sha256",
                    "sha1",
                    "spkiSha256",
                    "selfSigned",
                    "isCA",
                    "sans",
                    "keyUsage",
                    "extKeyUsage",
                    "basicConstraints",
                    "ocsp",
                    "caIssuers",
                    "crlDistributionPoints",
                    "policies",
                    "scts",
                    "subjectKeyId",
                    "authorityKeyId",
                    "mustStaple",
                    "extensions"
                  ],
                  "properties": {
                    "index": {
                      "type": "integer"
                    },
                    "subject": {
                      "type": "string"
                    },
                    "issuer": {
                      "type": "string"
                    },
                    "serialNumber": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer"
                    },
                    "notBefore": {
                      "type": "string"
                    },
                    "notAfter": {
                      "type": "string"
                    },
                    "validityDays": {
                      "type": "integer"
                    },
                    "daysRemaining": {
                      "type": "integer"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "valid",
                        "expired",
                        "not-yet-valid"
                      ]
                    },
                    "signatureAlgorithm": {
                      "type": "string"
                    },
                    "publicKey": {
                      "type": "string"
                    },
                    "publicKeyBits": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "sha256": {
                      "type": "string"
                    },
                    "sha1": {
                      "type": "string"
                    },
                    "spkiSha256": {
                      "type": "string"
                    },
                    "selfSigned": {
                      "type": "boolean"
                    },
                    "isCA": {
                      "type": "boolean"
                    },
                    "sans": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "keyUsage": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "extKeyUsage": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "basicConstraints": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "ca",
                        "pathLen"
                      ],
                      "properties": {
                        "ca": {
                          "type": "boolean"
                        },
                        "pathLen": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        }
                      }
                    },
                    "ocsp": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "caIssuers": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "crlDistributionPoints": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "policies": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "oid",
                          "name",
                          "cps"
                        ],
                        "properties": {
                          "oid": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "cps": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "scts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "version",
                          "logId",
                          "timestamp",
                          "hashAlgorithm",
                          "signatureAlgorithm"
                        ],
                        "properties": {
                          "version": {
                            "type": "integer"
                          },
                          "logId": {
                            "type": "string"
                          },
                          "timestamp": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "hashAlgorithm": {
                            "type": "string"
                          },
                          "signatureAlgorithm": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "subjectKeyId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "authorityKeyId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "mustStaple": {
                      "type": "boolean"
                    },
                    "extensions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "oid",
                          "name",
                          "critical"
                        ],
                        "properties": {
                          "oid": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "critical": {
                            "type": "boolean"
                          }
                        }
                      }
                    }
                  }
                }
              },
              "chain": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "inOrder",
                  "complete",
                  "suggestedOrder",
                  "links"
                ],
                "properties": {
                  "inOrder": {
                    "type": "boolean"
                  },
                  "complete": {
                    "type": "boolean",
                    "description": "Ends in a self-signed certificate with every link verified"
                  },
                  "suggestedOrder": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    }
                  },
                  "links": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "child",
                        "parent",
                        "nameMatch",
                        "signatureValid",
                        "note"
                      ],
                      "properties": {
                        "child": {
                          "type": "integer"
                        },
                        "parent": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "nameMatch": {
                          "type": "boolean"
                        },
                        "signatureValid": {
                          "type": [
                            "boolean",
                            "null"
                          ]
                        },
                        "note": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              },
              "csr": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "subject",
                  "publicKey",
                  "publicKeyBits",
                  "signatureAlgorithm",
                  "signatureValid",
                  "attributes",
                  "sans",
                  "keyUsage",
                  "extKeyUsage",
                  "basicConstraints",
                  "extensions",
                  "spkiSha256"
                ],
                "properties": {
                  "subject": {
                    "type": "string"
                  },
                  "publicKey": {
                    "type": "string"
                  },
                  "publicKeyBits": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "signatureAlgorithm": {
                    "type": "string"
                  },
                  "signatureValid": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "attributes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "sans": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "keyUsage": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "extKeyUsage": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "basicConstraints": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "additionalProperties": false,
                    "required": [
                      "ca",
                      "pathLen"
                    ],
                    "properties": {
                      "ca": {
                        "type": "boolean"
                      },
                      "pathLen": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      }
                    }
                  },
                  "extensions": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "oid",
                        "name",
                        "critical"
                      ],
                      "properties": {
                        "oid": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "critical": {
                          "type": "boolean"
                        }
                      }
                    }
                  },
                  "spkiSha256": {
                    "type": "string"
                  }
                }
              },
              "asn1": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "totalNodes",
                  "truncated",
                  "rows"
                ],
                "properties": {
                  "totalNodes": {
                    "type": "integer"
                  },
                  "truncated": {
                    "type": "boolean"
                  },
                  "rows": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "offset",
                        "depth",
                        "header",
                        "length",
                        "tag",
                        "value"
                      ],
                      "properties": {
                        "offset": {
                          "type": "integer"
                        },
                        "depth": {
                          "type": "integer"
                        },
                        "header": {
                          "type": "integer"
                        },
                        "length": {
                          "type": "integer"
                        },
                        "tag": {
                          "type": "string"
                        },
                        "value": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}