---
title: "Signing test vectors — Anis Developers"
description: "Exact requests, answers and signatures to test a client you write yourself — before it ever calls Anis."
url: https://developers.anis.ly/docs/test-vectors/
language: en
---

> Every page of this documentation: https://developers.anis.ly/llms.txt

# Signing test vectors

A signature is right to the byte or it is refused, and a refusal never says which byte. These vectors let you find the byte yourself: each one is a real request, answer or enrolment proof with the exact text that was signed and the exact result expected.

> **Using the .NET SDK?**
>
> It already passes every vector. This page is for a client written by hand — or by an AI assistant.

> **Test keys only**
>
> The keys in these files are test keys — never Anis’s or any partner’s real keys — and `partners.anis.ly` is an example address. Use them to test, never to enrol.

## What is here

| Set | What it tests | Vectors |
| --- | --- | --- |
| Requests | Your signature base, byte for byte, for every kind of signed call | 9 |
| Answers | Your answer checks: which answers to accept and which to throw away | 39 |
| Enrolment | Your proof-of-possession message | 2 |

[`/vectors/index.json`](https://developers.anis.ly/vectors/index.json) lists every vector with its title, its file and — for answers — whether it must be accepted or rejected. The same index names the signed parts of each kind of call.

## Testing request signing

Each request vector carries the request (`request`), the signature’s times (`signature.created`, `signature.expires`), the test key (`key`) and what must come out (`expected`).

1. Build the signature base from `request.method`, `request.authority`, `request.path`, `request.canonicalQuery` (the query without its `?`), `request.anisDate`, `request.nonce`, `request.idempotencyKey` and the body in `request.bodyBase64`, with `key.keyId` as the key id.
2. Compare your `Content-Digest` with `expected.contentDigest`, your `Signature-Input` with `expected.signatureInput`, and your base with `expected.signatureBaseUtf8` — **byte for byte**.
3. Sign your base with the test private key (`key.privateKeyPkcs8Base64`) and check that `key.publicJwk` verifies it. An ECDSA signature is different every time, so compare the base, never the signature bytes.

`RQ-03` gives the host as a caller might type it (`request.authorityAsGiven`) and as it must be signed (`request.authority`, lower-case). `RQ-06` is a reveal: no body at all, so the digest of zero bytes.

## Testing answer verification

Each answer vector carries the answer (`response.status`, `response.headers`, `response.bodyBase64`), the `Signature-Input` of the request it answers (`request.signatureInput`), Anis’s published keys at that moment (`signingKeys`) and the time to use as your clock (`verifyAt`, Unix seconds — use it, not the real clock).

Your verifier must reach `expected.outcome`: `accept` or `reject`. For a rejection, `expected.reason` says why; your own error names may differ, so match the outcome and use the reason to understand a mismatch. `signatureBaseForDebugging` is the base Anis signed.

Most answers come in families: one that must be accepted (`RS-001-…`) and changed copies of it (`RS-001-…-M01` onward) that must each be rejected — one body byte changed, a rewritten digest, a DER signature, a signed part missing, a time out of the window. Others test the published keys: an answer signed by the next or the retiring key must be accepted, and a key document carrying a private member must be refused whole.

## Testing the enrolment proof

Each enrolment vector gives what the key submission returned (`keySubmissionResult`) and the test key (`key`).

1. Build the proof message from `keySubmissionResult` and compare it with `expected.proofMessageUtf8` — and the challenge’s hash with `expected.challengeHashHex`.
2. Sign it with the test key; `exampleSignature` is one valid signature, and `key.publicJwk` verifies both.
3. `expected.proofRequest` is the body to send.

## After the vectors pass

Call [Check your signature](https://developers.anis.ly/reference/check-signature.md) with your real key. It runs every check Anis runs on a signed call, reports what Anis saw, and changes nothing.
