NID_sha
обозначает SHA-0, прямого предка SHA-1. SHA-0 первоначально назывался «SHA», но вскоре была опубликована модифицированная версия, названная SHA-1; предыдущий «SHA» был тогда объявлен устаревшим и теперь традиционно называется «SHA-0». Фактическая причина изменения не была официально озвучена, но было общепринято, что SHA-0 имел какую-то слабость - которая была обнаружена независимыми исследователями несколько лет спустя и использовалась для создания столкновений. Таким образом, SHA-0 «сломан» (намного больше, чем SHA-1), и вы не должны его использовать.
Для подписи RSA с SHA-256 вы должны использовать NID_sha256
(для SHA-512, NID_sha512
). Если вы используете NID_sha
, тогда вы получите неправильную подпись. Внутри процесс подписания включает в себя преобразование, в котором значение хеша (параметры m
/ m_len
в RSA_sign()
) дополняется заголовком, который идентифицирует хеш-функцию (поэтому RSA_sign()
должен иметь доступ к этой информации через параметр type
). Если вы используете NID_sha
, тогда этот заголовок скажет: «Это хешированное значение SHA-0 длиной 32 байта», что вдвойне неверно: хеш-значение SHA-0 имеет длину 20 байтов, а не 32; и это не хешированное значение SHA-0, а хешированное значение SHA-256.
Таким образом, ваш подписчик выдает подпись, которая отличается от официального стандарта подписи RSA ( PKCS # 1 ). Таким образом, ваша подпись не подлежит проверке с помощью совместимого верификатора. Однако ваш верификатор также отходит от стандарта тем же способом: используя NID_sha
в качестве параметра для RSA_verify()
, вы указываете верификатору ожидать заголовок "SHA-0" (и 32 -байтовое значение хеша). Это объясняет, почему вещи работают с вашим кодом: ваш верификатор делает ту же ошибку, что и подписавший, и эти две ошибки удаляются.
Другими словами, вы подписываетесь не с истинным RSA, а с его вариантом, который, на первый взгляд, не менее безопасен, чем подлинная вещь, но все же отличается и поэтому не совместим. Возможно, это не проблема в вашей конкретной ситуации, но, вообще говоря, для криптографических операций вы должны придерживаться буквы стандарта (потому что слабые места в безопасности - это тонкие вещи). Если вы используете NID_sha256
при подписании хеш-значения SHA-256, то вы получите стандартную подпись PKCS # 1 v1.5 RSA, и это намного лучше.
Подводя итог: забудьте NID_sha
, используйте NID_sha256
, если хэш-значение получено из SHA-256 (NID_sha512
для SHA-512), как для RSA_sign()
, так и RSA_verify()
.