1

Pythonを使用してOAuth1RFCセクションhttps://www.rfc-editor.org/rfc/rfc5849#section-3.4.3のRSA-SHA1署名方法に従ってメッセージに署名したい。結果をopensslの結果と比較することにより、自分が正しい方向に進んでいることを確認しようとしています。

今、私は突然余分なオクテットを持っていることに気づきました。暗号化の知識はせいぜい限られているので、助けが必要です。暗号のソースとopensslのマニュアルページを調べ、出力が非常に似ているという事実から、少なくとも正しいアルゴリズムを使用していると思います。

ただし、openssl rsautlを使用する場合、私は近くにいません...

$ openssl genrsa -out private.pem 1024

$ cat message
Lorem ipsum

$ cat sign.py
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA
key = RSA.importKey(open("private.pem").read())
message = open("message").read()[:-1] # skip last newline
h = SHA.new(message)
p = PKCS1_v1_5.new(key)
signature = p.sign(h)
signature_trim = p.sign(h)[:-1] # will give same output as openssl dgst -sign
print signature    # remove print when not using hexdump

Pythonからの出力

$ python sign.py | hexdump
0000000 1346 38af 89a8 d203 ee26 0cfa a4bc 3a6c
0000010 44fd a436 2c50 03ba 7c84 333a 910a 843e
0000020 f71b 5731 1d2a 8895 9f5c 86b1 1838 7de9
0000030 5c13 d7e5 a019 6ad1 e5a5 d4d5 bd6f 0032
0000040 f320 c5ad fc41 da2c a9c3 2d9a cdce f6d6
0000050 4ef4 6dbd 1ba2 edc1 648e 184a 2e6c e746
0000060 fd92 ba61 b4da f607 d7a4 fbef 8230 378d
0000070 a143 b444 c711 7121 6e08 9d88 bb05 0d25
0000080 000a                                   
0000081

openssl dgstを使用した署名からの出力(これが本当にrsa pkcs#1 v1.5であるかどうかはわかりません)

$ echo -n $(cat message) | openssl dgst -sign private.pem | hexdump
0000000 1346 38af 89a8 d203 ee26 0cfa a4bc 3a6c
0000010 44fd a436 2c50 03ba 7c84 333a 910a 843e
0000020 f71b 5731 1d2a 8895 9f5c 86b1 1838 7de9
0000030 5c13 d7e5 a019 6ad1 e5a5 d4d5 bd6f 0032
0000040 f320 c5ad fc41 da2c a9c3 2d9a cdce f6d6
0000050 4ef4 6dbd 1ba2 edc1 648e 184a 2e6c e746
0000060 fd92 ba61 b4da f607 d7a4 fbef 8230 378d
0000070 a143 b444 c711 7121 6e08 9d88 bb05 0d25
0000080

次にsign.pyで、署名の印刷を削除し、公開鍵に対して署名を検証します。署名をトリミングすると検証に失敗するので、それを行うべきではないという考えが浮かびますが、以前は間違っていました。

pubkey = key.publickey()
pp = PKCS1_v1_5.new(pubkey)
print pp.verify(h, signature)         # True
print pp.verify(h, signature_trim)    # False

openssl rsautlからの出力(これがpkcs#1 v1.5かどうかはわかりません)

$ echo -n $(cat message) | openssl dgst -sha1 | openssl rsautl -sign -inkey private.pem  | hexdump
0000000 14a4 f02c 527f 26f9 29f6 281c 3185 4a1a
0000010 def8 052b b620 cca2 38d9 a389 0b44 112a
0000020 283c ebff 4228 6f77 7a65 9d53 4b98 a073
0000030 bbd9 1aca 3447 a917 d7c3 0968 63c4 6806
0000040 6112 6f36 2d38 a770 5afa a8e0 adf3 4bef
0000050 120c cc10 5194 75ad bdda 91e6 fd79 8f4c
0000060 b864 efb8 cc88 a4da e977 b488 6241 15fb
0000070 e105 1d11 8627 75bd 345b 34da 538f a8db
0000080

私は明らかに何か間違ったことをしているのですが、今はどれだけのことか疑問に思います。base64エンコーディングと、「Loremipsum」が有効な署名ベース文字列ではないという面を除いて...

...これを有効なRSA-SHA1署名にするには、何を変更する必要がありますか?

4

2 に答える 2

4

Pythonprintは常に改行文字を追加します。これは、表示される余分なバイトです。

私の知る限り、それを回避するクリーンな方法はなく、機能しprint signature,ません。

別の方法は、より低いレベルを使用することですsys.stdout.write(signature)

于 2012-01-17T22:39:24.187 に答える
0

答えが見つかりました。何もない。

を使用して証明書+キーを作成しました

$ openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj \ 
  '/C=US/ST=CA/L=Mountain View/CN=www.example.com' -keyout myrsakey.pem \
  -out myrsacert.pem
  1. GoogleAuthPlaygroundにドメインを登録しましたhttp://googlecodesamples.com/oauth_playground/
  2. ドメインを確認し、証明書ファイルをアップロードしました
  3. Playgroundを使用してリクエストを作成しました
  4. Playgroundからの出力を私のコードからの出力で確認しました=)

RSA-SHA1署名方式

def sign_rsa(method, url, params, private_rsa):
   """Sign a request using RSASSA-PKCS #1 v1.5.

   Per `section 3.4.3`_ of the spec.

   .. _`section 3.4.3`: http://tools.ietf.org/html/rfc5849#section-3.4.3

   """
   from Crypto.PublicKey import RSA
   from Crypto.Signature import PKCS1_v1_5
   from Crypto.Hash import SHA
   key = RSA.importKey(private_rsa)
   message = prepare_base_string(method, url, params)
   h = SHA.new(message)    
   p = PKCS1_v1_5.new(key)
   return escape(binascii.b2a_base64(p.sign(h))[:-1])

RSA-SHA1検証

def verify_rsa(method, url, params, public_rsa, signature):
   """Verify a RSASSA-PKCS #1 v1.5 base64 encoded signature.

   Per `section 3.4.3`_ of the spec.

   .. _`section 3.4.3`: http://tools.ietf.org/html/rfc5849#section-3.4.3

   """
   from Crypto.PublicKey import RSA
   from Crypto.Signature import PKCS1_v1_5
   from Crypto.Hash import SHA
   key = RSA.importKey(public_rsa)
   message = prepare_base_string(method, url, params)
   h = SHA.new(message)
   p = PKCS1_v1_5.new(key)
   signature = binascii.a2b_base64(urllib.unquote(signature))
   return p.verify(h, signature)

好奇心旺盛な人は、prepare_base_stringと同様にそれらを見つけて、https://github.com/ib-lundgren/oauthlib/blob/master/oauthlib/oauth.pyでエスケープできます。

まだ16進ダンプについてはわかりませんが、理解できれば更新されます。

于 2012-01-17T21:33:57.723 に答える