Formato cavo Tink

Questa pagina descrive il formato di Tink per le chiavi e l'output primitivo. La documentazione è rivolta ai crittografi che vogliono aggiungere altre lingue a Tink e ai manutentori di altre librerie di crittografia di alto livello che vogliono una modalità compatibile con il cavo. Non è destinata al pubblico generico.

Serializzazione del set di chiavi

Tink utilizza Google protobuf per serializzare i propri keyset.

  • Un keyset serializzato binario è un proto Keyset serializzato definito in tink.proto. La proprietà del valore KeyData di una chiave è un proto serializzato del tipo di chiave corrispondente.
  • Un keyset serializzato JSON è un proto Keyset serializzato in formato JSON. Tieni presente che il valore KeyData è ancora un proto serializzato binario.
  • Un set di chiavi criptato è un proto EncryptedKeyset serializzato definito in tink.proto. Contiene un keyset binario serializzato criptato e, facoltativamente, alcuni metadati KeysetInfo non criptati.

Prefisso output Tink

La maggior parte delle primitive Tink supporta un prefisso di output di 5 byte composto da:

  • Versione a 1 byte: 0x01
  • Suggerimento per la chiave di 4 byte: questo è l'ID della chiave utilizzata.

Alcune chiavi legacy potrebbero supportare anche il byte di versione 0x00.

La primitiva Prehash utilizza il byte di versione 0xff. Vedi Valori di prehash ML-DSA esterni di Mu.

Tieni presente che questi prefissi non sono autenticati e non possono essere utilizzati per motivi di sicurezza. Tink li utilizza come suggerimento per velocizzare la decrittografia o la verifica oppure per scegliere la chiave di firma in uno scenario di prehash della firma.

AEAD

In generale, Tink formatta i testi criptati AEAD come segue:

prefix || IV || ciphertext || tag

se non diversamente specificato nella RFC corrispondente. prefix è vuoto o un prefisso di output Tink di 5 byte.

AES-CTR-HMAC

Per AES-CTR-HMAC, Tink calcola il MAC con i dati associati (AD) nel seguente modo:

AD || IV || ciphertext || bitlen(AD)

dove bitlen(AD) è la lunghezza dell'annuncio in bit rappresentata come numero intero senza segno big-endian a 64 bit. Questo schema HMAC segue la bozza per AES-CBC-HMAC di Mcgrew.

AEAD deterministico

Tink implementa RFC 5297 per AES-SIV, inserendo il vettore di inizializzazione (SIV) sintetico all'inizio del testo cifrato. La primitiva potrebbe aggiungere un prefisso di output Tink di 5 byte.

Mentre RFC 5297 supporta un elenco di dati associati, Tink supporta solo un dato associato, che corrisponde a un elenco con un elemento in RFC 5297. I dati associati vuoti sono un elenco con un elemento vuoto e non un elenco vuoto.

Streaming AEAD

Consulta AES-CTR HMAC e AES-GCM-HKDF.

Crittografia envelope

La crittografia envelope cripta i dati con una chiave di crittografia dei dati DEK utilizzando le primitive AEAD di Tink. La crittografia funziona nel seguente modo:

  • Viene generato un nuovo DEK utilizzando un determinato modello di chiave (o parametri della chiave).
  • DEK viene serializzato in una stringa di byte. Il formato di serializzazione della serializzazione del buffer di protocollo del proto del tipo di chiave. Ad esempio, questo è un messaggio del buffer di protocollo AesGcmKey serializzato definito in aes_gcm.proto per la DEK del tipo di chiave AES GCM. Consulta Serializzazione del buffer di protocollo per informazioni su come serializzare un buffer di protocollo.
  • DEK serializzato viene criptato da un provider esterno (ad esempio GCP) in un encrypted DEK.
  • DEK viene utilizzato per crittografare il testo non crittografato con i dati associati in ciphertext. Pertanto, ciphertext ha esattamente lo stesso formato della primitiva AEAD corrispondente a DEK.

Il formato di output della crittografia envelope è il seguente:

encrypted DEK length || encrypted DEK || ciphertext

encrypted DEK length è di 4 byte e memorizza la lunghezza di encrypted DEK come numero intero big-endian a 32 bit.

MAC

Tink segue le RFC corrispondenti. I primitivi potrebbero aggiungere un prefisso di output Tink di 5 byte al tag.

Set PRF

Tink segue le RFC corrispondenti. Tieni presente che per PRF Set the key type il tipo di chiave è diverso dal tipo di chiave MAC dello stesso algoritmo perché non include la lunghezza dell'output. Le chiavi del set PRF non aggiungono mai un prefisso di output Tink. In questo modo, l'output è effettivamente una PRF.

Crittografia ibrida

Il formato wire generale per la crittografia ibrida Tink è il seguente:

prefix || encapsulated_key || encrypted_data

prefix è vuoto o un prefisso di output Tink di 5 byte. Ogni tipo di chiave contiene le informazioni su quanti byte analizzare e come analizzarli da encapsulated_key.

