Сортировка исходной строки не требуется, поскольку вы будете хэшировать полезную нагрузку b64, а не саму исходную строку JSON.

ющий вопрос более сложен, чем может показаться на первый взгляд.

Предположим, у меня есть произвольный объект JSON, который может содержать любой объем данных, включая другие вложенные объекты JSON. То, что я хочу, - это криптографический хэш / дайджест данных JSON, без учета самого фактического форматирования JSON (например, игнорирование переносов строк и различий между токенами JSON).

Последняя часть является требованием, поскольку JSON будет генерироваться / считываться различными (де) сериализаторами на нескольких различных платформах. Я знаю по крайней мере одну библиотеку JSON для Java, которая полностью удаляет форматирование при чтении данных во время десериализации. Как таковой он сломает хеш.

Вышеупомянутое предложение произвольных данных также усложняет ситуацию, так как мешает мне взять известные поля в заданном порядке и объединить их перед хэшированием (подумайте примерно, как работает не криптографический метод hashCode () в Java).

Наконец, нежелательно хэширование всей строки JSON в виде фрагмента байтов (до десериализации), поскольку в JSON есть поля, которые следует игнорировать при вычислении хэша.

Я не уверен, что есть хорошее решение этой проблемы, но я приветствую любые подходы или мысли =)

 Nandeep Mali20 февр. 2013 г., 18:20
Я не могу не заметить, насколько ваше имя подходит к вопросу.
 mtraut12 янв. 2011 г., 16:37
Вы смотрели на XML DSig? Они имеют ту же проблему и имеют довольно сложную спецификацию «канонизации».
 Natim27 авг. 2015 г., 14:41
@ RomanPlášil, есть существующая реализация в Go / Node.js / Python, которую вы можете использовать, и она выполняет канонизацию для вас.
 Roman Plášil06 февр. 2014 г., 02:41
что RFC определяет только формат JSON для хранения полезной нагрузки + подпись + некоторые заголовки, канонизация JSON не упоминается
 user23955829 окт. 2013 г., 21:47
Это стандартизируется. См. Проект RFC JSON Web Signature (JWS).tools.ietf.org/html/draft-ietf-jose-json-web-signature-17

Ответы на вопрос(5)

Решение Вопроса

где допускается гибкость. Чтобы решить это, вам нужноКаноническаяФорма представление.

Например, протокол OAuth1.0a, который используется Twitter и другими службами для проверки подлинности, требует безопасного хэша сообщения запроса. OAuth1.0a говорит, что для вычисления хэша необходимо сначала расположить поля по алфавиту, разделить их новыми строками, удалить имена полей (которые хорошо известны) и использовать пустые строки для пустых значений. Сигнатура или хеш вычисляется на основе результата этой канонизации.

XML DSIG работает аналогично - вам нужно канонизировать XML перед его подписанием. Существуетпредлагаемый стандарт W3, охватывающий этотпотому что это такое фундаментальное требование для подписания. Некоторые люди называют это c14n.

Я не знаю стандарта канонизации для JSON. Это стоит исследовать.

Если его нет, вы, безусловно, можете установить соглашение для вашего конкретного использования приложения. Разумное начало может быть:

лексикографически сортировать свойства по именидвойные кавычки используются на всех именахдвойные кавычки используются для всех строковых значенийбез пробелов или пробелов между именами и двоеточием, а также между двоеточием и значениембез пробелов между значениями и следующей запятойвсе остальные пустые пространства свернулись либо в одно пространство, либо в ничто - выберите одинисключить любые свойства, которые вы не хотите подписывать (например, свойство, которое содержит саму подпись)подпишите результат выбранным вами алгоритмом

Вы также можете подумать о том, как передать эту сигнатуру в объекте JSON - возможно, установить хорошо известное имя свойства, например, «nichols-hmac» или что-то подобное, которое получит версию хэша в кодировке base64. Это свойство должно быть явно исключено алгоритмом хеширования. Затем любой получатель JSON сможет проверить хеш.

Канонизированное представление не обязательно должно быть представлением, которое вы передаете в приложении. Это только должно быть легко произведено, учитывая произвольный объект JSON.

 opyate12 июн. 2014 г., 12:40
 jbaylina16 сент. 2015 г., 21:58
 Dave15 мая 2016 г., 05:35
