Zum Inhalt springen
ecdsa.com

Signatures

Verify an ECDSA signature

POSThttps://ecdsa.com/api/v1/verify

Verifies a signature over a message (or a precomputed digest) against a public key. Curves: P-256, P-384, P-521, secp256k1. Signature formats auto-detected: ASN.1 DER or raw r‖s, in hex, base64 or base64url. Public key formats: PEM SPKI ("PUBLIC KEY"), EC JWK, or a bare SEC1 point in hex/base64. A signature that simply does not verify returns valid: false with HTTP 200; only unparseable input yields 400.

API-Schlüssel
Optional; ein Schlüssel braucht den Scope api
Kontingentverbrauch mit Schlüssel
1 Einheit pro Aufruf
Rate Limit
60 Anfragen/min pro IP

Anfrage

JSON-Body: VerifyRequest

FeldTypErforderlichBeschreibung
publicKeystringja

PEM "PUBLIC KEY" (SPKI), EC JWK JSON, or a bare SEC1 point in hex/base64.

messagestringja

The signed message (or its digest — see messageIsDigest).

signaturestringja

DER or raw r‖s signature in hex, base64 or base64url (auto-detected).

hashstringnein

Digest applied to the message (ignored when messageIsDigest is true).

  • Standardwert "SHA-256"
  • einer der Werte "SHA-256", "SHA-384" oder "SHA-512"
curvestringnein

Force a curve, or auto to infer it from the key.

  • Standardwert "auto"
  • einer der Werte "auto", "P-256", "P-384", "P-521" oder "secp256k1"
messageEncodingstringnein

How the message string encodes bytes.

  • Standardwert "utf8"
  • einer der Werte "utf8", "hex" oder "base64"
messageIsDigestbooleannein

When true, message bytes are used as the digest directly (no hashing).

  • Standardwert false

Antworten

200Verification outcome.

FeldTypErforderlichBeschreibung
validbooleanja
curvestring | nullja

Curve the signature verified on (or the single candidate when it did not).

curvesTriedstring[]ja

Every curve tried, in order.

keySourcestringja

How the public key was encoded.

  • einer der Werte "pem-spki", "jwk" oder "raw-point"
signatureFormatstringja
  • einer der Werte "der" oder "raw"
detailsobjectja
details.rstringja

r as hex.

details.sstringja

s as hex.

details.highSbooleanja

s > n/2 (non-canonical for Bitcoin & co).

notesstring[]ja

Per-curve diagnostics.

Header: X-Request-Id · X-RateLimit-Limit · X-RateLimit-Remaining · X-RateLimit-Reset · X-Quota-Limit · X-Quota-Remaining · X-Quota-Reset

StatusBedeutungCodes
400Bad request. Input limits: a request body of at most 100 KB (a larger one is answered with 413) and arrays and objects nested at most 64 levels deep, JSON documents inside string fields included.
401Unauthorized.
403Forbidden.
404Not found.
405Method not allowed.
413Payload too large.
429Too many requests.
500Internal server error.
503Service unavailable.
504Gateway timeout.

Jede Fehlerantwort enthält das JSON-Fehlerobjekt; die Fehlertabelle erklärt, was jeder Code bedeutet und was zu tun ist.

Beispiel

P-256 key as PEM, UTF-8 message, DER signature

curl
curl -sS 'https://ecdsa.com/api/v1/verify' \
  -H 'content-type: application/json' \
  -d '{
  "publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4+8TCP3Hop/Acb8L7reksO9flyt1\nsUhvEqUs7a45RVDRDtAIZdTnOJcAhTCQvdzUBO4KUyxSRcZm6ro+2RGfSQ==\n-----END PUBLIC KEY-----",
  "message": "The quick brown fox jumps over the lazy dog",
  "signature": "3045022100df542bb71e0e3019086f1b1ba51f1aa0ec5e6afca05c3f5a7f4f02f5b7c39d24022030c59f1ac6d8c6893fb2a5ac8dfd9388d31ebd3382510dcfb7f28f9182eb1131"
}'
JavaScript (fetch)
const response = await fetch("https://ecdsa.com/api/v1/verify", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    "publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4+8TCP3Hop/Acb8L7reksO9flyt1\nsUhvEqUs7a45RVDRDtAIZdTnOJcAhTCQvdzUBO4KUyxSRcZm6ro+2RGfSQ==\n-----END PUBLIC KEY-----",
    "message": "The quick brown fox jumps over the lazy dog",
    "signature": "3045022100df542bb71e0e3019086f1b1ba51f1aa0ec5e6afca05c3f5a7f4f02f5b7c39d24022030c59f1ac6d8c6893fb2a5ac8dfd9388d31ebd3382510dcfb7f28f9182eb1131"
  }),
});
console.log(response.status, await response.json());
Python (httpx)
import httpx

