Skip to content

Instantly share code, notes, and snippets.

@muromec
Created June 3, 2018 11:51
Show Gist options
  • Save muromec/bec2702c08243b2c9cf9f0038512a923 to your computer and use it in GitHub Desktop.
Save muromec/bec2702c08243b2c9cf9f0038512a923 to your computer and use it in GitHub Desktop.
import wcurve
import hashlib
def inverse_mod(a, m):
"""Inverse of a mod m."""
if a < 0 or m <= a:
a = a % m
# From Ferguson and Schneier, roughly:
c, d = a, m
uc, vc, ud, vd = 1, 0, 0, 1
while c != 0:
q, c, d = divmod(d, c) + (c,)
uc, vc, ud, vd = ud - q * uc, vd - q * vc, uc, vc
# At this point, d is the GCD, and ud*a+vd*m = d.
# If d == 1, this means that ud is a inverse.
assert d == 1
if ud > 0:
return ud
else:
return ud + m
def be_num(num_bytes):
ret = 0
for x in num_bytes:
ret = x | ret << 8
return ret
def unpack(point_bytes):
assert point_bytes[0] == 0x4
assert len(point_bytes) % 2 == 1
middle = (len(point_bytes) // 2) + 1
return be_num(point_bytes[1:middle]), be_num(point_bytes[middle:])
def verify(curve, pub, tbs_hash, signature):
r, s = signature
c = inverse_mod(s, curve.n)
u1 = (tbs_hash * c) % curve.n
u2 = (r * c) % curve.n
xy = (curve.base_point * u1) + (pub * u2)
v = xy.get_affine_x() % curve.n
assert v == r, "Signature doesnt match"
return True
def offset_parse1():
with open('CZO-ROOT-256ECC.cer', 'rb') as cert_file:
cert_data = cert_file.read(1064)
tbs = cert_data[4:4+971+4]
sha = hashlib.sha256()
sha.update(tbs)
hash_bytes = sha.digest()
sign_r_bytes = cert_data[996+2:996+2+32]
sign_s_bytes = cert_data[1030+2:1030+2+32]
pub_bytes = cert_data[496+3:496+3+65]
return unpack(pub_bytes), be_num(hash_bytes), (be_num(sign_r_bytes), be_num(sign_s_bytes))
def offset_parse2():
with open('CA-Justice-ECDSA-261217.cer', 'rb') as cert_file:
cert_data = cert_file.read(1149)
tbs = cert_data[4:4+1055+4]
sha = hashlib.sha256()
sha.update(tbs)
hash_bytes = sha.digest()
sign_r_bytes = cert_data[1080+2:1080+2+33]
sign_s_bytes = cert_data[1115+2:1115+2+32]
pub_bytes = cert_data[489+3:489+3+65]
return unpack(pub_bytes), be_num(hash_bytes), (be_num(sign_r_bytes), be_num(sign_s_bytes))
def main():
curve = wcurve.secp256r1_curve()
(x,y), tbs_hash, signature = offset_parse1()
pub = wcurve.JacobianPoint.from_affine(x, y, curve)
print(verify(curve, pub, tbs_hash, signature))
_pub, tbs_hash, signature = offset_parse2()
print(verify(curve, pub, tbs_hash, signature))
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment