{"revision":"0ed62d2c742f8e20","language":"it","entry":{"id":"verify-file","kind":"endpoint","group":"keys","title":"Verifica un file o un rilascio","method":"POST","path":"/v1/verify","paths":[],"summary":"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.","response":"Il verdetto della verifica di un messaggio, più format, external, signedAt, atFrom, covers, hash, file, list e match.","parameters":[],"sample":"/v1/verify","access":"public","base":"directory","notes":["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."],"errors":["400 hash_needed","400 invalid_block","400 invalid_file_signature","400 invalid_json","400 invalid_parameter","401 invalid_api_key","403 api_key_scope","403 api_key_suspended","403 developer_suspended","413 payload_too_large","422 file_needed","429 rate_limited","500 internal_error","503 busy"],"related":["verify-files","verify-message","external-keys-file","lookup"],"sections":[{"kind":"code","language":"shell","code":"sha512=$(sha512sum veil-1.2.tar.gz | cut -d' ' -f1)\njq -n --rawfile sig veil-1.2.tar.gz.sig --arg h \"$sha512\" \\\n  '{signature: $sig, sha512: $h, name: \"veil-1.2.tar.gz\"}' \\\n  | curl -fsS https://veil.rip/v1/verify --json @-"},{"kind":"code","language":"shell","code":"jq -n --rawfile sig SHA256SUMS.asc --rawfile list SHA256SUMS \\\n  --arg h \"$(sha256sum veil-1.2.tar.gz | cut -d' ' -f1)\" \\\n  '{signature: $sig, list: $list, sha256: $h, name: \"veil-1.2.tar.gz\", card: \"1\"}' \\\n  | curl -fsS https://veil.rip/v1/verify --json @-"}],"verify":"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.","bodyFields":[{"name":"signature","description":"La 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.","in":"body","required":true},{"name":"sha256, sha512, blake2b512","description":"Gli 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.","in":"body","required":false},{"name":"name","description":"Il nome del file, al più 255 byte. In un elenco vale la riga con questo nome, altrimenti quella con questo nome senza cartelle.","in":"body","required":false},{"name":"list","description":"Il 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.","in":"body","required":false},{"name":"format","description":"ssh, pgp, minisign o veil. Senza, il server lo legge dal testo.","in":"body","required":false},{"name":"card","description":"Il 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.","in":"body","required":false},{"name":"at","description":"Secondi Unix facoltativi. Il default è la data di una firma OpenPGP, altrimenti adesso.","in":"body","required":false}],"live":false,"responses":[{"status":200,"contentType":"application/json","description":"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.","fields":[{"name":"valid","type":"boolean","description":"Verdetto complessivo su firma, stato della chiave ed eventuale titolarità dell’account. HTTP 200 comprende anche `valid=false`."},{"name":"signatureOk","type":"boolean","description":"Indica se la firma crittografica è valida."},{"name":"identity","type":"IdentityRef | null","description":"Scheda associata alla chiave o indicata dal blocco, se nota."},{"name":"device","type":"string | null","description":"Dispositivo di firma, se identificato."},{"name":"role","type":"string | null","description":"Ruolo di firma, se identificato."},{"name":"keyState","type":"KeyState | null","description":"Validità della chiave nell’istante richiesto."},{"name":"account","type":"object | null","description":"platform, subject, owned e reason quando sono stati richiesti platform/subject."},{"name":"reason","type":"string | null","description":"Null 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."},{"name":"key","type":"string | null","description":"La 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."},{"name":"format","type":"string","description":"ssh, pgp, minisign o veil."},{"name":"external","type":"object | null","description":"La 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)."},{"name":"signedAt","type":"string | null","description":"La data che dichiara una firma OpenPGP, scritta dall’orologio di chi firma. Null per gli altri formati."},{"name":"atFrom","type":"string","description":"Da dove viene il momento del controllo: request, signature o now."},{"name":"covers","type":"string","description":"file o list."},{"name":"hash","type":"string | null","description":"L’hash del file usato nel controllo: sha256, sha512 o blake2b512."},{"name":"file","type":"object | null","description":"Il nome e gli hash che hai mandato."},{"name":"list","type":"object | null","description":"Le righe dell’elenco firmato: name, alg e hash."},{"name":"match","type":"object | null","description":"La riga del blocco o dell’elenco per il tuo file: name, alg, expected e ok."}],"example":{"language":"json","code":"{\n  \"valid\": false,\n  \"signatureOk\": true,\n  \"identity\": {\n    \"n\": 1,\n    \"url\": \"https://veil.rip/u/1\",\n    \"name\": \"Marta Lanzoni\",\n    \"nameHidden\": false\n  },\n  \"device\": null,\n  \"role\": null,\n  \"keyState\": {\n    \"at\": 1793287911,\n    \"active\": true,\n    \"reason\": \"active\",\n    \"validFrom\": \"2026-10-29T15:54:50Z\",\n    \"validUntil\": null\n  },\n  \"account\": null,\n  \"reason\": \"hash_mismatch\",\n  \"key\": \"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKX/sjzOxM0MkL47LkMqAm0iZXcdiRGBJiqvesABK66k\",\n  \"format\": \"ssh\",\n  \"external\": {\n    \"type\": \"ssh-ed25519\",\n    \"fp\": \"SHA256:yKGK3rJbLA9EAbnKwNXuQvLvsvT0WRrii16h6sF9Rwk\",\n    \"label\": \"Release key\",\n    \"addedIn\": 2,\n    \"removedIn\": null,\n    \"signer\": \"SHA256:yKGK3rJbLA9EAbnKwNXuQvLvsvT0WRrii16h6sF9Rwk\"\n  },\n  \"signedAt\": null,\n  \"atFrom\": \"now\",\n  \"covers\": \"list\",\n  \"hash\": \"sha256\",\n  \"file\": {\n    \"name\": \"veil-1.2.tar.gz\",\n    \"sha256\": \"5d2aebc96df7ba9f758fbaaca850d629e39284b55d676c828e6498962b694d12\",\n    \"sha512\": null\n  },\n  \"list\": {\n    \"lines\": [\n      {\n        \"name\": \"veil-1.2.tar.gz\",\n        \"alg\": \"sha256\",\n        \"hash\": \"04cac27551ecc1b787e5ce856537f28802f70c1222efa5454f0ab626f4c242c2\"\n      }\n    ]\n  },\n  \"match\": {\n    \"name\": \"veil-1.2.tar.gz\",\n    \"alg\": \"sha256\",\n    \"expected\": \"04cac27551ecc1b787e5ce856537f28802f70c1222efa5454f0ab626f4c242c2\",\n    \"ok\": false\n  }\n}"}}],"responseObjects":[{"id":"key-ref","title":"Riferimento alla scheda","fields":[{"name":"n","type":"integer","description":"Numero permanente della scheda."},{"name":"url","type":"string","description":"URL permanente della scheda."},{"name":"name","type":"string","description":"Nome visualizzato corrente."},{"name":"nameHidden","type":"boolean","description":"Indica se lo staff nasconde il nome."}],"typeName":"IdentityRef"},{"id":"key-state","title":"Stato della chiave in un istante","fields":[{"name":"at","type":"integer","description":"Istante controllato, in secondi Unix."},{"name":"active","type":"boolean","description":"Indica se la chiave era attiva in quell’istante."},{"name":"reason","type":"string","description":"active, not_yet_valid o revoked."},{"name":"validFrom","type":"string","description":"Data e ora di pubblicazione della versione che l’ha aggiunta."},{"name":"validUntil","type":"string | null","description":"Data e ora di pubblicazione della revoca, oppure null."}],"typeName":"KeyState"}],"errorFormat":"json","errorDetails":[{"status":400,"code":"hash_needed","description":"La firma copre un hash del file che la richiesta non porta. Il messaggio comincia con il suo nome: sha256, sha512 o blake2b512.","action":"Calcola quell’hash del file (sha256sum, sha512sum o b2sum) e mandalo nel campo con lo stesso nome.","scope":"endpoint"},{"status":400,"code":"invalid_block","description":"Il blocco firma non è leggibile o indica un’altra rubrica.","action":"Incolla il blocco completo con il messaggio e usa la rubrica che indica.","scope":"endpoint"},{"status":400,"code":"invalid_file_signature","description":"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.","action":"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.","scope":"endpoint"},{"status":400,"code":"invalid_json","description":"Il corpo non è un oggetto JSON, contiene chiavi duplicate o dati finali.","action":"Invia un solo oggetto JSON valido con `Content-Type` application/json.","scope":"endpoint"},{"status":400,"code":"invalid_parameter","description":"Un campo del percorso, della query o del corpo manca, è malformato o fuori intervallo.","action":"Correggi il campo indicato in `error.message` prima di inviare di nuovo.","scope":"endpoint"},{"status":401,"code":"invalid_api_key","description":"La credenziale Bearer è malformata, sconosciuta, scaduta o revocata.","action":"Usa una chiave attiva. Per l’accesso pubblico anonimo, rimuovi del tutto `Authorization`. Credenziali non valide non attivano automaticamente l’accesso anonimo.","scope":"optional-api-key"},{"status":403,"code":"api_key_scope","description":"La chiave API non ha il permesso read o verify, oppure l’endpoint non accetta chiavi Bearer.","action":"Usa il permesso corretto. Le modifiche alle schede e la gestione delle chiavi richiedono una firma del dispositivo.","scope":"optional-api-key"},{"status":403,"code":"api_key_suspended","description":"Questa chiave API è sospesa.","action":"Chiedi allo staff di ripristinarla; un’altra chiave non rimuove la sospensione dell’account.","scope":"optional-api-key"},{"status":403,"code":"developer_suspended","description":"L’account API del titolare è sospeso oppure la scheda titolare non è disponibile.","action":"Controlla l’account titolare e le restrizioni dello staff. Creare un’altra chiave non aggira la sospensione.","scope":"optional-api-key"},{"status":413,"code":"payload_too_large","description":"Il corpo della richiesta supera il limite in byte dell’endpoint.","action":"Riduci il corpo codificato. La gestione delle chiavi API ammette al massimo 8 KiB.","scope":"endpoint"},{"status":422,"code":"file_needed","description":"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.","action":"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.","scope":"endpoint"},{"status":429,"code":"rate_limited","description":"È stato superato un limite anonimo, delle richieste firmate o della chiave API.","action":"Attendi almeno i secondi indicati da `Retry-After`. Condividi coda e budget dei tentativi tra i tuoi processi.","scope":"common"},{"status":500,"code":"internal_error","description":"Si è verificato un errore imprevisto del server. I dettagli interni non vengono restituiti.","action":"Riprova le letture con attese crescenti e un limite. Controlla l’esito delle scritture prima di inviare una nuova operazione firmata.","scope":"common"},{"status":503,"code":"busy","description":"L’applicazione ha raggiunto un limite temporaneo di concorrenza o del database.","action":"Attendi i secondi indicati da `Retry-After` e riprova con attese crescenti e un limite.","scope":"common"}],"responseHeaders":[{"name":"Content-Type","value":"application/json","description":"Usa il tipo dichiarato per scegliere come leggere il corpo."},{"name":"Date","value":"HTTP date","description":"Ora del server. Confrontala con il tuo orologio per firmare le richieste."},{"name":"Retry-After","value":"integer seconds, on rate_limited or busy","description":"Attendi almeno questo intervallo prima di riprovare. Altri codici 429/503 non lo includono necessariamente."}],"documentationUrl":"https://veil.rip/docs/verify-file?lang=it","supportsBrowserFetch":true,"browserMode":"fetch"}}