Сообщение об ошибке
Invalid key object type public, expected private.
Два названия типа в сообщении меняются в зависимости от ключа и операции: sign() с секретным ключом выдаёт «Invalid key object type secret, expected private.», а verify() с секретным ключом — «Invalid key object type secret, expected private or public.» Сам verify() принимает закрытый ключ и выполняет проверку его открытой половиной. Структура сообщения не меняется.
Node.js crypto — TypeError, code ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE
Что это означает
Вы передали KeyObject не того класса для этой операции: crypto.sign() требуется закрытый ключ, а ему передали открытый (или verify() передали секретный ключ и т. п.). Объекты ключей в Node знают свой тип (открытый, закрытый или секретный), и каждый API принимает только определённые типы.
Почему это происходит
Переменные перепутаны в месте вызова
частоpublicKey и privateKey перепутаны при деструктуризации, или в параметр функции с именем key попадает тот ключ, который оказался у вызывающего кода. Подписать открытым ключом невозможно в принципе, и Node сообщает об этом сразу, а не падает загадочным образом позже.
При загрузке получился не тот тип, что ожидался
частоcreatePublicKey(privatePem) намеренно выводит открытый ключ — код, который затем использует результат как закрытый ключ для подписи, падает здесь. Точно так же PEM-файл, в котором на самом деле лежит открытый ключ, загружается с типом «public», что бы ни говорило имя файла.
Секретный (симметричный) ключ в асимметричном API
иногдаРезультат createSecretKey() (ключ HMAC/AES) передан в sign/verify для ECDSA. Симметричный ключевой материал не может участвовать в подписях с открытым ключом.
Как исправить
- 1.
Проверяйте тип ключа на входе
KeyObject.type принимает значения "public" | "private" | "secret". Однострочная проверка превращает запутанную криптографическую ошибку в очевидную ещё на этапе загрузки.
js import { createPrivateKey } from "node:crypto"; const signingKey = createPrivateKey(pem); if (signingKey.type !== "private") { throw new Error(`expected private key, got ${signingKey.type}`); } - 2.
Используйте каждую половину пары для своей операции
Закрытый ключ подписывает, открытый проверяет. Если у вас есть только закрытый ключ, выведите из него открытую половину для проверки, а не используйте объект закрытого ключа везде.
js import { createPublicKey, sign, verify } from "node:crypto"; const signature = sign("sha256", data, privateKey); // private → sign const publicKey = createPublicKey(privateKey); // derive public half const ok = verify("sha256", data, publicKey, signature); // public → verify