Frage

Die folgende Frage ist komplexer als es zunächst scheinen mag.

Nehmen wir an, ich habe ein beliebiges JSON-Objekt erhielt, eine, die jede Menge Daten, einschließlich andere verschachtelte JSON-Objekte enthalten. Was ich will, ist ein kryptographischer Hash / Digest der JSON-Daten, ohne Rücksicht auf die tatsächliche JSON selbst die Formatierung (zB Zeilenumbrüche und Abstandsunterschiede zwischen der JSON-Token zu ignorieren).

Der letzte Teil ist eine Voraussetzung, da die JSON wird durch eine Vielzahl von (de) Serializer auf einer Reihe von verschiedenen Plattformen generiert / gelesen werden. Ich weiß von mindestens einem JSON-Bibliothek für Java, die vollständig Formatierung entfernt, wenn die Daten während der Deserialisierung zu lesen. Als solches wird es den Hash brechen.

Die willkürliche Daten Klausel oben auch Dinge kompliziert, da es mich daran hindert, unter bekannten Felder in einer bestimmten Reihenfolge und verketten sie vor Häsing (man denke etwa wie Java nicht-Verschlüsselungs hashCode () Methode funktioniert).

Schließlich ist, wie ein Stück von Bytes (vor Deserialisierung) den gesamt JSON String Hashing ist nicht wünschenswert, entweder, da es Felder in der JSON, die ignoriert werden sollen, wenn die Hash-Berechnung.

Ich bin nicht sicher, es ist eine gute Lösung für dieses Problem, aber ich begrüße alle Ansätze und Gedanken =)

War es hilfreich?

Lösung

Das Problem ist ein allgemeiner, wenn Hashes für jedes Datenformat Rechen wo Flexibilität erlaubt. Um dies zu lösen, müssen Sie canonicalize die Darstellung.

Zum Beispiel kann das OAuth1.0a-Protokoll, das durch Twitter und andere Dienste für die Authentifizierung verwendet wird, erfordert eine sichere Hash-Wert des Anforderungsnachricht. Um den Hash zu berechnen, sagt OAuth1.0a Sie zuerst alphabetize müssen die Felder, trennen Sie diese durch Zeilenumbrüche, entfernen Sie die Feldnamen (die allgemein bekannt sind), und verwenden Sie Leerzeilen für leere Werte. Die Unterschrift oder Hash wird auf dem Ergebnis dieser Kanonisierungsprobleme berechnet.

XML DSIG funktioniert auf die gleiche Art und Weise - müssen Sie die XML normalisieren, bevor es unterzeichnet. Es gibt eine vorgeschlagenen W3 Norm für diese , weil es so eine grundlegende Anforderung ist für Unterzeichnung. Manche Leute nennen es C14N.

Ich weiß nicht, von einer Kanonisierung Standard für json. Es lohnt sich zu erforschen.

Wenn es nicht ein, man kann sicherlich eine Konvention für die jeweilige Anwendungsnutzung etablieren. Eine vernünftige Start könnte sein:

  • lexikographisch Art der Eigenschaften von Namen
  • doppelte Anführungszeichen auf allen Namen verwendet
  • doppelte Anführungszeichen auf allen String-Werte verwendet,
  • keinen Raum oder ein Raum, zwischen Namen und dem Doppelpunkt und zwischen dem Doppelpunkt und dem Wert
  • keine Leerzeichen zwischen den Werten und dem folgenden Komma
  • alle anderen weißen Raum kollabiert, um entweder ein einzelnes Leerzeichen oder nichts - wählen Sie ein
  • schließen alle Eigenschaften, die Sie nicht wollen, zu unterschreiben (ein Beispiel ist, die Eigenschaft, dass die Unterschrift selbst hält)
  • Melden Sie das Ergebnis, mit dem gewählten Algorithmus

Sie können auch darüber nachdenken, wie diese Signatur im JSON-Objekt zu übergeben - vielleicht schafft einen bekannten Eigenschaftsnamen, wie „nichols-hmac“ oder etwas, das die Base64-codierte Version des Hash bekommt. Diese Eigenschaft würde müssen explizit durch den Hash-Algorithmus ausgeschlossen werden. Dann jeder Empfänger der JSON der Lage wäre, den Hash zu überprüfen.

