Comment hachage cryptographique un objet JSON?
La question suivante est plus complexe qu'il peut d'abord sembler.
Supposer que j'ai eu à l'arbitraire d'un objet JSON, qui peut contenir n'importe quelle quantité de données, y compris d'autres imbriquée objets JSON. Ce que je veux, c'est un hachage cryptographique/recueil de données JSON, sans égard à la réalité de JSON mise en forme elle-même (par exemple: le fait d'ignorer les retours à la ligne et l'espacement des différences entre le JSON jetons).
La dernière partie est une exigence, comme le JSON sera généré/lu par une variété de (de)sérialiseurs sur un certain nombre de plates-formes différentes. Je connais au moins un JSON bibliothèque Java qui supprime complètement mise en forme lors de la lecture des données lors de la désérialisation. En tant que tel, il va briser le hachage.
L'arbitraire de la clause de données ci-dessus complique aussi les choses, car il m'empêche de prendre des domaines connus dans un ordre donné et la concaténation avant hasing (pense à peu près la Java non cryptographiques hashCode() méthode fonctionne).
Enfin, le hachage de l'ensemble de la Chaîne JSON comme un bloc d'octets (avant la désérialisation) n'est pas souhaitable, car il y a des champs dans le JSON qui doit être ignoré lors du calcul de la valeur de hachage.
Je ne suis pas sûr qu'il y est une bonne solution à ce problème, mais je souhaite la bienvenue à toutes les approches ou des pensées =)
- Avez-vous regarder le XML DSig? Ils ont le même problème et ont une assez complexe "canonique" spéc.
- Je peux pas m'empêcher de remarquer comment apt votre nom est sur la question.
- C'est standardisée. Voir le JSON Web Signature (JWS) projet de RFC. tools.ietf.org/html/draft-ietf-jose-json-web-signature-17
- que RFC spécifie uniquement un format JSON pour stocker la charge utile+signature+certains en-têtes, pas de JSON de mise en forme canonique est mentionné
- il existe déjà mise en œuvre dans Go / Node.js / Python que vous pouvez utiliser et la mise en forme canonique pour vous.
- Vous pouvez également jeter un oeil à ce RFC projet: dpaste-bkero.paas.allizom.org/MtkA/raw
Vous devez vous connecter pour publier un commentaire.
Le problème est courant au moment de calculer les hachages pour tout format de données où la flexibilité est permise. Pour résoudre ce problème, vous devez accepter la représentation.
Par exemple, la OAuth1.0a protocole, qui est utilisé par Twitter et d'autres services pour l'authentification, nécessite un secure hash du message de demande. Pour calculer la valeur de hachage, OAuth1.0a dit que vous devez d'abord enumérer les champs, séparés par des retours à la ligne, supprimer les noms de champ (qui sont bien connus), et l'utilisation de lignes vierges pour des valeurs vides. La signature ou le hash est calculé sur le résultat de cette mise en forme canonique.
XML DSIG fonctionne de la même façon, vous devez accepter le XML avant de le signer. Il y a un proposé W3 standard couvrant cette, parce que c'est une exigence fondamentale pour la signature. Certains l'appellent c14n.
Je ne sais pas d'une mise en forme canonique standard json. Il vaut la peine de la recherche.
Si il n'existe pas, vous pouvez certainement établir une convention pour votre utilisation de l'application. Raisonnable de départ pourrait être:
Vous pouvez aussi envie de penser à comment passer que la signature de l'objet JSON - éventuellement établir un bien connu nom de la propriété, comme "nichols-hmac" ou quelque chose, qui est la version encodée en base 64 de la table de hachage. Cette propriété devrait être expressément exclus par l'algorithme de hachage. Puis, tout récepteur de l'JSON serait en mesure de vérifier le hash.
Le canoniser représentation n'a pas besoin d'être la représentation vous passer autour dans l'application. Il n'a besoin d'être facile à réaliser compte tenu de l'arbitraire d'un objet JSON.
"A"
vs"\u0041"
,"é"
vs"\u00e9"
vs"\u00E9"
. Même question pour les nombres:1
vs0.1e1
.Au lieu d'inventer votre propre JSON normalisation/mise en forme canonique vous souhaiterez peut-être utiliser bencode. Sémantiquement, c'est le même que JSON (composition des nombres, chaînes de caractères, les listes et les dicts), mais avec la propriété de non équivoque de l'encodage qui est nécessaire pour le hachage cryptographiques.
bencode est utilisé comme un torrent format de fichier, chaque client bittorrent contient une mise en œuvre.
bencoding
encode uniquement les chaînes d'octets alors que JSON-encode des chaînes Unicode. Donc, vous avez à la conception d'un JSON-chaîne de mise en forme canonique sur le dessus de bencode. Et bencode ne pas coder les valeurs flottantes que JSON est.C'est le même problème que les causes des problèmes avec les signatures S/MIME et XML signatures. C'est, il y a de multiples représentations équivalentes des données à signer.
Par exemple en JSON:
vs
Ou en fonction de votre application, cela peut même être équivalent:
Canonicalisation pouvait résoudre le problème, mais c'est un problème que vous n'avez pas besoin du tout.
La solution facile si vous avez le contrôle sur la spécification consiste à placer l'objet dans une sorte de récipient pour l'empêcher d'être transformé en un "équivalent", mais différente de la représentation.
I. e. éviter le problème en pas la signature de la "logique" de l'objet, mais la signature d'un particulier de la représentation sérialisée de la place.
Par exemple, les Objets JSON -> UTF-8 de Texte -> Octets. Signe les octets octets, puis de les transmettre octets par exemple, par l'encodage base64. Depuis la signature du octets, les différences comme les espaces sont une partie de ce qui est signé.
Au lieu d'essayer de le faire:
Viens de le faire:
I. e. ne signez pas le JSON, signe les octets de la codées JSON.
Oui, cela signifie que la signature n'est plus transparent.
JSON-LD peut faire normalitzation.
Vous devrez définir votre contexte.
RFC 7638: JSON Web Clé (JWK) de l'Empreinte numérique comprend un type de mise en forme canonique. Bien que RFC7638 s'attend à un ensemble limité de membres, nous serions en mesure de faire le même calcul pour tous les membres.
https://tools.ietf.org/html/rfc7638#section-3
Je ferais tous les champs dans un ordre donné (par ordre alphabétique par exemple). Pourquoi des données arbitraires faire une différence? Vous pouvez simplement effectuer une itération sur les propriétés (ala réflexion).
Sinon, je veux le regarder dans la conversion du raw chaîne json dans certains bien définis forme canonique (supprimer tous superflu de mise en forme) - et de hachage qui.
Nous avons rencontré une question simple, avec hachage JSON codé charges.
Dans notre cas, nous utilisons la méthodologie suivante:
Avantages de cette solution:
Inconvénients
{"a":1,"b":2}
, quand vous dites charge utile de faire tout vous dire les valeurs1
et2
, ou voulez-vous dire de l'ensemble de la chaîne sérialisée'{"a":1,"b":2}'
? Si ce dernier, alors qu'il est absolument t d'importance pour les clés pour être ordonné. Un changement dans la commande modifier l'encodage base64. Et si vous voulez dire que l'ancien, alors ce n'est pas de résoudre l'ensemble du problème.