Verify a signed message
Check the exact text, its signing key and that key’s state.
A person signs text from the Sign a message tab on their card. They can copy a signature block into a post, announcement or email. Your app sends that whole block to POST /v1/verify.
curl -fsS 'https://veil.rip/v1/verify' \
--json @signed-message.jsonThe JSON file contains a block field with the pasted text. You may add at in Unix seconds. Block mode cannot be combined with key, message, signature, platform or subject.
Read the verdict#
Use valid for the overall result. signatureOk checks the bytes of the signature. keyState says whether the key could sign at the chosen time. A signature can still match after its key has been revoked, while valid is false for the current time.
Use a publication time from a source you trust when passing at. A date written by the signer does not prove when a message was published.
Check the account too#
Raw-signature mode accepts key, message and signature. Add platform and subject together to ask whether that identity held the sending account at the selected time. For a bot, use the platform’s stable account ID.
Keep the message in the browser#
The /verify page can read a signature block from the URL fragment or from pasted text and check it locally. Fragment data after # stays in the browser. A /v/ link sends its message to the server so the link can have a social preview. Calling the verification API also sends the message to the server.
Build a sharing link#
Use the original message and signatureBytes from the signer. cardNumber is the permanent card number. The browser link supports both signature algorithms. Use the preview link only for Ed25519 and a message of at most 1500 UTF-8 bytes.
function base64url(bytes) {
return btoa(String.fromCharCode(...bytes))
.replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
}
const messageData = base64url(new TextEncoder().encode(message));
const signatureData = base64url(signatureBytes);
const browserLink = `https://veil.rip/verify#u=${cardNumber}&m=${messageData}&s=${signatureData}`;
const previewLink = `https://veil.rip/v/${cardNumber}/${signatureData}?m=${messageData}`;