ed25519のpython実装を紐解く 暗号編 その1(キーペア生成からベリファイまで) - Pebble Coding
リファレンス実装では、sign.inputというファイルの中に:区切りでの
秘密鍵,公開鍵,メッセージ,署名+メッセージのセットがhex表示で1024個入っています。
例として3行目のデータを取り出します。
c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025 :fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025 :af82 :6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40aaf82 :
1列目が秘密鍵32バイト+公開鍵32バイトです。
c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025
2列目が公開鍵32バイトです。
fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025
3列目がメッセージです。
1行目が0バイト,2行目が1バイト,...,1024行目が1023バイトとなっているようです。
ここでは2バイトです。
af82
4列目が署名64バイト+元のメッセージです。 ここでは64バイト+2バイトです。 6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40aaf82
以下のコマンドで1024のセットに対して検証が行われます。
$ sign.py < ./sign.input
MacBookPro 2017で試すと、1つの行の処理に7秒ほどかかります。
検証プログラムの中身を見ていきましょう。
import sys import binascii import ed25519 # examples of inputs: see sign.input # should produce no output: python sign.py < sign.input # warning: currently 37 seconds/line on a fast machine # fields on each input line: sk, pk, m, sm # each field hex # each field colon-terminated # sk includes pk at end # sm includes m at end while 1: line = sys.stdin.readline() if not line: break x = line.split(':') sk = binascii.unhexlify(x[0][0:64]) pk = ed25519.publickey(sk) m = binascii.unhexlify(x[2]) s = ed25519.signature(m,sk,pk) ed25519.checkvalid(s,m,pk) forgedsuccess = 0 try: if len(m) == 0: forgedm = "x" else: forgedmlen = len(m) forgedm = ''.join([chr(ord(m[i])+(i==forgedmlen-1)) for i in range(forgedmlen)]) ed25519.checkvalid(s,forgedm,pk) forgedsuccess = 1 except: pass assert not forgedsuccess assert x[0] == binascii.hexlify(sk + pk) assert x[1] == binascii.hexlify(pk) assert x[3] == binascii.hexlify(s + m)
pk = ed25519.publickey(sk)
で秘密鍵から公開鍵を計算し、メッセージの署名を計算しています。
ed25519.checkvalidで計算した署名が正しいかを確認しています。
そのあと実施しているforgedでは、メッセージバイト列の最後のバイトに1を追加した場合、
署名が一致しなくなることを確認しています。
その後、公開鍵が ファイル内の値と一致すること、
署名+メッセージがファイル内の値と一致することを確認しています。