Question

La question suivante est plus complexe qu'il peut d'abord sembler.

Supposons que j'ai un objet JSON arbitraire, qui peut contenir une quantité de données, y compris d'autres objets JSON imbriqués. Ce que je veux est un hachage cryptographique / condensé des données JSON, sans tenir compte de la mise en forme JSON réel lui-même (par exemple: en ignorant les différences et les nouvelles lignes d'espacement entre les jetons JSON).

La dernière partie est une exigence, comme JSON sera généré / lu par une variété de (de) serializers sur un certain nombre de plates-formes différentes. Je connais au moins une bibliothèque JSON pour Java qui élimine complètement le formatage lors de la lecture des données lors de la désérialisation. En tant que tel, il brisera le hachage.

La clause de données arbitraire ci-dessus complique aussi les choses, car il me empêche de prendre des champs connus dans un ordre donné et les concaténer avant hasing (pensez à peu près comment hashCode non-cryptographique Java () méthode fonctionne).

Enfin, hachant la chaîne entière JSON comme un morceau d'octets (avant désérialisation) n'est pas souhaitable non plus, car il y a des domaines dans le JSON qui doivent être ignorés lors du calcul du hachage.

Je ne suis pas sûr qu'il ya une bonne solution à ce problème, mais je me félicite des approches ou pensées =)

Était-ce utile?

La solution

Le problème est commun lors du calcul hash pour tout format de données où la flexibilité est permise. Pour résoudre ce problème, vous devez canonicalize la représentation.

Par exemple, le protocole OAuth1.0a, qui est utilisé par Twitter et d'autres services pour l'authentification, nécessite un hachage sécurisé du message de demande. Pour calculer le hachage, OAuth1.0a dit que vous devez d'abord Alphabétiser les champs, les séparer par des sauts de ligne, supprimer les noms de champs (qui sont bien connus), et d'utiliser des lignes vides pour les valeurs vides. La signature ou de hachage est calculée sur le résultat de cette mise en forme canonique.

XML DSIG fonctionne de la même façon - vous devez canoniser le XML avant de le signer. Il y a un norme W3 couvrant proposé cette , parce qu'il est une telle exigence fondamentale pour signature. Certaines personnes appellent C14N.

Je ne sais pas d'une norme pour canonicalisation JSON. Il est des recherches vaut la peine.

S'il n'y en a pas, vous pouvez certainement établir une convention pour l'utilisation de votre application particulière. peut-être un début raisonnable:

  • lexicographique trier les propriétés par nom
  • guillemets doubles utilisés sur tous les noms
  • guillemets doubles utilisés sur toutes les valeurs de chaîne
  • aucun espace ou un espace, entre les noms et le côlon, et entre le côlon et la valeur
  • pas d'espace entre les valeurs et la virgule suivant
  • tout autre espace blanc effondré soit un seul espace ou rien - choisissez
  • exclure toutes les propriétés que vous ne voulez pas signer (un exemple est la propriété qui détient la signature elle-même)
  • signe le résultat, avec votre algorithme choisi

Vous pouvez aussi penser à la façon de passer cette signature dans l'objet JSON - peut-être établir un nom de propriété bien connue, comme « nichols-HMAC » ou quelque chose, qui obtient la base64 version codée du hachage. Cette propriété devrait être exclue explicitement par l'algorithme de hachage. Ensuite, tout récepteur de JSON serait en mesure de vérifier le hachage.

La représentation canonisé n'a pas besoin d'être la représentation que vous passez autour de l'application. Il n'a besoin que d'être facilement produit donné un objet JSON arbitraire.

Autres conseils

Au lieu d'inventer votre propre normalisation JSON / canonicalisation vous pouvez utiliser bencode . Sémantiquement c'est la même que JSON (composition des nombres, des chaînes, des listes et dicts), mais avec la propriété d'encodage sans ambiguïté qui est nécessaire pour le hachage cryptographique.

bencode est utilisé comme format de fichier torrent, chaque client bittorrent contient une implémentation.

Ceci est la même question que provoque des problèmes avec les signatures S / MIME et les signatures XML. Autrement dit, il existe de multiples représentations équivalentes des données à signer.

Par exemple, dans JSON:

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

vs.

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

Ou en fonction de votre application, cela peut même être équivalent:

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

Canonicalisation pourrait résoudre ce problème, mais il 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 est d'envelopper l'objet dans une sorte de récipient pour le protéger d'être transformé en une représentation « équivalent », mais différent.

i.e.. éviter le problème en ne signant pas l'objet « logique », mais la signature d'une représentation sérialisée particulière au lieu.

Par exemple, JSON Objets -> UTF-8 Texte -> Octets. Signez les octets en octets , puis de les transmettre en octets par exemple par base64 codant. Puisque vous signez les octets, les différences comme des espaces font partie de ce qui est signé.

Au lieu d'essayer de faire ceci:

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

Il suffit de faire ceci:

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

}

i.e.. ne signez pas le JSON, signe les octets du encodée JSON.

Oui, cela signifie que la signature n'est plus transparent.

JSON-LD peut faire normalitzation.

Vous devez définir votre contexte.

RFC 7638: JSON Web Key (JWK) comprend un Thumbprint type de canonicalisation. Bien que RFC7638 prévoit un nombre limité de membres, nous serons en mesure de demander un membre, le même calcul.

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

Je ne tous les champs dans un ordre donné (par ordre alphabétique, par exemple). Pourquoi les données arbitraires font une différence? Vous pouvez juste itérer sur les propriétés (ala réflexion).

Sinon, je chercherais dans la conversion de la chaîne de JSON brut en une forme canonique bien définie (supprimer le formatage superflu) -. Et que hachant

Nous avons rencontré un problème simple avec hachage des charges utiles codées JSON. Dans notre cas, nous utilisons la méthodologie suivante:

  1. données Convertir en objet JSON;
  2. charge utile Encode JSON en base64
  3. Message Digest (HMAC) la charge utile base64 générée.
  4. Transmettre la charge utile base64.

Les avantages de l'utilisation de cette solution:

  1. base64 produira la même sortie pour une charge utile donnée.
  2. Depuis la signature résultante sera directement dérivée de la charge utile base64 et depuis base64-charge utile seront échangées entre les points d'extrémité, nous serons certains que la signature et la charge utile sera maintenue.
  3. Cette solution résoudre les problèmes qui se posent en raison de la différence dans le codage des caractères spéciaux.

Inconvénients

  1. Le codage / décodage de la charge utile peut ajouter les frais généraux
  2. données base64 est habituellement de 30 +% plus grande que la charge utile d'origine.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top