bugfix> ruby > 投稿

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') 、署名はもう一致しません。 したがって、エンコーディングはまったく役割を果たしていないようです。

ファイルの読み取りから来るのか、文字列として書き込まれるのか、まったく同じコンテンツに違いがあるのはなぜですか?

回答 1 件
  • ファイル data.txt  あなたのコードで考慮していない末尾の改行があります。を使用して

    message = "000\n"
    
    

    動作するはずです。

    あなたもできる

    message = File.binread("data.txt")
    
    

    コマンドラインとして正確なデータを取得するようにします。

あなたの答え