DER署名

署名をシリアライズする場合、署名のr, sをエンコードする必要がある。しかし、pointのように圧縮はできない
署名をシリアライズする標準をDERフォーマット(Distinguished Encoding Rules)と呼ぶ。

### DER署名
1. 0x30バイトで開始
2. 署名の残りの長さをエンコード(0x44または0x45)して追加
3. マーカーバイト0x02を追加
4. rをビッグエンディアン整数としてエンコード ただしrの先頭バイトが0x80以上の時は0x00を付与、長さをrの先頭に追加
5. マーカーバイト0x02を追加
6. sをビッグエンディアン整数としてエンコード ただしsの先頭バイトが0x80以上の時は0x00を付与、長さをsの先頭に追加

先頭ビットが1の場合は負の数。DERは負のエンコードを許容する。

    def der(self):
        rbin = self.r.to_bytes(32, byteorder='big')
        rbin = rbin.lstrip(b'\x00')
        if rbin[0] & 0x80:
            rbin = b'\x00' + rbin 
        result = bytes([2, len(rbin)]) + rbin
        sbin = self.s.to_bytes(32, byteorder='big')
        sbin = sbin.lstrip(b'\x00')
        if sbin[0] & 0x80:
            sbin = b'\x00' + sbin
        result += bytes([2, len(sbin)]) + sbin
        return bytes([0x30, len(result)]) + result

r, sが定まれば、DERフォーマットが求められる。

from ecc import Signature

r = 0x37206a0610995c58074999cb9767b87af4c4978db68c06e8e6e81d282047a7c6
s = 0x8ca63759c1157ebeaec0d03cecca119fc9a75bf8e6d0fa65c841c8e2738cdaec

sig = Signature(r, s)
print(sig.der().hex())

$ python3 main.py
3045022037206a0610995c58074999cb9767b87af4c4978db68c06e8e6e81d282047a7c60221008ca63759c1157ebeaec0d03cecca119fc9a75bf8e6d0fa65c841c8e2738cdaec