veil

Verifica un file o un rilascio

Controlla la firma di un file dal suo hash, o di un elenco di checksum firmato, con le chiavi di una scheda. Questa POST legge soltanto.

POST/v1/verify
Accesso
Pubblico; chiave API facoltativa
Client
Fetch dal browser supportato

Corpo JSON#

NomePosizioneSignificato
signatureObbligatorioJSONLa firma come l’ha scritta lo strumento: il .sig di ssh-keygen -Y sign -n file, il .asc di gpg (o il suo .sig binario in base64), un testo di gpg --clear-sign, un file .minisig o un blocco di Veil.
sha256, sha512, blake2b512JSONGli hash del file in esadecimale, calcolati da te. Manda quello che usa la firma: una firma SSH lo nomina, una firma minisign prefirmata usa BLAKE2b-512, un blocco di Veil di un file nomina lo SHA-256.
nameJSONIl nome del file, al più 255 byte. In un elenco vale la riga con questo nome, altrimenti quella con questo nome senza cartelle.
listJSONIl testo esatto dell’elenco di checksum che una firma staccata copre (SHA256SUMS o SHA512SUMS, al più 1000 righe). Un elenco firmato in chiaro e il blocco di Veil di un rilascio portano il loro.
formatJSONssh, pgp, minisign o veil. Senza, il server lo legge dal testo.
cardJSONIl numero o l’alias di una scheda. Serve per una firma OpenPGP fatta da una sottochiave di firma, e per una chiave che la scheda ha tolto.
atJSONSecondi Unix facoltativi. Il default è la data di una firma OpenPGP, altrimenti adesso.

Esempi di richiesta#

cURL
sha512=$(sha512sum veil-1.2.tar.gz | cut -d' ' -f1)
jq -n --rawfile sig veil-1.2.tar.gz.sig --arg h "$sha512" \
  '{signature: $sig, sha512: $h, name: "veil-1.2.tar.gz"}' \
  | curl -fsS https://veil.rip/v1/verify --json @-
cURL
jq -n --rawfile sig SHA256SUMS.asc --rawfile list SHA256SUMS \
  --arg h "$(sha256sum veil-1.2.tar.gz | cut -d' ' -f1)" \
  '{signature: $sig, list: $list, sha256: $h, name: "veil-1.2.tar.gz", card: "1"}' \
  | curl -fsS https://veil.rip/v1/verify --json @-

Risposta#

HTTP 200application/json

valid è il verdetto complessivo: la firma regge, la chiave valeva, nessun bando dello staff la ferma, e l’hash del file è quello firmato. Gli altri campi lo spiegano.

CampoTipoSignificato
validbooleanVerdetto complessivo su firma, stato della chiave ed eventuale titolarità dell’account. HTTP 200 comprende anche valid=false.
signatureOkbooleanIndica se la firma crittografica è valida.
identityIdentityRef | nullScheda associata alla chiave o indicata dal blocco, se nota.
devicestring | nullDispositivo di firma, se identificato.
rolestring | nullRuolo di firma, se identificato.
keyStateKeyState | nullValidità della chiave nell’istante richiesto.
accountobject | nullplatform, subject, owned e reason quando sono stati richiesti platform/subject.
reasonstring | nullNull quando valida. Altrimenti bad_signature, unknown_key, unknown_identity, other_card, not_yet_valid, revoked, key_banned, identity_banned, identity_erased, hash_mismatch o not_in_list.
keystring | nullLa chiave di dispositivo in hex per un blocco di Veil, la chiave pubblica di altri sistemi come la scrive la scheda per gli altri formati.
formatstringssh, pgp, minisign o veil.
externalobject | nullLa chiave pubblica di altri sistemi: type, fp, label, addedIn, removedIn, e signer, la chiave che ha firmato (l’impronta di una sottochiave di firma OpenPGP quando ha firmato una sottochiave).
signedAtstring | nullLa data che dichiara una firma OpenPGP, scritta dall’orologio di chi firma. Null per gli altri formati.
atFromstringDa dove viene il momento del controllo: request, signature o now.
coversstringfile o list.
hashstring | nullL’hash del file usato nel controllo: sha256, sha512 o blake2b512.
fileobject | nullIl nome e gli hash che hai mandato.
listobject | nullLe righe dell’elenco firmato: name, alg e hash.
matchobject | nullLa riga del blocco o dell’elenco per il tuo file: name, alg, expected e ok.

