Ответ 1
Да, шифрование PKCS # 1 и сигнатуры PKCS # 1 разные. В случае шифрования (тот, который вы пробовали) входное сообщение просто дополняется до того, как оно будет экспоненциальным.
PKCS # 1 signagtures, с другой стороны, сначала вычислит структуру DER ASN.1 формы
DigestInfo ::= SEQUENCE {
digestAlgorithm AlgorithmIdentifier,
digest OCTET STRING
}
Затем это снова заполняется, чтобы сформировать закодированное сообщение EM
EM = 0x00 || 0x01 || PS || 0x00 || T
где PS - строка заполнения длиной 0xff достаточной длины. Если вы воспроизведете эту EM и используете RSA_private_encrypt
, тогда вы получите правильную кодировку подписи PKCS # 1 v1.5, то же самое получилось бы с помощью RSA_sign
или даже лучше, используя общий EVP_PKEY_sign.
Вот небольшая демонстрация в Ruby:
require 'openssl'
require 'pp'
data = "test"
digest = OpenSSL::Digest::SHA256.new
hash = digest.digest("test")
key = OpenSSL::PKey::RSA.generate 512
signed = key.sign(digest, data)
dec_signed = key.public_decrypt(signed)
p hash
pp OpenSSL::ASN1.decode dec_signed
Хэш SHA-256 выводится следующим образом:
"\x9F\x86\xD0\x81\x88L}e\x9A/..."
dec_signed
является результатом того, что RSA_sign
снова расшифровывается с открытым ключом - это возвращает нас точно к входу функции RSA с удалением отступов, и, как выясняется, это как раз структура DigestInfo
упомянутых выше:
#<OpenSSL::ASN1::Sequence:0x007f60dc36b250
@infinite_length=false,
@tag=16,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=
[#<OpenSSL::ASN1::Sequence:0x007f60dc36b318
@infinite_length=false,
@tag=16,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=
[#<OpenSSL::ASN1::ObjectId:0x007f60dc36b390
@infinite_length=false,
@tag=6,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value="SHA256">,
#<OpenSSL::ASN1::Null:0x007f60dc36b340
@infinite_length=false,
@tag=5,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=nil>]>,
#<OpenSSL::ASN1::OctetString:0x007f60dc36b2a0
@infinite_length=false,
@tag=4,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value="\x9F\x86\xD0\x81\x88L}e\x9A/...">]>
Как вы можете видеть, значение поля digest
DigestInfo
такое же, как и хэш SHA-256, который мы вычислили сами.