Это та же проблема, что и вызывает проблемы с сигнатурами 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.
Да, это означает, что подпись больше не прозрачна.