Passa al contenuto principale

4. Oggetti di Firma

  1. Oggetti di Firma

COSE supporta due diverse strutture di firma. COSE_Sign consente di applicare una o più firme allo stesso contenuto. COSE_Sign1 è limitato a un singolo firmatario. Le strutture non possono essere convertite tra loro; poiché il calcolo della firma include un parametro che identifica quale struttura viene utilizzata, la struttura convertita fallirà la convalida della firma.

4.1. Firma con uno o più firmatari

La struttura COSE_Sign consente di applicare una o più firme a un payload di messaggio. I parametri di intestazione relativi al contenuto e i parametri di intestazione relativi alla firma vengono trasportati insieme alla firma stessa. Questi parametri di intestazione possono essere autenticati dalla firma o essere semplicemente presenti. Un esempio di parametro di intestazione sul contenuto è il parametro di intestazione del tipo di contenuto. Un esempio di parametro di intestazione sulla firma sarebbe l'algoritmo e la chiave utilizzati per creare la firma.

La [RFC5652] indica che:

| Quando è presente più di una firma, la convalida riuscita di una firma associata a un determinato firmatario viene solitamente trattata come una firma riuscita da parte di quel firmatario. Tuttavia, ci sono alcuni ambienti applicativi in cui sono necessarie altre regole. Un'applicazione che impiega una regola diversa da una firma valida per ogni firmatario deve specificare tali regole. Inoltre, laddove la semplice corrispondenza dell'identificatore del firmatario non è sufficiente per determinare se le firme sono state generate dallo stesso firmatario, la specifica dell'applicazione deve descrivere come determinare quali firme sono state generate dallo stesso firmatario. Il supporto di diverse comunità di destinatari è il motivo principale per cui i firmatari scelgono di includere più di una firma.

Ad esempio, la struttura COSE_Sign potrebbe includere firme generate con l'Edwards-curve Digital Signature Algorithm (EdDSA) [RFC8032] e l'Elliptic Curve Digital Signature Algorithm (ECDSA) [DSS]. Ciò consente ai destinatari di verificare la firma associata a un algoritmo o all'altro. Informazioni più dettagliate sulle valutazioni di firme multiple possono essere trovate nella [RFC5752].

La struttura della firma può essere codificata come etichettata (tagged) o non etichettata (untagged), a seconda del contesto in cui verrà utilizzata. Una struttura COSE_Sign etichettata è identificata dal tag CBOR 98. Il frammento CDDL che rappresenta questo è:

COSE_Sign_Tagged = #6.98(COSE_Sign)

Un messaggio firmato COSE è definito in due parti. L'oggetto CBOR che trasporta il corpo e le informazioni sul messaggio è chiamato struttura COSE_Sign. L'oggetto CBOR che trasporta la firma e le informazioni sulla firma è chiamato struttura COSE_Signature. Esempi di messaggi firmati COSE possono essere trovati nell'Appendice C.1.

La struttura COSE_Sign è un array CBOR. I campi dell'array, in ordine, sono:

protected (protetto): Questo è come descritto nella Sezione 3.

unprotected (non protetto): Questo è come descritto nella Sezione 3.

payload (payload): Questo campo contiene il contenuto serializzato da firmare. Se il payload non è presente nel messaggio, l'applicazione è tenuta a fornire il payload separatamente. Il payload è avvolto in una bstr per garantire che venga trasportato senza modifiche. Se il payload viene trasportato separatamente ("contenuto distaccato"), allora un oggetto CBOR nil viene posizionato in questa posizione, ed è responsabilità dell'applicazione garantire che venga trasportato senza modifiche.

  Nota: Quando viene utilizzata una firma con un algoritmo di recupero del messaggio (Sezione 8.1), il numero massimo di byte che possono essere recuperati è la lunghezza del payload originale. La dimensione del payload codificato viene ridotta del numero di byte che verranno recuperati. Se tutti i byte del payload originale vengono consumati, allora il payload trasmesso viene codificato come una stringa di byte di lunghezza zero piuttosto che come assente.

