Created
June 3, 2018 11:51
-
-
Save muromec/bec2702c08243b2c9cf9f0038512a923 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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