(twisted) Edwards Curve DSA
PoC
from hashlib import sha256 from random import randrange from Crypto.Util.number import bytes_to_long, long_to_bytes, inverse p = 208053691657152142396309207664840706929 a = 106 d = 1 q = 208053691657152142368110593084285429184 c = 6 gx = 192217116159845343943848738627289660061 gy = 146486504425718591283424926785441299471 def is_on_curve(P): x, y = P return (a*x**2 + y**2) % p == (1 + d*x**2*y**2) % p def add(P, Q): (x1, y1) = P (x2, y2) = Q x3 = (x1*y2 + y1*x2) * inverse(1 + d*x1*x2*y1*y2, p) % p y3 = (y1*y2 - a*x1*x2) * inverse(1 - d*x1*x2*y1*y2, p) % p return (x3, y3) def mul(x, P): Q = (0, 1) x = x % q while x > 0: if x % 2 == 1: Q = add(Q, P) P = add(P, P) x = x >> 1 return Q def to_bytes(P): x, y = P return int(x).to_bytes(128 // 8, "big") + int(y).to_bytes(128 // 8, "big") def h(msg): return int(sha256(msg).hexdigest(), 16) G = (gx, gy) k = randrange(0, q) hk = h(long_to_bytes(k)) s = hk % 2**128 P = mul(s, G) def sign(m, hk, P): s = hk % 2**128 r = h(long_to_bytes(hk >> 128) + m) R = mul(r, G) S = (r + h(to_bytes(R) + to_bytes(P) + m)*s) % q return R, S def verify(m, s, P): R, S = s x = h(to_bytes(R) + to_bytes(P) + m) (ax, ay) = mul(2**c * S, G) (bx, by) = add(mul(2**c, R), mul(2**c*x, P)) return (ax == bx) and (ay == by) m = long_to_bytes(randrange(0, q)) S = sign(m, hk, P) print( verify(m, S, P) )
Protocol
public parameter
curve: ed25519 (適当なedwards curve)
G: base point
q: order of the curve
: bit出力 の暗号学的ハッシュ関数
where
keygen
適当な bitの整数 をシードとする
の下位 ビット(≒下位半分)を と置いて、 が秘密鍵、 が公開鍵
sign
の上位 ビットを と置いて、
- ここで は適当にエンコードされてる
署名は
verify
を計算して
が成り立つかどうかをみる
がなりたつような最大の ( の素因数である2のべき数)
Attack
に対する署名 と、不正な公開鍵 を用いて計算された署名 から 秘密鍵 が計算可能
で、 が未知なので、減算して
とすると
ECDSA の nonce reuse attack と似た手法