signatures (firme): Questo campo è un array di firme. Ogni firma è rappresentata come una struttura COSE_Signature.

Il frammento CDDL che rappresenta il testo sopra per COSE_Sign segue.

COSE_Sign = [ Headers, payload : bstr / nil, signatures : [+ COSE_Signature] ]

La struttura COSE_Signature è un array CBOR. I campi dell'array, in ordine, sono:

protected (protetto): Questo è come descritto nella Sezione 3.

unprotected (non protetto): Questo è come descritto nella Sezione 3.

signature (firma): Questo campo contiene il valore della firma calcolata. Il tipo del campo è una bstr. Gli algoritmi DEVONO specificare il riempimento se il valore della firma non è un multiplo di 8 bit.

Il frammento CDDL che rappresenta il testo sopra per COSE_Signature segue.

COSE_Signature = [ Headers, signature : bstr ]

4.2. Firma con un solo firmatario

La struttura di firma COSE_Sign1 viene utilizzata quando solo una firma verrà posizionata su un messaggio. I parametri di intestazione che trattano il contenuto e la firma sono posizionati nella stessa coppia di bucket, piuttosto che avere la separazione di COSE_Sign.

La struttura può essere codificata come etichettata o non etichettata a seconda del contesto in cui verrà utilizzata. Una struttura COSE_Sign1 etichettata è identificata dal tag CBOR 18. Il frammento CDDL che rappresenta questo è:

COSE_Sign1_Tagged = #6.18(COSE_Sign1)

L'oggetto CBOR che trasporta il corpo, la firma e le informazioni sul corpo e sulla firma è chiamato struttura COSE_Sign1. Esempi di messaggi COSE_Sign1 possono essere trovati nell'Appendice C.2.

La struttura COSE_Sign1 è un array CBOR. I campi dell'array, in ordine, sono:

protected (protetto): Questo è come descritto nella Sezione 3.

unprotected (non protetto): Questo è come descritto nella Sezione 3.

payload (payload): Questo è come descritto nella Sezione 4.1.

signature (firma): Questo campo contiene il valore della firma calcolata. Il tipo del campo è una bstr.

Il frammento CDDL che rappresenta il testo sopra per COSE_Sign1 segue.

COSE_Sign1 = [ Headers, payload : bstr / nil, signature : bstr ]

4.3. Dati forniti esternamente

Una delle funzionalità offerte in COSE è la capacità per le applicazioni di fornire dati aggiuntivi che devono essere autenticati ma non sono trasportati come parte dell'oggetto COSE. La ragione principale per supportare questo può essere vista guardando la struttura del messaggio CoAP [RFC7252], dove esiste la possibilità che le opzioni vengano trasportate prima del payload. Esempi di dati che possono essere posizionati in questa posizione sarebbero il codice CoAP o le opzioni CoAP. Se i dati sono nelle intestazioni del messaggio CoAP, allora sono disponibili per i proxy per aiutare a eseguire operazioni di proxy. Ad esempio, l'opzione Accept può essere utilizzata da un proxy per determinare se un valore appropriato è nella cache del proxy. Il mittente può utilizzare la funzionalità dei dati aggiuntivi per consentire il rilevamento di eventuali modifiche al set di valori Accept apportate da un proxy o da un attaccante. Includendo il campo nei dati forniti esternamente, qualsiasi modifica successiva causerà il fallimento dell'elaborazione del messaggio da parte del server.