Esempio di risposta

Valori illustrativi. Leggi la risposta corrente della tua richiesta.

json
{
  "valid": false,
  "signatureOk": true,
  "identity": {
    "n": 1,
    "url": "https://veil.rip/u/1",
    "name": "Marta Lanzoni",
    "nameHidden": false
  },
  "device": null,
  "role": null,
  "keyState": {
    "at": 1793287911,
    "active": true,
    "reason": "active",
    "validFrom": "2026-10-29T15:54:50Z",
    "validUntil": null
  },
  "account": null,
  "reason": "hash_mismatch",
  "key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKX/sjzOxM0MkL47LkMqAm0iZXcdiRGBJiqvesABK66k",
  "format": "ssh",
  "external": {
    "type": "ssh-ed25519",
    "fp": "SHA256:yKGK3rJbLA9EAbnKwNXuQvLvsvT0WRrii16h6sF9Rwk",
    "label": "Release key",
    "addedIn": 2,
    "removedIn": null,
    "signer": "SHA256:yKGK3rJbLA9EAbnKwNXuQvLvsvT0WRrii16h6sF9Rwk"
  },
  "signedAt": null,
  "atFrom": "now",
  "covers": "list",
  "hash": "sha256",
  "file": {
    "name": "veil-1.2.tar.gz",
    "sha256": "5d2aebc96df7ba9f758fbaaca850d629e39284b55d676c828e6498962b694d12",
    "sha512": null
  },
  "list": {
    "lines": [
      {
        "name": "veil-1.2.tar.gz",
        "alg": "sha256",
        "hash": "04cac27551ecc1b787e5ce856537f28802f70c1222efa5454f0ab626f4c242c2"
      }
    ]
  },
  "match": {
    "name": "veil-1.2.tar.gz",
    "alg": "sha256",
    "expected": "04cac27551ecc1b787e5ce856537f28802f70c1222efa5454f0ab626f4c242c2",
    "ok": false
  }
}

Apri un oggetto annidato per leggerne i campi. I tipi con null ammettono un valore null; i campi optional possono essere assenti. Gli altri campi sono presenti nell’oggetto.

Riferimento alla scheda IdentityRef
CampoTipoSignificato
nintegerNumero permanente della scheda.
urlstringURL permanente della scheda.
namestringNome visualizzato corrente.
nameHiddenbooleanIndica se lo staff nasconde il nome.
Stato della chiave in un istante KeyState
CampoTipoSignificato
atintegerIstante controllato, in secondi Unix.
activebooleanIndica se la chiave era attiva in quell’istante.
reasonstringactive, not_yet_valid o revoked.
validFromstringData e ora di pubblicazione della versione che l’ha aggiunta.
validUntilstring | nullData e ora di pubblicazione della revoca, oppure null.

Intestazioni della risposta#

IntestazioneValoreSignificato
Content-Typeapplication/jsonUsa il tipo dichiarato per scegliere come leggere il corpo.
DateHTTP dateOra del server. Confrontala con il tuo orologio per firmare le richieste.
Retry-Afterinteger seconds, on rate_limited or busyAttendi almeno questo intervallo prima di riprovare. Altri codici 429/503 non lo includono necessariamente.

Cosa verificare#

Questo è il verdetto del server sull’hash che hai mandato. Per controllare da te, verifica la firma sul file con le chiavi della scheda di GET /u/{card}/keys.txt, e le prove della scheda in un browser.

