Domanda

La seguente questione è più complessa di quanto possa sembrare a prima vista.

Si supponga che ho un oggetto JSON arbitraria, uno che può contenere qualsiasi quantità di dati, compresi altri oggetti JSON nidificati. Quello che voglio è un hash crittografico / digerire dei dati JSON, senza tener conto del reale JSON formattazione stesso (ad esempio: ignorando nuove righe e spaziatura differenze tra il JSON gettoni).

L'ultima parte è un requisito, come JSON sarà generato / letto da una varietà di (de) serializzatori su un certo numero di differenti piattaforme. So di almeno una libreria JSON per Java che consente di rimuovere completamente la formattazione nella lettura dei dati durante la deserializzazione. Come tale si romperà l'hash.

La clausola di dati arbitrari sopra complica anche le cose, in quanto mi impedisce di prendere i campi noti in un dato ordine e concatenando prima hasing (si pensi o meno come hashCode non crittografico di Java () metodo funziona).

Infine, hashing l'intero JSON String come un pezzo di byte (prima deserializzazione) non è auspicabile né, dato che ci sono campi nel JSON che devono essere ignorati quando si calcola l'hash.

Non sono sicuro che ci sia una buona soluzione a questo problema, ma accolgo con favore eventuali approcci o pensieri =)

È stato utile?

Soluzione

Il problema è comune nel calcolo hash per qualsiasi formato di dati in cui è consentita la flessibilità. Per risolvere questo problema, è necessario canonicalize la rappresentazione.

Per esempio, il protocollo OAuth1.0a, che viene utilizzato da Twitter e altri servizi per l'autenticazione, richiede un hash sicuro del messaggio di richiesta. Per calcolare l'hash, OAuth1.0a dice che è necessario prima alfabetizzare i campi, separarli con a capo, rimuovere i nomi dei campi (che sono ben noti), e di utilizzare righe vuote per i valori vuoti. La firma o hash è calcolato sul risultato di quella canonica.

XML DSIG funziona allo stesso modo - è necessario canonicalize XML prima di firmarlo. C'è un proposto W3 di serie che coprono questo , perché è un requisito fondamentale per tale firma. Alcuni lo chiamano C14N.

Non so di uno standard per la canonizzazione JSON. Vale la pena indagando.

Se non c'è uno, si può certamente stabilire una convenzione per la vostra particolare l'utilizzo dell'applicazione. Un inizio ragionevole potrebbe essere:

  • lexicographically ordinare le proprietà per nome
  • virgolette usati su tutti i nomi
  • virgolette usati su tutti i valori di stringa
  • nessuno spazio, o uno spazio, tra i nomi e il colon, e tra i due punti e il valore
  • senza spazi tra i valori e il seguente comma
  • tutti gli altri spazi bianchi è crollata ad un singolo spazio o niente - scegliere una
  • escludere qualsiasi proprietà che non si desidera firmare (un esempio è, la proprietà che contiene la firma stessa)
  • firmare il risultato, con la vostra scelta algoritmo

Si può anche voler pensare a come passare che la firma in oggetto JSON - forse stabilire un nome di proprietà ben nota, come "Nichols-hmac" o qualcosa del genere, che ottiene i base64 versione del hash codificati. La struttura dovrebbe essere esplicitamente esclusa dalla algoritmo di hashing. Quindi, qualsiasi ricevitore della JSON sarebbe in grado di controllare l'hash.

La rappresentazione canonicalized non ha bisogno di essere la rappresentazione si passa in giro per l'applicazione. Necessita solo di essere facilmente prodotto in un oggetto JSON arbitrario.

Altri suggerimenti

Invece di inventare il proprio JSON normalizzazione / canonica si consiglia di utilizzare bencode . Semanticamente è lo stesso di JSON (composizione di numeri, stringhe, liste e dicts), ma con la proprietà di codifica univoca che è necessario per hash crittografici.

bencode viene utilizzato come formato di file torrent, ogni client BitTorrent contiene un'implementazione.

Questo è lo stesso problema in quanto causa problemi con firme S / MIME e firme XML. Cioè, ci sono più rappresentazioni equivalenti di dati che devono essere firmati.

Ad esempio in JSON:

{  "Name1": "Value1", "Name2": "Value2" }

vs.

{
    "Name1": "Value\u0031",
    "Name2": "Value\u0032"
}

In alternativa seconda dell'applicazione in uso, questo può anche essere equivalente:

{
    "Name1": "Value\u0031",
    "Name2": "Value\u0032",
    "Optional": null
}

La canonizzazione potrebbe risolvere il problema, ma è un problema che non è necessario a tutti.

La soluzione facile se si ha il controllo sopra la specifica è di avvolgere l'oggetto in una sorta di contenitore per proteggerlo da eventuali trasformato in una rappresentazione "equivalente", ma diverso.

vale a dire. evitare il problema non firmando l'oggetto "logico", ma firmando una particolare rappresentazione serializzata invece.

Per esempio, JSON Oggetti -> UTF-8 Testo -> Bytes. Firmare i byte come byte , quindi li trasmette come byte esempio da base64 codifica. Dal momento che si sta firmando i byte, differenze come spazi bianchi sono parte di ciò che è firmato.

Invece di cercare di fare questo:

{  
   "JSONContent": {  "Name1": "Value1", "Name2": "Value2" },
   "Signature": "asdflkajsdrliuejadceaageaetge="
}

Basta fare questo:

{
   "Base64JSONContent": "eyAgIk5hbWUxIjogIlZhbHVlMSIsICJOYW1lMiI6ICJWYWx1ZTIiIH0s",
   "Signature": "asdflkajsdrliuejadceaageaetge="

}

vale a dire. non firmare il JSON, segno i byte del codificato JSON.

Sì, significa che la firma non è più trasparente.

JSON-LD può fare normalitzation.

Si dovrà definire il contesto.

RFC 7638: JSON Web chiave (JWK) Identificazione include un tipo di canonica. Sebbene RFC7638 prevede un insieme limitato di elementi, ci sarebbe in grado di applicare lo stesso calcolo per ogni utente.

https://tools.ietf.org/html/rfc7638#section-3

I avrebbe fatto tutti i campi di un dato ordine (in ordine alfabetico per esempio). Perché arbitrarie di dati fanno la differenza? Si può solo un'iterazione sulle proprietà (ala di riflessione).

In alternativa, vorrei esaminare la conversione della stringa JSON grezzo in una qualche forma canonica ben definito (rimuovere tutta la formattazione superfluo) -. E hashing che

Si è verificato un problema semplice, con carichi utili hashing JSON-codificati. Nel nostro caso si usa la seguente metodologia:

  1. Dati convertire in oggetto JSON;
  2. Codifica JSON payload in base64
  3. Message Digest (HMAC) il carico utile Base64 generato.
  4. Base64 payload
  5. Transmit.

I vantaggi di utilizzare questa soluzione:

  1. Base64 produrrà la stessa uscita per un dato carico.
  2. Poiché la firma risultante verrà derivato direttamente dal payload codifica base64 e base64 dal carico utile sarà scambiato tra gli endpoint, saremo certi che la firma e payload saranno mantenuti.
  3. Questa soluzione risolve problemi che sorgono a causa della differenza nella codifica di caratteri speciali.

Svantaggi

  1. La codifica / decodifica del carico utile può aggiungere sovraccarico
  2. Dati
  3. codifica Base64 è di solito più grande del 30% rispetto + payload originale.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top