Канонизация также должна учитывать цифры. ECMAscript определяет JSON.stringify, который говорит о необходимости форматировать число без показателя степени, если оно находится в диапазоне [1e-6, 1e21); в противном случае отформатируйте его с 1 цифрой перед десятичной точкой.
 dolmen19 авг. 2013 г., 16:06
Каноникализация также должна учитывать представление символов:"A" против"\u0041", "é" против"\u00e9" против"\u00E9", Та же проблема для номеров:1 против0.1e1.

отпечаток веб-ключа JSON (JWK) включает тип канонизации. Хотя RFC7638 ожидает ограниченный набор участников, мы могли бы применить тот же расчет для любого участника.

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

чтобы придумывать свою собственную нормализацию / канонизацию JSON, вы можете использоватьbencode, Семантически это то же самое, что и JSON (состав чисел, строк, списков и кодов), но со свойством однозначного кодирования, которое необходимо для криптографического хеширования.

В качестве торрент-файла используется bencode, каждый битторрент-клиент содержит реализацию.

 Jason Nichols12 янв. 2011 г., 17:39
JSON очень предпочтителен, потому что почти на каждом языке есть библиотеки, доступные для сериализации объектов.
 joeforker08 февр. 2013 г., 20:02
Bencode великолепен и супер прост в реализации. Canonical JSON также не будет анализироваться со стандартным анализатором JSON. Ни то, ни другое не нужно анализировать для этого приложения, которое требует только ввода хеш-функции.
 Nikita Nemkin12 янв. 2011 г., 17:51
Я имел в виду использование bencode только в качестве шага нормализации перед хэшированием. Вне вашей процедуры хеширования все остается в формате JSON.
 dolmen19 авг. 2013 г., 17:34
bencoding кодирует только строки байтов, в то время как JSON кодирует строки Unicode. Таким образом, вы должны спроектировать канонизацию JSON-строки поверх bencode. И bencode не кодирует значения с плавающей запятой, которые есть в JSON.
 Steve Midgley05 июл. 2013 г., 02:27
+1 за этот ответ - я работаю над проектом OSS под названием Learning Registry, который является распределенной базой данных JSON. Мы должны подписать каждый документ JSON, прежде чем он попадет в базу данных. Для этого мы (среди прочего) преобразуем JSON в Bencode перед подписанием. B / c Bencode - это надежное семантическое представление, а JSON - нет (по нашему опыту).

что и проблемы с сигнатурами S / MIME и XML. То есть существует несколько эквивалентных представлений данных для подписи.

Например в JSON:

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

против

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

Или, в зависимости от вашего приложения, это может быть даже эквивалентно:

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

Канонизация может решить эту проблему, но эта проблема вам вообще не нужна.

Простое решение, если у вас есть контроль над спецификацией, - это обернуть объект в какой-то контейнер, чтобы защитить его от преобразования в «эквивалентное», но другое представление.

То есть Избегайте проблемы, не подписывая «логический» объект, а подписывая вместо него определенное сериализованное представление.

Например, JSON Objects -> UTF-8 Text -> Bytes. Подпишите байтыв байтах, а затем передать ихв байтах например по кодировке base64. Поскольку вы подписываете байты, различия, такие как пробелы, являются частью того, что подписано.

Вместо того, чтобы пытаться сделать это:

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

Просто сделай это:

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

}

То есть не подписывайте JSON, подписывайтебайты закодированы JSON.

Да, это означает, что подпись больше не прозрачна.

 Jason Nichols31 авг. 2017 г., 16:03
Прошло много лет с тех пор, как я сосредоточился на этой проблеме, но если бы мне пришлось сегодня внедрять хеширование, я бы выбрал такой подход.
 LexieHankins21 июл. 2017 г., 01:38
Pro: Это ослабляет связь для свойств, как указано вашим «Необязательным» объектом. Небольшой минус: стандартные инструменты API не понимают эту упаковку. Опять же, создание хешей для них не тривиально.

JSON-LD можно сделать нормализацию.

Вы должны будете определить свой контекст.

Ваш ответ на вопрос