Note d’uso#

  • Il server non vede mai il file. Manda il suo hash, calcolato da te, con la firma. Una firma sui byte del file (una firma staccata OpenPGP, una firma minisign legacy) risponde 422 file_needed: controllala in un browser su veil.rip/verify o con l’azione GitHub, oppure firma un elenco di checksum.
  • La modalità file comincia con sha256, sha512, blake2b512 o list, oppure con una firma che arriva senza key e message. Non si combina con key, message, platform, subject o block.
  • Una firma OpenPGP porta una data scritta dall’orologio di chi firma, e lo stato della chiave si legge a quella data se non mandi at. Passa in at un orario di pubblicazione fidato quando ce l’hai. Le firme SSH e minisign non hanno data.

Errori#

Gli errori API restituiscono un oggetto error. Usa error.code nella logica del programma; error.message è un testo inglese per le persone e può cambiare. Guida a risposte ed errori

HTTPCodiceSignificato e cosa fare
400hash_needed

La firma copre un hash del file che la richiesta non porta. Il messaggio comincia con il suo nome: sha256, sha512 o blake2b512.

Calcola quell’hash del file (sha256sum, sha512sum o b2sum) e mandalo nel campo con lo stesso nome.

400invalid_block

Il blocco firma non è leggibile o indica un’altra rubrica.

Incolla il blocco completo con il messaggio e usa la rubrica che indica.

400invalid_file_signature

La firma di un file o di un elenco di checksum non si legge. Il messaggio comincia con il motivo: unreadable, namespace (una firma SSH fatta per un uso diverso dai file), pgp_type, pgp_version, weak_hash, list_unreadable o block_message.

Manda il file della firma come l’ha scritto lo strumento. Firma i file con ssh-keygen -Y sign -n file, gpg --detach-sign con SHA-256 o SHA-512, oppure minisign -Sm.

400invalid_json

Il corpo non è un oggetto JSON, contiene chiavi duplicate o dati finali.

Invia un solo oggetto JSON valido con Content-Type application/json.

400invalid_parameter

Un campo del percorso, della query o del corpo manca, è malformato o fuori intervallo.

Correggi il campo indicato in error.message prima di inviare di nuovo.

413payload_too_large

Il corpo della richiesta supera il limite in byte dell’endpoint.

Riduci il corpo codificato. La gestione delle chiavi API ammette al massimo 8 KiB.

422file_needed

Una firma staccata OpenPGP o una firma minisign legacy del file stesso. Copre i byte del file, e il server non vede mai il file.

Controllala dove sta il file: su veil.rip/verify in un browser o con l’azione GitHub. Oppure firma un elenco di checksum, che il server controlla in ogni formato.

Quando usi una chiave API facoltativa
HTTPCodiceSignificato e cosa fare
401invalid_api_key

La credenziale Bearer è malformata, sconosciuta, scaduta o revocata.

Usa una chiave attiva. Per l’accesso pubblico anonimo, rimuovi del tutto Authorization. Credenziali non valide non attivano automaticamente l’accesso anonimo.

403api_key_scope

La chiave API non ha il permesso read o verify, oppure l’endpoint non accetta chiavi Bearer.

Usa il permesso corretto. Le modifiche alle schede e la gestione delle chiavi richiedono una firma del dispositivo.

403api_key_suspended

Questa chiave API è sospesa.

Chiedi allo staff di ripristinarla; un’altra chiave non rimuove la sospensione dell’account.

403developer_suspended

L’account API del titolare è sospeso oppure la scheda titolare non è disponibile.

Controlla l’account titolare e le restrizioni dello staff. Creare un’altra chiave non aggira la sospensione.

Errori comuni delle richieste
HTTPCodiceSignificato e cosa fare
429rate_limited

È stato superato un limite anonimo, delle richieste firmate o della chiave API.

Attendi almeno i secondi indicati da Retry-After. Condividi coda e budget dei tentativi tra i tuoi processi.

500internal_error

Si è verificato un errore imprevisto del server. I dettagli interni non vengono restituiti.

Riprova le letture con attese crescenti e un limite. Controlla l’esito delle scritture prima di inviare una nuova operazione firmata.

503busy

L’applicazione ha raggiunto un limite temporaneo di concorrenza o del database.

Attendi i secondi indicati da Retry-After e riprova con attese crescenti e un limite.