署名をシリアライズする場合、署名の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