This article is like a reminder that I wondered how RSA signature verification is done using Ruby's OpenSSL library and wrote the code. It is not a detailed explanation of public key cryptography or RSA cryptography.
The act of signing public key cryptography seems to mean that the message is encrypted with a private key. (There is also a story that it is correct to ** decrypt ** the message with the private key when signing with RSA encryption, as the creator of RSA said so.) Here, the signature is verified by ** decrypting ** (public_decrypt) with the public key, so the signature is defined as ** encrypted ** with the private key.
Now, let's create a signature and verify the signature using Ruby.
require 'openssl'
#Creating a key
rsa = OpenSSL::PKey::RSA.generate 2048
#message
M = "Signature verification procedure confirmation"
#Hash function specification
digest = OpenSSL::Digest::SHA256.new
#Signature creation
sig = rsa.sign(digest, M)
=> "#I\xE1\xE9\xE3\x95\xCE\xE2U\x8EwU\xF49a\f\xE7\x11\xF5\xC5|H\xF0\xB1\x9Ct\xE5\xB3\x93Tj\xD2\xFC,\x0F1+\xB9\x88p\xEEe\x99#\xCC\xB3\x81\x98U\x01Uc\xC3*\x92\v\xD3(\xE9~&@{\xA1S\x83\v\x83\xFF\xDF\xB8\x82r\xC8\x85|\xC1^\x9F>\xDAc\x17\x9A\xEB\xA8\x1E\xA8\xA4v\xC0\xA3\x98f\xFF\x87^\xFB9#\x98l\xE1\xA9\xB5g-\a\xC3\xAD\x17&\x8C\x84\xAD\x06\xB7\x04c\xA9\xB4{w\x15\xDB\f\xCFQ\x91\xF8t\x16\x8A\x8A\xBC\xB2\xC5H\xD1\xC8p}\xC7\xD6\a\x0F'm\xDB\tT\xDF4\xAAv\xF1\xD4\x14\x86\xD0\x82?\xA6\xB8\xC8\x91\xA8Su\x81Yc9\x83\x94$\x96I\xC9%\xE3\x82\xD6\xB6j\xD1\xB9\xDB\xE0\xD80=v\xBD\n\xDC\xFB:\xC9\x01\xA6\xF3\xC2\xBAT\xAE\x98\xE7B\x10\xE7$\x12_\xEC\x1Ar\x86B\xDEC<:nfV\x12z\xC8%Ng\xF0\xCF\xAA\xD2\x94\xC1\xC0\x1C\x9D,>\xF7+\x83s\xCBX)!\x90)W\xF0\xEA"
#Signature verification
rsa.verify(digest, sig, M)
The signature has been created and verified above.
・ ・ ・ ・ ・ ・
What on earth is verification? I thought.
I referred to this article and the image of the blog in the article.
Signature verification --Hash value H1 for message with hash function --Decrypt the signature with the public key and obtain the data of EMSA-PKCS1-v1_5 --EMSA-PKCS1-v1_5 Remove padding of data to obtain H2 --Compare H1 and H2
If you follow the procedure, it seems that signature verification can be done with Ruby's OpenSSL. (Actually, I think we have to do more processing like the reference article.)
Let's actually experiment with the code.
#Decrypt signature
decrypted = rsa.public_decrypt(sig)
=> "010\r\x06\t`\x86H\x01e\x03\x04\x02\x01\x05\x00\x04 Un\x1A\x02^\xDE\x11Q\x9C~\xD3c\xE7H}6\x88\xAF\x1E\xC5\xAC7#\xB6\xC4@\"_]\xB9W\x10"
#Since it is a 2048bit key, 32 bytes are taken out.
m_hash = decrypted[-32, 32]
=> "Un\x1A\x02^\xDE\x11Q\x9C~\xD3c\xE7H}6\x88\xAF\x1E\xC5\xAC7#\xB6\xC4@\"_]\xB9W\x10"
#Message hash value
digest.digest(M)
=> "Un\x1A\x02^\xDE\x11Q\x9C~\xD3c\xE7H}6\x88\xAF\x1E\xC5\xAC7#\xB6\xC4@\"_]\xB9W\x10"
m_hash == digest.digest(M)
=> true
The decrypted signature and the hashed message matched. Verification was successful.
Let's also check the verification failure pattern.
m_hash == digest.digest("Verification will fail")
=> false
It failed as expected.
It seems that this kind of processing is done in the signature verification verify
.
I hope it will be helpful for those who have the same questions as me.
Those who are strong in this area are welcome to point out and request corrections.
Recommended Posts