/api/fingerprint
MCP tool fingerprint Finds every public key in input and returns its fingerprints in the formats other tools print. SSH: ssh-keygen -l SHA256 and MD5. Certificates: openssl x509 -fingerprint SHA-1 and SHA-256 over the DER, plus the RFC 7469 SPKI pin. PEM public keys: SHA-256 over the SubjectPublicKeyInfo. Where an equivalent exists, the SSH fingerprint of the same key is included, so you can confirm that a certificate and an SSH key share a key. OpenPGP: v4 (SHA-1) and v6 (SHA-256) fingerprints and key IDs for the primary key and subkeys. Private keys are refused.
Browser version (runs locally): Fingerprints.
Try it
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
input required | string | — | One or more SSH public key lines, RFC 4716 blocks, PEM CERTIFICATE / PUBLIC KEY blocks, or an armored PGP public key block. |
Also accepted on every endpoint: format (json | text).
Parameters may come from the query string, a JSON object body, an urlencoded or multipart form,
or (for input) a text/plain body.
Global parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
format | json | text | json | json returns the documented object. text returns only the primary value as text/plain (see "Text output"). |
Response 200 application/json
| Field | Type | Description |
|---|---|---|
items | array of one of (by kind) | Keys found, in input order by format. |
items[] (kind = "ssh") | variant | SSH public key. |
items[].type | string | Key type, e.g. ssh-ed25519. |
items[].bits | integer | null | Key size. |
items[].comment | string | Trailing comment, often user@host. |
items[].ssh | object | |
items[].ssh.sha256 | string | SHA256: + unpadded Base64, as printed by ssh-keygen -l. |
items[].ssh.md5 | string | MD5: + colon hex, as printed by ssh-keygen -E md5 -l. |
items[] (kind = "certificate") | variant | X.509 certificate. |
items[].subject | string | Subject DN. |
items[].sha1 | string | SHA-1 of DER, colon hex. |
items[].sha256 | string | SHA-256 of DER, colon hex. |
items[].spkiSha256 | string | RFC 7469 pin. |
items[].ssh | object | null | |
items[].ssh.sha256 | string | SHA256: + unpadded Base64, as printed by ssh-keygen -l. |
items[].ssh.md5 | string | MD5: + colon hex, as printed by ssh-keygen -E md5 -l. |
items[] (kind = "public-key") | variant | PEM SubjectPublicKeyInfo. |
items[].algorithm | string | Key algorithm. |
items[].spkiSha256Hex | string | SHA-256 of the SPKI DER, colon hex. |
items[].spkiSha256 | string | RFC 7469 pin. |
items[].ssh | object | null | |
items[].ssh.sha256 | string | SHA256: + unpadded Base64, as printed by ssh-keygen -l. |
items[].ssh.md5 | string | MD5: + colon hex, as printed by ssh-keygen -E md5 -l. |
items[] (kind = "pgp") | variant | OpenPGP public key. |
items[].userIds | array of string | User IDs (not verified against self-signatures). |
items[].keys | array of object | Primary key and subkeys. |
items[].keys[].role | "primary" | "subkey" | primary or subkey. |
items[].keys[].version | integer | Key packet version (4, 5 or 6). |
items[].keys[].fingerprint | string | Uppercase hex fingerprint. |
items[].keys[].grouped | string | Fingerprint in groups of four, as GnuPG prints it. |
items[].keys[].keyId | string | Key ID: last 8 bytes (v4) or first 8 bytes (v5/v6) of the fingerprint. |
items[].keys[].algorithm | string | Public key algorithm. |
items[].keys[].bits | integer | null | Key size. |
items[].keys[].created | string | Key creation time, ISO 8601. |
Errors
Errors are JSON: {"error": "<message>", "code": "<code>", "param": "<name>"?}.
| Status | Code | When |
|---|---|---|
422 | unprocessable_input | No public key is found, a key is malformed, or the input contains a private key (which is refused without being parsed). |
400 | missing_parameter | A required parameter is absent. |
400 | unknown_parameter | A parameter name is not in the table above (typos are rejected, not ignored). |
400 | invalid_parameter | A value has the wrong type, is out of range, or is not an allowed value. |
413 | payload_too_large | The request body exceeds 1 MiB. |
405 | method_not_allowed | A method other than GET, POST or OPTIONS. |
Behaviour
- Idempotent: the same arguments always return the same result.
-
Requires a client ID and secret (authentication). Each call is
recorded as one metadata row against your client ID; inputs and outputs are never stored or
logged. Responses carry
cache-control: no-store. - CORS: any origin may call this endpoint from a browser, using your credentials.
Examples
Responses below were produced by running each request through this code at build time. Long strings are shortened.
SSH public key
curl -X POST 'https://util.caruana.me/api/fingerprint' \
-H 'content-type: application/json' \
-d '{"input":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHGVluSiNj6bqXsllRWYUFXc2JNxW9mDP9PntMYyVHeM me@host"}'
Response 200
{
"items": [
{
"kind": "ssh",
"type": "ssh-ed25519",
"bits": 256,
"comment": "me@host",
"ssh": {
"sha256": "SHA256:z/6pzDuxOun5oze7jd1IYwPEPvElvGHF6E/heDuWjEo",
"md5": "MD5:ed:33:28:56:1e:c6:f6:47:f4:4d:d0:da:97:32:18:ff"
}
}
]
}
Same call as an MCP tools/call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "fingerprint",
"arguments": {
"input": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHGVluSiNj6bqXsllRWYUFXc2JNxW9mDP9PntMYyVHeM me@host"
}
}
}OpenPGP v6 key (RFC 9580 sample)
curl -X POST 'https://util.caruana.me/api/fingerprint' \
-H 'content-type: application/json' \
-d '{"input":"-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxioGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laPCsQYf\nGwoAAABCBYJjh3/jAwsJBwUVCg4IDAIWAAKbAwIeCSIhBssYbE8GCaaX5NUt+mxy\nKwwfHifBilZwj2Ul7Ce62azJBScJAgcCAAAAAK0oIBA+LX0ifsDm185Ecds2v8lw\ngyU2kCcUmKfvBXbAf6rhRYWzuQOwEn7E/aLwIwRaLsdry0+VcallHhSu4RN6HWaE\nQsiPlR4zxP/TP7mhfVEe7XWPxtnMUMtf15OyA51YBM4qBmOHf+MZAAAAIIaTJINn\n+eUBXbki+PSAld2nhJh/LVmFsS+60WyvXkQ1wpsGGBsKAAAALAWCY4d/4wKbDCIh\nBssYbE8GCaaX5NUt+mxyKwwfHifBilZwj2Ul7Ce62azJAAAAAAQBIKbpGG2dWTX8\nj+VjFM21J0hqWlEg+bdiojWnKfA5AQpWUWtnNwDEM0g12vYxoWM8Y81W+bHBw805\nI8kWVkXU6vFOi+HWvv/ira7ofJu16NnoUkhclkUrk0mXubZvyl4GBg==\n-----END PGP PUBLIC KEY BLOCK-----\n"}'
Response 200
{
"items": [
{
"kind": "pgp",
"userIds": [],
"keys": [
{
"role": "primary",
"version": 6,
"fingerprint": "CB186C4F0609A697E4D52DFA6C722B0C1F1E27C18A56708F6525EC27BAD9ACC9",
"keyId": "CB186C4F0609A697",
"algorithm": "Ed25519",
"bits": 256,
"created": "2022-11-30T16:08:03.000Z",
"grouped": "CB18 6C4F 0609 A697 E4D5 2DFA 6C72 2B0C 1F1E 27C1 8A56 708F 6525 EC27 BAD9 ACC9"
},
{
"role": "subkey",
"version": 6,
"fingerprint": "12C83F1E706F6308FE151A417743A1F033790E93E9978488D1DB378DA9930885",
"keyId": "12C83F1E706F6308",
"algorithm": "X25519",
"bits": 256,
"created": "2022-11-30T16:08:03.000Z",
"grouped": "12C8 3F1E 706F 6308 FE15 1A41 7743 A1F0 3379 0E93 E997 8488 D1DB 378D A993 0885"
}
]
}
]
}
Same call as an MCP tools/call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "fingerprint",
"arguments": {
"input": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxioGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laPCsQYf\nGwoAAABCBYJjh3/jAwsJBwUVCg4IDAIWAAKbAwIeCSIhBssYbE8GCaaX5NUt+mxy\nKwwfHifBilZwj2Ul7Ce62azJBScJAgcCAAAAAK0oIBA+LX0ifsDm185Ecds2v8lw\ngyU2kCcUmKfvBXbAf6rhRYWzuQOwEn7E/aLwIwRaLsdry0+VcallHhSu4RN6HWaE\nQsiPlR4zxP/TP7mhfVEe7XWPxtnMUMtf15OyA51YBM4qBmOHf+MZAAAAIIaTJINn\n+eUBXbki+PSAld2nhJh/LVmFsS+60WyvXkQ1wpsGGBsKAAAALAWCY4d/4wKbDCIh\nBssYbE8GCaaX5NUt+mxyKwwfHifBilZwj2Ul7Ce62azJAAAAAAQBIKbpGG2dWTX8\nj+VjFM21J0hqWlEg+bdiojWnKfA5AQpWUWtnNwDEM0g12vYxoWM8Y81W+bHBw805\nI8kWVkXU6vFOi+HWvv/ira7ofJu16NnoUkhclkUrk0mXubZvyl4GBg==\n-----END PGP PUBLIC KEY BLOCK-----\n"
}
}
}