Рассчитать хеш для проверки подписи в webauthn

Я пытаюсь реализовать webauthn, но у меня возникают проблемы с проверкой подписи. Согласно https://w3c.github.io/webauthn/ я должен в основном проверить подпись на следующих данных:

authData || sha256 (clientDataJSON)

AuthData и хэш sha256 должны быть "двоичными". Я понятия не имею, что именно они имеют в виду под этим, но я предполагаю, что они просто хотят прикрепить байты рядом друг с другом, хотя понятия не имею, что именно будет "двоичным" в этом отношении.

Итак, учитывая PublicKeyCredential с именем attestation, я могу сгенерировать данные, для которых генерируется подпись, следующим образом:

var auth_data = new Uint8Array(attestation.response.authenticatorData);
var data_hash = sha256(new Uint8Array(attestation.response.clientDataJSON));
var signed    = new Uint8Array(auth_data.length + data_hash.length);

signed.set(auth_data);
signed.set(data_hash, auth_data.length);

Я, конечно, пытался проверить это "подписанное" значение напрямую, и я также пытался его хешировать. Ни один из них не подтверждает. Что я делаю не так при расчете подписанных данных?

У меня есть эквивалентный код на стороне сервера (в C++), где я строю то же значение, а затем проверяю его с помощью OpenSSL. Этот подписанный расчет только для того, чтобы показать, что я делаю - я, конечно, не буду доверять этому значению на стороне сервера.

2 ответа

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

Подписи аттестации, в общем, не подписало с вновь созданным верительным закрытым ключом , но с аутентикатором аттестационного закрытым ключом . Кроме того, формат подписанных данных и процедура их проверки определяются об форматом заявленияаттестации . Это сделано для того, чтобы уже существующее оборудование могло поддерживать генерацию подписей только определенным образом, поэтому эти различные форматы аттестации позволяют этим аппаратным реализациям работать с WebAuthn без обновления оборудования или прошивки.

Проверка подписи аттестации всегда требует анализа CBOR как в заявлении аттестации, так и в данных аутентификатора . Это связано с тем, что подпись доставляется в объекте аттестации с кодировкой CBOR, а открытый ключ учетных данных доставляется в данных аутентификатора . Хотяcredential.response.getPublicKey()также возвращает тот же открытый ключ учетных данных, это его представление не подписано. Данные аутентификатора покрываются подписью, поэтому открытый ключ учетных данных должен быть проанализирован из данных аутентификатора, чтобы подпись была значимой.

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

Предполагая, что по опубликованной вами ссылке вы пытаетесь создать подпись утверждения. Я нашел это в документах -

Пусть подпись будет подписью утверждения конкатенации AuthenticatorData || хэш с использованием privateKey selectedCredential, как показано на рисунке 4 ниже. Здесь безопасно использовать простую неограниченную конкатенацию, поскольку данные аутентификатора описывают свою длину. Хеш сериализованных клиентских данных (которые потенциально могут иметь переменную длину) всегда является последним элементом.

посмотрите на изображение ниже пункта 11

Я думаю, что правильным способом было бы использовать сериализованную строку JSON AuthData, добавить ее в Client Data Hash и подписать с помощью закрытого ключа. На стороне сервера вы можете попытаться воссоздать ту же структуру и проверить ее с помощью открытого ключа.

Я не знаю о C++, но в python вы можете использовать пакет под названием cryptography и проверять подпись следующим образом:

>>> public_key.verify(
...     signature,
...     message,
...     padding.PSS(
...         mgf=padding.MGF1(hashes.SHA256()),
...         salt_length=padding.PSS.MAX_LENGTH
...     ),
...     hashes.SHA256()
... )
Другие вопросы по тегам