pythonで秘密鍵を用いて任意のデータを署名して公開鍵で署名を検証する

技術メモ

前回実施した内容をベースに進めていく。

やっぱり、テストソースが参考になる。

class KeyTest(unittest.TestCase):

    def test_sign_verify(self):
        secret = 1
        private_key = Key(secret_exponent=1)
        h = b"x00" * 32
        sig = private_key.sign(h)
        self.assertTrue(private_key.verify(h, sig))
        public_key = private_key.public_copy()
        self.assertTrue(public_key.verify(h, sig))
        h160_key = Key(hash160=private_key.hash160())
        self.assertTrue(h160_key.verify(h, sig))
 :
 :

のソースの部分。 h の変数を任意の文字列にして実行する。

>>> from pycoin.key import Key
>>> private_key = Key(secret_exponent=1)
>>> key = 'todoroki'
>>> sig = private_key.sign(key)
>>> sig
'0Dx02 R>xc7x1axd75xacxd0(xecx14Rx17j_xaax8cxa6x96).]9gAx99xa7xf1fxe2x82xbfx02 )xa9tx86B{.xb0|x94Nxadxd1Axe9mx8f)-15xa9xdd5x8axcfxa5^Ux0eqx03'
>>> public_key = private_key.public_copy()
>>> public_key.verify(key, sig)
True

これでよさそうだけど、どう署名しているかがさっぱり中身がわかっていないので少し追っていく。

署名のアルゴリズムはwikipediaが詳しくのっている。

signしている箇所は以下。ecdsa.signで求めたr, s を sigencode_der で DERにしている。DERの説明はこのあたりを

https://github.com/richardkiss/pycoin/blob/1105b29dfae217b41944c6bd379c1a6d9eb4fdb7/pycoin/key/Key.py#L232

    def sign(self, h):
        """
        Return a der-encoded signature for a hash h.
        Will throw a RuntimeError if this key is not a private key
        """
        if not self.is_private():
            raise RuntimeError("Key must be private to be able to sign")
        val = from_bytes_32(h)
        r, s = ecdsa.sign(ecdsa.generator_secp256k1, self.secret_exponent(),
                          val)
        return sigencode_der(r, s)

sigencode_derの部分。DER化。

https://github.com/richardkiss/pycoin/blob/1105b29dfae217b41944c6bd379c1a6d9eb4fdb7/pycoin/tx/script/der.py#L113

def sigencode_der(r, s):
return encode_sequence(encode_integer(r), encode_integer(s))

def encode_sequence(*encoded_pieces):
total_len = sum([len(p) for p in encoded_pieces])
return b"x30" + encode_length(total_len) + b"".join(encoded_pieces)

def encode_integer(r):
assert r >= 0 # can't support negative numbers yet
h = "%x" % r
if len(h) % 2:
h = "0" + h
s = binascii.unhexlify(h.encode("utf8"))
if ord(s[:1])

Sponsored Link
コメントはまだありません

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


仮想通貨全般
TendermintをDocker使って起動してみる

以前、勉強会に行ってきた際にTendermintの事を聞いて ブロックチェーンプロトコルが実装できる …

仮想通貨全般
Bitcoinのdifficultyを決めるnBitsを理解する

マイニングする際の理解を深めようと思い、マイニング難易度(difficulty)を決めるnBitsに …

仮想通貨全般
EOS Night Meetupにいってきた

今回は、以前からEOSに興味があったので EOS Night Meetupにいってきました。 暗号通 …