秘密鍵をpem形式にする
ctfをやっている最中に、求めた秘密鍵をWiresharkに食わせて
暗号化された通信を復号する必要があった.
秘密鍵の値や素数の値は分かっているので、フォーマットを合わせればいけるだろと簡単に考えてたら結構時間を費やしてしまった。
wiresharkは、opensslコマンドでデフォルトで生成されるpem形式を扱うことができる。
pem形式のフォーマットに関しては、こちらを参考にした。
RSA 秘密鍵/公開鍵ファイルのフォーマット - bearmini's blog
とても分かりやすくスクリプトを書く際にとても役立った。感謝
以下が、pem形式の秘密鍵ファイルを生成するpythonでのスクリプト。
ファイルに格納される情報は、e、p、qさえあれば全て計算できるが、割愛している
# s: integer, return "00ABFF" def my_hex(s): s = hex(s)[2:] if s[-1] == 'L': s = s[:-1] if len(s) % 2 == 0: return s else: return '0'+s # s: integer, return byte length def getLength(s): he = my_hex(s) le = len(he) / 2 return le # s: integer, return str_hex def setByteStream(s): buf = "02" length = getLength(s) if length >= 0b10000000: lengthlength = getLength(length + 1) buf += my_hex(0b10000000 | lengthlength) buf += my_hex(length +1) buf += '00' + my_hex(s) else: buf += my_hex(length) buf += my_hex(s) return buf def calcLength(buf): length = len(buf) / 2 b = "" if length >= 0b10000000: lengthlength = getLength(length) b += my_hex(0b10000000 | lengthlength) b += my_hex(length) else: b += my_hex(length) return b e = 65537 d = 100 p = 3 q = 5 n = p * q inv_q = 10 f = open("privatekey.pem", "wb") f.write("-----BEGIN RSA PRIVATE KEY-----\n") version = "020100" modules = setByteStream(n) pubExp = setByteStream(e) priExp = setByteStream(d) prime1 = setByteStream(p) prime2 = setByteStream(q) exp1 = setByteStream(d % (p-1)) exp2 = setByteStream(d % (q-1)) coefficient = setByteStream(inv_q) buf = version + modules + pubExp + priExp + prime1 + prime2 + exp1 + exp2 + coefficient sequence = "30" + calcLength(buf) buf = sequence + buf buf = al.decode("hex") buf = al.encode("base64") f.write(buf) f.write("-----END RSA PRIVATE KEY-----\n") f.close()