HPKE (Hybrid Public Key Encryption)

Tink segue lo standard HPKE definito nella RFC 9180. Una suite di cifratura HPKE include le seguenti tre primitive.

  • Meccanismo di incapsulamento chiave (KEM)
  • Funzione di derivazione della chiave (KDF)
  • Crittografia autenticata con dati associati (AEAD)

Lo standard HPKE non definisce un formato di trasmissione generale nella RFC 9180, sezione 10. L'implementazione HPKE di Tink utilizza i seguenti valori encapsulated_key e encrypted_data.

  • encapsulated_key
    • Chiave pubblica serializzata del mittente
    • Definito come enc nella RFC 9180, sezione 4.1
    • Formato determinato dal KEM HPKE specifico utilizzato
  • encrypted_data
    • Testo cifrato e tag (ad es. ciphertext || tag senza IV)
    • Definito come ct nella RFC 9180, sezione 4
    • Formato determinato dall'AEAD HPKE specifico utilizzato
KEM basato su X25519 Diffie-Hellman

Per X25519 DHKEM, il valore enc è la chiave pubblica Diffie-Hellman di 32 byte del mittente.

ECIES-AEAD-HKDF

Per l'implementazione ECIES-AEAD-HKDF di Tink, encapsulated_key è l'output del meccanismo di incapsulamento della chiave (KEM) e encrypted_data è l'output del meccanismo di incapsulamento dei dati (DEM).

KEM

A seconda del tipo di chiave, Tink utilizza punti della curva ellittica compressi e non compressi, seguendo gli standard di codifica RFC 8422/ANSI.X9-62.2005. Per i punti non compressi, al byte 0x04 seguono le coordinate x e y come numeri interi di dimensioni fisse. Per le coordinate compresse, vengono utilizzati il byte 0x02 o 0x03 e la coordinata x come numero intero di dimensioni fisse. Per X25519, viene utilizzata la definizione RFC 7748 (coordinata x come numero intero di dimensioni fisse).

DEM

Per encrypted_data, Tink utilizza lo stesso formato di AEAD. Ciò include la specifica di un IV.

Derivazione delle chiavi

Viene calcolata prima la coordinata x x_ss del punto condiviso. La chiave per AEAD viene quindi impostata su:

HKDF(ikm = encapsulated_key || x_ss, salt = salt_of_key, info = context_info, length = dem_key_size)

dove encapsulated_key è l'output KEM completo in byte.

Firme digitali

Tink segue le RFC corrispondenti. Le primitive potrebbero aggiungere un prefisso di output Tink di 5 byte al tag generato.

ECDSA

A seconda del campo EcdsaSignatureEncoding nella chiave, il formato di una firma ECDSA è IEEE P1363 o ASN.1 DER.

Il formato della firma IEEE P1363 è r || s, dove r e s sono riempiti con zeri e hanno le stesse dimensioni in byte dell'ordine della curva. Ad esempio, per la curva NIST P-256, r e s vengono riempiti con zeri fino a 32 byte.

La firma DER è codificata utilizzando ASN.1:

ECDSA-Sig-Value :: = SEQUENCE { r INTEGER, s INTEGER }

In particolare, la codifica è:

0x30 || totalLength || 0x02 || r's length || r || 0x02 || s's length || s

Tink segue le best practice per la verifica della firma, accettando solo firme ECDSA con codifica DER (le firme con codifica BER alternativa non sono valide).

Ciò contribuisce a prevenire attacchi di malleabilità della firma, che spesso interessano i sistemi di criptovalute.

Valori prehash ML-DSA di Mu esterno

La primitiva Prehash trasforma un messaggio in un valore prehash, che viene poi firmato dalla primitiva SignPrehash. Per ML-DSA in modalità External Mu, come descritto in RFC 9881, il valore prehash è di 69 byte con il seguente layout:

0xff || key_id (4 bytes, big-endian) || mu (64 bytes)
  • mu è il rappresentante del messaggio ML-DSA, calcolato come SHAKE256(tr || 0x00 || 0x00 || message, 64), dove tr è l'hash di 64 byte della chiave pubblica, il primo 0x00 è il separatore di dominio FIPS 204 per ML-DSA puro e il secondo 0x00 è la lunghezza della stringa di contesto (vuota). Poiché tr deriva dalla chiave pubblica, mu è crittograficamente associato a questa chiave, anche se il controllo dell'associazione richiede il messaggio originale.
  • Il prefisso di 5 byte è l'inquadratura di Tink, non fa parte di mu. Associa il valore pre-hash a una chiave specifica, in modo che SignPrehash sappia con quale chiave firmare e possa rifiutare un valore pre-hash per cui non ha una chiave. Il prefisso è un semplice metadato e non vincola nulla a livello crittografico: chiunque può riscriverlo.

La firma rifiuta qualsiasi input che non sia esattamente di 69 byte, che non inizi con 0xff o il cui ID chiave non corrisponda a una chiave abilitata nel relativo keyset.