RSA SHA1署名検証を実装しようとしています。 驚いたことに、コマンドラインのOpenSSLツールはRuby OpenSSLと同じキーを生成しません。
これらのコマンドを実行すると:
MacBook-Pro-de-Geoffrey:ssl_tests Escaflowne$ cat data.txt
000
MacBook-Pro-de-Geoffrey:ssl_tests Escaflowne$ openssl dgst -sha1 -binary -sign prvkey.pem -out sig.bin data.txt
MacBook-Pro-de-Geoffrey:ssl_tests Escaflowne$ openssl base64 -in sig.bin -out sig64.txt
MacBook-Pro-de-Geoffrey:ssl_tests Escaflowne$ cat sig64.txt
AJEh2kA7O3j624Kdl7UCGN1HiEk/v2LQudB+cjxw1CfmRTjcSPBjUE/EAwy8NEut
K4zYgfRwwTs7NY3AwYiUEtAe5yohUM0Qv17qSDW+G4IWjwe9PKE7Sl00umiMdszA
q/1hqeQlHKgjme7YO7H6i1UcAXmriOOjn+ySRaovsHw=
コマンドラインでの最終的なbase64の結果は次のとおりです。
AJEh2kA7O3j624Kdl7UCGN1HiEk/v2LQudB+cjxw1CfmRTjcSPBjUE/EAwy8NEut
K4zYgfRwwTs7NY3AwYiUEtAe5yohUM0Qv17qSDW+G4IWjwe9PKE7Sl00umiMdszA
q/1hqeQlHKgjme7YO7H6i1UcAXmriOOjn+ySRaovsHw=
さて、Rubyスクリプトで署名しようとすると:
def sign_message(message)
privkey = OpenSSL::PKey::RSA.new(File.read(Rails.root.join('lib', 'payment', 'prvkey.pem')))
digest = OpenSSL::Digest.new('sha1')
expected_sign = privkey.sign(digest, message)
base_64_expected_sign = [expected_sign].pack('m')
puts "Expected Signature"
puts expected_sign
puts "Base 64 Expected Signature"
puts base_64_expected_sign
return base_64_expected_sign
end
そして、このような関数を呼び出す:
def test_sign
message = "000"
message_signature = sign_message(message)
puts "Message Signature : #{message_signature}"
puts "Valid : #{verify_signature(message_signature, message)}"
end
私は出力を取得します:
Expected Signature
??|??n?^~?T_1Y@??BR??u???k x?*????S?L?:.7
t??tc?)崪? ?}DMp?p2??4?D-f??jT;!e
?k??5??
Base 64 Expected Signature
QjhL1zQoUdGFLVCMg06/CKeE/HdhRTOhJ/p09wkWeK0qD/afsxfcU7tMtDou
Nw3rwXw/5W68XhZ+BK1UXwIxWUDbFYlCUpu6HnWTmI5rC3QP+f50Y8kp5bSq
gQkekH1ETXDmcDKvExeSNKVELWYe3uwTalQ7IWUMyWvnF541rvo=
Message Signature : QjhL1zQoUdGFLVCMg06/CKeE/HdhRTOhJ/p09wkWeK0qD/afsxfcU7tMtDou
Nw3rwXw/5W68XhZ+BK1UXwIxWUDbFYlCUpu6HnWTmI5rC3QP+f50Y8kp5bSq
gQkekH1ETXDmcDKvExeSNKVELWYe3uwTalQ7IWUMyWvnF541rvo=
最終的なルビーOpenSSL署名は次のとおりです。
QjhL1zQoUdGFLVCMg06/CKeE/HdhRTOhJ/p09wkWeK0qD/afsxfcU7tMtDou
Nw3rwXw/5W68XhZ+BK1UXwIxWUDbFYlCUpu6HnWTmI5rC3QP+f50Y8kp5bSq
gQkekH1ETXDmcDKvExeSNKVELWYe3uwTalQ7IWUMyWvnF541rvo=
コマンドラインとの比較:
AJEh2kA7O3j624Kdl7UCGN1HiEk/v2LQudB+cjxw1CfmRTjcSPBjUE/EAwy8NEut
K4zYgfRwwTs7NY3AwYiUEtAe5yohUM0Qv17qSDW+G4IWjwe9PKE7Sl00umiMdszA
q/1hqeQlHKgjme7YO7H6i1UcAXmriOOjn+ySRaovsHw=
私はこれにしばらく苦労してきましたが、何が違いをもたらすのか理解できません!
更新:
さて、メッセージ変数を
File.read(Rails.root.join('lib', 'payment', 'data.txt'))
に置き換えると、結果は明らかに一致しますしたがって、基本的に、テキストファイルにあるものと同じ値の文字列を使用しても、同じ結果は得られません。
これは、エンコーディング関連の権利であることを意味しますか?
更新2:
そのため、ファイルは
us-ascii
でエンコードされていると言います
file -I data.txt
を実行した場合ただし、
message.encoding.name
を実行すると
UTF-8
としてロードされていると言うまた、
message.encode('ascii')
生成された署名の結果は変更されませんが、コマンドラインのopensslに対応しています。
文字列
"000".encode('utf-8')
に切り替えるとすぐにまたは
"000".encode('ascii')
、署名はもう一致しません。
したがって、エンコーディングはまったく役割を果たしていないようです。
ファイルの読み取りから来るのか、文字列として書き込まれるのか、まったく同じコンテンツに違いがあるのはなぜですか?
ファイル
data.txt
あなたのコードで考慮していない末尾の改行があります。を使用して動作するはずです。
あなたもできる
コマンドラインとして正確なデータを取得するようにします。