response = httpx.post(
    "https://ecdsa.com/api/v1/verify",
    json={
        "publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4+8TCP3Hop/Acb8L7reksO9flyt1\nsUhvEqUs7a45RVDRDtAIZdTnOJcAhTCQvdzUBO4KUyxSRcZm6ro+2RGfSQ==\n-----END PUBLIC KEY-----",
        "message": "The quick brown fox jumps over the lazy dog",
        "signature": "3045022100df542bb71e0e3019086f1b1ba51f1aa0ec5e6afca05c3f5a7f4f02f5b7c39d24022030c59f1ac6d8c6893fb2a5ac8dfd9388d31ebd3382510dcfb7f28f9182eb1131",
    },
    timeout=30.0,
)
print(response.status_code, response.json())
Antwort 200
{
  "valid": true,
  "curve": "P-256",
  "curvesTried": [
    "P-256"
  ],
  "keySource": "pem-spki",
  "signatureFormat": "der",
  "details": {
    "r": "df542bb71e0e3019086f1b1ba51f1aa0ec5e6afca05c3f5a7f4f02f5b7c39d24",
    "s": "30c59f1ac6d8c6893fb2a5ac8dfd9388d31ebd3382510dcfb7f28f9182eb1131",
    "highS": false
  },
  "notes": []
}

Die Antwort der API auf dieses Beispiel, erzeugt für diese Seite am 20. Oktober 2026; relative Zeitangaben und Tageszahlen darin beziehen sich auf diesen Tag.

Fehlercodes

CodeStatusBedeutung
invalid_json400The body is not valid JSON or not a JSON object; or the input nests arrays and objects more than 64 levels deep (JSON documents inside string fields count too), or is too complex to inspect for private keys.
missing_field400A required field is absent or empty.
invalid_input400A field could not be parsed — the message explains exactly why.
private_key_rejected400The request contains private-key material (a PEM PRIVATE KEY block, an OpenSSH, SSH2 or PuTTY private key, or a JWK with "d"). Never send private keys anywhere.
unauthorized401The Authorization or X-API-Key header is malformed, the API key is not valid (wrong checksum, unknown, revoked or expired), or the operation needs a key.
forbidden_scope403The API key is valid but lacks a scope this operation requires; the message names it.
not_found404No operation exists at this path.
method_not_allowed405The path exists but does not accept this HTTP method; see the Allow header.
payload_too_large413The body exceeds 100 KB.
rate_limited429Too many requests — see Retry-After.
quota_exceeded429A daily or monthly quota of the API key's account is used up. X-Quota-Reset (and Retry-After) say when it starts over; retrying earlier cannot succeed.
internal_error500Unexpected server error.
service_unavailable503API keys cannot be verified right now (the key store is unreachable); retry shortly.
timeout504The operation did not finish within its time budget.

Schemas

Error

The error envelope of every non-2xx response.

FeldTypErforderlichBeschreibung
errorobjectja
error.codestringja

Machine-readable error code. Each response lists the codes it can carry; new codes may be added within v1, so treat an unknown code by its HTTP status.

error.messagestringja

Human-readable explanation (English).

error.requestIdstringnein

The X-Request-Id of this request — quote it when reporting a problem. Sent since v1.1.

error.detailobjectnein

Structured context for the error, such as the offending field; omitted when there is none.

  • beliebige Feldnamen
error.docsstringnein

Where the error codes are explained. Sent since v1.1.

  • Format uri

Alle Operationen findest du in der API-Referenz.