Как проверить подпись MSSQL в NodeJS

Я не знаком с криптографией или протоколом PKCS, но мне нужно успешно выполнить crypto.verify в NodeJS, используя подпись, сгенерированную в MSSQL Signbycert.

используя это в качестве ссылки: https://stackoverflow.com/a/77519242/19991312 со следующим значением:

DECLARE @PlainText as varchar(max) = 'Hello World';
DECLARE @Signature as varbinary(max); 
SET @Signature = SignByCert(Cert_ID('MyTestCertificate'), @PlainText);

SELECT @Signature as SIG, CERTENCODED(Cert_ID('MyTestCertificate')) as PBK;

простой текст Hello World

Подпись 01000502040000002B0DFBF8B0EB048B18BA30A7A9AC3C63C18D8F932DC974178C61F810758A3FB81F14247AA338E6DBABAE265A8D8077C689901E33B016379685F7A0D27429DCB78F438201F5C04827F2F2B816BF5EFD569FA2AD7EEECC69621AF5F7C39893F0001FC22EAA74DB0F5026CDB38F5BFF3A3D208196C75E7A7A9556050459C826194E460D4C5AB1F30ACFF8594E4E99BC8FD5C8675E79EC54AC9EB017FA112C1759BF387C248869C461677E1CF711860618BFCAC1332C879C01D88C0EBFD584BCF4B358D5D47618A7367DE3A1943AB18454D1B8C423437661120EEE2225A35F763002E9AC80B23B5F03F1EA4C16422BEA8C51032AA0C16B73C7AC5583496EDFD6AA21

открытый ключ 3082036B30820253A00302010202146472932AE654353AF660E02361C2062FC040FEE6300D06092A864886F70D01010B05003045310B30090603550406130241553113301106035504080C0A536F6D652D53746174653121301F060355040A0C18496E7465726E6574205769646769747320507479204C7464301E170D3233313132303137303835375A170D3234313131393137303835375A3045310B30090603550406130241553113301106035504080C0A536F6D652D53746174653121301F060355040A0C18496E7465726E6574205769646769747320507479204C746430820122300D06092A864886F70D01010105000382010F003082010A0282010100CF9CCF5AF133484FC7DC8FF41C1B9010FC7821B373D0352A57E76A0FA0456AE1F35FDCED60343551594FC0E636727AF868EC237978BBBAE8C366B955A507CB942A3380755F6565F1811BF4476948008F18F3BEBE852540C660A781B362DAD21E70567CE70363EB4DE0F281DB239381308C2A8664B066F7F3331038E62465FC837AF170346AB63D1D18CA0400A6FC41EEE87FEFFB80C01D2FF7B86A1E48F299FA4BECA495C8B33CCB3A9603731AC9CE6B6F55EA1EB91DD919DCCBB17833CB1FB67C97891AF9FAC34EFDB2E7777DF5DFD7E4172638ED65ECBAE08AB5E17EB7EA81937DAAA79F9B041BE3C05488423BB3EF1B26C91D91CF7FD9D7A42E8E5582DA5F0203010001A3533051301D0603551D0E041604145F7A25691BA68CF1D6B59AD50E8F2CA6D0403018301F0603551D230418301680145F7A25691BA68CF1D6B59AD50E8F2CA6D0403018300F0603551D130101FF040530030101FF300D06092A864886F70D01010B0500038201010064E1E3CB35A81CB136B599134D0F536A4D1776CE26B2822B33C415C8E65EE4A8A5E185668455DDF326A4219CAB87D12ED59E85BDA31521201998165F41979CA0DB6608AF2A5D5A3A7566082B6E7B1204666233312E0FFABFF427DDB8E37415559CD8B5405F13425078ACDC1C02AECD3DE372FDC9DE0DCE9A74F3716AF2D0D2ACD06F6070AB620A5E6A5575CA760AED728AAD8549B047345D4F286EA51CB005719B2396F5C0340FB94162EE9E7EAC247CE402169FC754EACAC818C08DAD0A796D336F4437D665CD7ABAB1ED9E30D6213ED2328859709884C35BE1143861429A84FA2CE530F95434554B33131AA66EC6ABC22091E91072242B466877ED6D82C137


Основываясь на моем приблизительном понимании после прочтения этого: https://stackoverflow.com/a/77519242/19991312, подпись MSSQL отличается от стандартного протокола PKCS и не может быть напрямую использована в crypto.verify.

поэтому я сделал некоторые грубые преобразования значения подписи, но все еще не смог проверить подпись, возможно, из-за моего непонимания или отсутствия знаний в области криптографии. Моя текущая проверка в nodeJS выглядит следующим образом:

const plainText    = 'Hello World';
const textDigest   = crypto.hash('sha256', plainText, 'hex');
const sqlSignature = '...';
const pbk          = '...';
const x509Cert     = new crypto.X509Certificate(Buffer.from(pbk, 'hex'))

const signatureTransform = Buffer.from(sqlSignature.slice(16), 'hex').reverse()

const isSignatureValid = crypto.verify(null, Buffer.from(textDigest, 'hex'), x509Cert.publicKey, signatureTransform)

console.info('isSignatureValid', isSignatureValid ) // false Q^Q
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как уже описано в связанном посте, signatureTransform не совместим со схемой подписи PKCS#1 v1.5 (точнее со схемой подписи RSASSA-PKCS1-v1_5 ), поскольку применяемая кодировка отличается от EMSA-PKCS1. -v1_5 в том смысле, что использовались только хешированные данные, а не кодировка DER значения DigestInfo.
По этой причине crypto.verify() нельзя применять, так как при этом проверяется, строго ли расшифрованные данные соответствуют кодировке EMSA-PKCS1-v1_5 и, в частности, соответствует ли хеш-часть хешированному сообщению.
Вместо этого следует использовать crypto.publicDecrypt(). Эта реализация выполняет чистое дешифрование с помощью открытого ключа и распаковку статической части (0x0001FF...FF00) без дальнейшей проверки результирующих данных и, следовательно, возвращает сюда хеш сообщения.
Таким образом, проверка просто состоит из проверки идентичности хэшей:

...
const decrypted = crypto.publicDecrypt(x509Cert.publicKey, signatureTransform).toString('hex')
const verified = (decrypted === textDigest) 
console.info("Verified:" , verified) // Verified: true

Другие вопросы по теме