Die canonicalized Darstellung nicht brauchte die Darstellung, die Sie in der Anwendung übergeben zu rund. Es braucht nur leicht ein beliebiges JSON-Objekt angegeben hergestellt werden.

Andere Tipps

Statt des eigenen JSON erfinden Normalisierung / Kanonisierung Sie können verwenden möchten bencode . es ist semantisch die gleiche wie JSON (Zusammensetzung von Zahlen, Strings, Listen und dicts), aber mit der Eigenschaft der eindeutigen Kodierung, die für Verschlüsselungs Hashing erforderlich ist.

bencode als Torrent-Datei-Format verwendet wird, enthält jedes BitTorrent-Client eine Implementierung.

Dies ist das gleiche Problem wie Ursachen Probleme mit S / MIME-Signaturen und XML-Signaturen. Das heißt, gibt es mehrere äquivalente Darstellungen der Daten unterzeichnet werden.

Zum Beispiel in JSON:

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

vs.

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

oder je nach Anwendung, dies sogar gleichwertig sein kann:

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

Kanonisierung könnte dieses Problem lösen, aber es ist ein Problem, das Sie überhaupt nicht braucht.

Die einfache Lösung, wenn Sie die Kontrolle über die Spezifikation haben, ist das Objekt in einer Art Behälter wickeln Sie es zu schützen, in eine „gleichwertige“ umgewandelt werden, aber andere Darstellung.

d. vermeidet das Problem, indem nicht die Unterzeichnung das „logische“ Objekts, sondern eine bestimmte serialisierte Darstellung davon anstelle der Anmeldung.

Zum Beispiel JSON-Objekte -> UTF-8 Text -> Bytes. Melden Sie die Bytes als Bytes , dann übertragen sie als Bytes z.B. durch Base64-Kodierung. Da Sie die Bytes unterzeichnen, wie Unterschiede Leerzeichen sind Teil dessen, was signiert ist.

Anstatt zu versuchen, dies zu tun:

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

Nur soviel tun:

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

}

d. nicht das JSON unterzeichnen, zeichen die Bytes der codierten JSON.

Ja, es bedeutet, dass die Unterschrift nicht mehr transparent.

JSON-LD können normalitzation tun.

Sie müssen Ihren Kontext definieren.

RFC 7638: JSON Web Key (JWK) Thumbprint enthält eine Art von Kanonisierung. Obwohl RFC7638 eine begrenzte Anzahl von Mitgliedern erwartet, würden wir die gleiche Berechnung für jedes Mitglied beantragen.

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

ich tun würde, alle Felder in einer bestimmten Reihenfolge (alphabetisch zum Beispiel). Warum machen beliebige Daten einen Unterschied? Sie können nur Iterierte über die Eigenschaften (ala Reflexion).

Alternativ würde ich in schaut den rohen JSON-String in eine gut definierte kanonische Form umgewandelt (entfernen Sie alle superflous Formatierung.) - und das Hashing

Wir stießen auf eine einfache Frage mit Hashing-JSON-kodierte Nutzlasten. In unserem Fall verwenden wir die folgende Methodik:

  1. Konvertieren von Daten in JSON-Objekt;
  2. Encode JSON Nutzlast in base64
  3. Message Digest (HMAC) die erzeugte base64 Nutzlast.
  4. Transmit base64 Nutzlast.

Die Vorteile der Verwendung dieser Lösung:

  1. Base64 wird die gleiche Leistung für eine gegebene Nutzlast erzeugen.
  2. Da die resultierende Signatur wird direkt von der Base64-kodiert Nutzlast und da Base64-Nutzlast zwischen den Endpunkten ausgetauscht werden, abgeleitet wird, werden wir sicher sein, dass die Signatur und die Nutzlast werden beibehalten.
  3. Diese Lösung Probleme lösen, die bei der Codierung von Sonderzeichen Differenz aufgrund entstehen.

Nachteile

  1. Die Codierung / Decodierung der Nutzlast kann Overhead hinzuzufügen
  2. Base64-codierte Daten sind in der Regel 30 +% größer als die ursprüngliche Nutzlast.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top