Questo documento descrive il processo per utilizzare un array di byte di dati autenticati forniti esternamente; il metodo di costruzione dell'array di byte è una funzione dell'applicazione. Le applicazioni che utilizzano questa funzionalità devono definire come i dati autenticati forniti esternamente devono essere costruiti. Tale costruzione deve tenere conto dei seguenti problemi:

  • Se sono inclusi più elementi, le applicazioni devono garantire che la stessa stringa di byte non possa essere prodotta se ci sono input diversi. Un esempio di come potrebbe sorgere lo scenario problematico sarebbe concatenando le stringhe di testo "AB" e "CDE" o concatenando le stringhe di testo "ABC" e "DE". Questo viene solitamente risolto rendendo i campi di una larghezza fissa e/o codificando la lunghezza del campo come parte dell'output. Utilizzando le opzioni di CoAP [RFC7252] come esempio, questi campi utilizzano una struttura TLV in modo che possano essere concatenati senza problemi.

  • Se sono inclusi più elementi, deve essere definito un ordine per gli elementi. Utilizzando le opzioni di CoAP come esempio, un'applicazione potrebbe dichiarare che i campi devono essere ordinati in base al numero dell'opzione.

  • Le applicazioni devono garantire che la stringa di byte sarà la stessa su entrambi i lati. L'utilizzo delle opzioni di CoAP potrebbe dare un problema se viene mantenuta la stessa numerazione relativa. Un nodo intermedio potrebbe inserire o rimuovere un'opzione, modificando il modo in cui viene eseguita la numerazione relativa. Un'applicazione dovrebbe specificare che il numero relativo deve essere ricodificato per essere relativo solo alle opzioni che sono nei dati esterni.

4.4. Processo di firma e verifica

Per creare una firma, è necessaria una stringa di byte ben definita. La Sig_structure viene utilizzata per creare la forma canonica. Questo processo di firma e verifica prende in input le informazioni del corpo (COSE_Sign o COSE_Sign1), le informazioni del firmatario (COSE_Signature) e i dati dell'applicazione (fonte esterna). Una Sig_structure è un array CBOR. I campi della Sig_structure, in ordine, sono:

  1. Una stringa di testo di contesto che identifica il contesto della firma. La stringa di testo di contesto è:

    "Signature" per le firme che utilizzano la struttura COSE_Signature.

    "Signature1" per le firme che utilizzano la struttura COSE_Sign1.

  2. Gli attributi protetti dalla struttura del corpo, codificati in un tipo bstr. Se non ci sono attributi protetti, viene utilizzata una stringa di byte di lunghezza zero.

  3. Gli attributi protetti dalla struttura del firmatario, codificati in un tipo bstr. Se non ci sono attributi protetti, viene utilizzata una stringa di byte di lunghezza zero. Questo campo è omesso per la struttura di firma COSE_Sign1.

  4. I dati forniti esternamente dall'applicazione, codificati in un tipo bstr. Se questo campo non viene fornito, il valore predefinito è una stringa di byte di lunghezza zero. (Vedere la Sezione 4.3 per la guida all'applicazione sulla costruzione di questo campo.)

  5. Il payload da firmare, codificato in un tipo bstr. Il payload completo viene utilizzato qui, indipendentemente da come viene trasportato.

Il frammento CDDL che descrive il testo sopra è:

Sig_structure = [ context : "Signature" / "Signature1", body_protected : empty_or_serialized_map, ? sign_protected : empty_or_serialized_map, external_aad : bstr, payload : bstr ]

Come calcolare una firma:

  1. Creare una Sig_structure e popolarla con i campi appropriati.

  2. Creare il valore ToBeSigned codificando la Sig_structure in una stringa di byte, utilizzando la codifica descritta nella Sezione 9.

  3. Chiamare l'algoritmo di creazione della firma, passando K (la chiave con cui firmare), alg (l'algoritmo con cui firmare) e ToBeSigned (il valore da firmare).

  4. Posizionare il valore della firma risultante nella posizione corretta. Questo è il campo "signature" della struttura COSE_Signature o COSE_Sign1.

I passaggi per verificare una firma sono:

  1. Creare una Sig_structure e popolarla con i campi appropriati.

  2. Creare il valore ToBeSigned codificando la Sig_structure in una stringa di byte, utilizzando la codifica descritta nella Sezione 9.

  3. Chiamare l'algoritmo di verifica della firma, passando K (la chiave con cui verificare), alg (l'algoritmo utilizzato per firmare), ToBeSigned (il valore da firmare) e sig (la firma da verificare).

Oltre a eseguire la verifica della firma, l'applicazione esegue i controlli appropriati per garantire che la chiave sia correttamente accoppiata con l'identità di firma e che l'identità di firma sia autorizzata prima di eseguire azioni.