Сообщение об ошибке
DataError: Data provided to an operation does not meet requirements
Ориентироваться нужно на имя DOMException DataError; текст сообщения зависит от среды выполнения. Firefox и Safari показывают общую фразу, приведённую выше; Chrome часто оставляет сообщение пустым или называет причину («The imported EC key specifies a different curve than requested»); Node выводит «Invalid keyData» или конкретную причину, например «Named curve mismatch».
WebCrypto crypto.subtle.importKey — browsers & Node
Что это означает
importKey (или unwrapKey) отклонил байты ключа: они не разбираются как заявленный формат либо их содержимое противоречит параметрам алгоритма (не та кривая, несогласованные поля JWK). Так WebCrypto сообщает, что «эти байты — не тот ключ, за который вы их выдаёте»; ошибка возникает ещё до создания какого-либо объекта ключа.
Почему это происходит
Имя формата не соответствует байтам
частоКлассическая путаница — импорт открытого ключа с форматом «pkcs8» (контейнер закрытого ключа) или закрытого ключа с форматом «spki». Названия неочевидны: spki = открытый, pkcs8 = закрытый, raw = точка EC без обёртки, jwk = объект JSON.
Текст PEM не преобразован в двоичный вид
частоimportKey принимает ArrayBuffer с DER, а не текст PEM. Если передать строку PEM в кодировке UTF-8 или применить к ней декодирование base64, не удалив сначала строки BEGIN/END и переводы строк, получатся байты, которые не пройдут разбор структуры.
Кривая ключа не совпадает с алгоритмом
иногдаSPKI ключа P-256, импортированный с namedCurve: "P-384" (Node сообщает «Named curve mismatch»), или JWK, у которого crv не соответствует запрошенному алгоритму. С байтами всё в порядке, ошибочно объявление. Firefox при импорте не проверяет случай с SPKI, поэтому один и тот же код может пройти там и упасть в Chrome, Safari и Node.
Некорректная точка в формате raw
иногдаДля формата «raw» 65 байт должны иметь вид 0x04 ‖ X ‖ Y, причём точка (X, Y) действительно должна лежать на кривой; Chrome, Firefox и Node отклоняют повреждённую точку при импорте, а движок Safari в нашей проверке импортировал её без возражений. Сжатые точки (33 байта с префиксом 0x02/0x03) — ловушка переносимости в обратную сторону: Chrome, Firefox и Node их принимают, а Safari отклоняет с этой ошибкой.
Как исправить
- 1.
Корректно преобразуйте PEM → ArrayBuffer
Удалите строки обрамления, декодируйте тело из base64 и выберите формат по метке PEM: PUBLIC KEY → spki, PRIVATE KEY → pkcs8.
js function pemToArrayBuffer(pem) { const b64 = pem.replace(/-----[^-]+-----/g, "").replace(/\s+/g, ""); return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0)).buffer; } const key = await crypto.subtle.importKey( "spki", pemToArrayBuffer(publicKeyPem), { name: "ECDSA", namedCurve: "P-256" }, false, ["verify"], ); - 2.
Если ключевой материал есть в JSON, используйте JWK
Эндпоинты JWKS уже отдают объекты, готовые для WebCrypto: двоичное преобразование не нужно, а crv передаётся вместе с ключом.
js const key = await crypto.subtle.importKey( "jwk", jwk, { name: "ECDSA", namedCurve: jwk.crv }, false, ["verify"], ); - 3.
Выясните, что на самом деле содержат байты
Вставьте ключ в декодер сертификатов или в средство проверки подписей ниже: оба инструмента локально разбирают SPKI/PKCS#8/JWK и показывают фактическую кривую и тип ключа, и обычно это сразу указывает на несоответствие.