recover_pk: flake8

This commit is contained in:
Philippe Teuwen 2021-02-20 00:30:27 +01:00
commit c299b102ee

View file

@ -4,6 +4,7 @@
import binascii
import sys
import hashlib
debug = False
@ -15,9 +16,11 @@ debug = False
# code snippets we needed:
#######################################################################
# code snippets from JacobianCurve:
# This code is public domain. Everyone has the right to do whatever they want with it for any purpose.
# This code is public domain. Everyone has the right to do whatever
# they want with it for any purpose.
# Copyright (c) 2013 Vitalik Buterin
class JacobianCurve:
def __init__(self, p, n, a, b, g):
self.p = p
@ -27,11 +30,9 @@ class JacobianCurve:
self.g = g
self.n_length = len(bin(self.n).replace("0b", ""))
def to_jacobian(self, p):
return p[0], p[1], 1
def jacobian_double(self, p):
if not p[1]:
return 0, 0, 0
@ -43,7 +44,6 @@ class JacobianCurve:
nz = (2 * p[1] * p[2]) % self.p
return nx, ny, nz
def jacobian_add(self, p, q):
if not p[1]:
return q
@ -67,12 +67,10 @@ class JacobianCurve:
nz = (h * p[2] * q[2]) % self.p
return (nx, ny, nz)
def from_jacobian(self, p):
z = inverse(p[2], self.p)
return (p[0] * z ** 2) % self.p, (p[1] * z ** 3) % self.p
def jacobian_shamir(self, a, n, b, m):
ab = self.jacobian_add(a, b)
if n < 0 or n >= self.n:
@ -97,17 +95,15 @@ class JacobianCurve:
return res
def fast_shamir(self, a, n, b, m):
return self.from_jacobian(self.jacobian_shamir(self.to_jacobian(a), n, self.to_jacobian(b), m))
return self.from_jacobian(
self.jacobian_shamir(
self.to_jacobian(a), n, self.to_jacobian(b), m))
#######################################################################
# code snippets from sslcrypto
# MIT License
# Copyright (c) 2019 Ivan Machugovskiy
import hmac
import os
import hashlib
import struct
def int_to_bytes(raw, length):
data = []
@ -123,6 +119,7 @@ def bytes_to_int(data):
raw = raw * 256 + byte
return raw
def legendre(a, p):
res = pow(a, (p - 1) // 2, p)
if res == p - 1:
@ -130,6 +127,7 @@ def legendre(a, p):
else:
return res
def inverse(a, n):
if a == 0:
return 0
@ -141,6 +139,7 @@ def inverse(a, n):
lm, low, hm, high = nm, new, lm, low
return lm % n
def square_root_mod_prime(n, p):
if n == 0:
return 0
@ -186,8 +185,9 @@ def square_root_mod_prime(n, p):
r = r * b % p
return r
# name: (nid, p, n, a, b, (Gx, Gy)),
CURVES = {
# name: (nid, p, n, a, b, (Gx, Gy)),
"secp128r1": (
706,
0xFFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF,
@ -199,7 +199,6 @@ CURVES = {
0xCF5AC8395BAFEB13C02DA292DDED7A83
)
),
# ! h=4, how to handle that?
"secp128r2": (
707,
0xFFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF,
@ -305,13 +304,14 @@ CURVES = {
)
}
def get_curve(name):
if name not in CURVES:
raise ValueError("Unknown curve {}".format(name))
nid, p, n, a, b, g = CURVES[name]
params = {"p": p, "n": n, "a": a, "b": b, "g": g}
return EllipticCurve(nid, p, n, a, b, g)
class EllipticCurve:
def __init__(self, nid, p, n, a, b, g):
self.p, self.n, self.a, self.b, self.g = p, n, a, b, g
@ -319,15 +319,12 @@ class EllipticCurve:
self.public_key_length = (len(bin(p).replace("0b", "")) + 7) // 8
self.order_bitlength = len(bin(n).replace("0b", ""))
def _int_to_bytes(self, raw, len=None):
return int_to_bytes(raw, len or self.public_key_length)
def _subject_to_int(self, subject):
return bytes_to_int(subject[:(self.order_bitlength + 7) // 8])
def recover(self, signature, data, hash="sha256"):
# Sanity check: is this signature recoverable?
if len(signature) != 1 + 2 * self.public_key_length:
@ -395,24 +392,26 @@ class EllipticCurve:
#######################################################################
def guess_curvename(signature):
l = (len(signature) // 2) & 0xfe
if l == 32 :
siglen = (len(signature) // 2) & 0xfe
if siglen == 32:
curves = ["secp128r1", "secp128r2"]
elif l == 48:
elif siglen == 48:
curves = ["secp192k1", "secp192r1"]
elif l == 56:
elif siglen == 56:
curves = ["secp224k1", "secp224r1"]
elif l == 64:
elif siglen == 64:
curves = ["secp256k1", "secp256r1"]
elif l == 96:
elif siglen == 96:
curves = ["secp384r1"]
elif l == 132:
elif siglen == 132:
curves = ["secp521r1"]
else:
raise ValueError("Unsupported signature size %i" % len(signature))
return curves
def recover(data, signature, curvename, alghash=None):
recovered = set()
curve = get_curve(curvename)
@ -423,7 +422,7 @@ def recover(data, signature, curvename, alghash=None):
recovered.add(pk)
if debug:
print("Possible Pk: ", binascii.hexlify(pk))
except:
except ValueError:
pass
else:
for i in range(2):
@ -434,20 +433,23 @@ def recover(data, signature, curvename, alghash=None):
recovered.add(pk)
if debug:
print("Possible Pk: ", binascii.hexlify(pk))
except:
except ValueError:
pass
return recovered
def recover_multiple(uids, sigs, curvename, alghash=None):
recovered = set()
assert len(uids) == len(sigs)
for i in range(len(uids)):
data = binascii.unhexlify(uids[i])
if debug:
print("UID (%2i): " % len(data), binascii.hexlify(data))
print("UID (%2i): " %
len(data), binascii.hexlify(data))
signature = binascii.unhexlify(sigs[i])
if debug:
print("Signature (%2i): " % len(signature), binascii.hexlify(signature))
print("Signature (%2i): " %
len(signature), binascii.hexlify(signature))
recovered_tmp = recover(data, signature, curvename, alghash)
if i == 0:
if recovered_tmp == set():
@ -458,6 +460,7 @@ def recover_multiple(uids, sigs, curvename, alghash=None):
recovered &= recovered_tmp
return recovered
def selftests():
tests = [
{'name': "Mifare Ultralight EV1",
@ -486,8 +489,8 @@ def selftests():
'samples': ["04448BD2DB6B80", "5CBB5632795C8F15263FEFB095B51C7B541AFD914A1AE44EF6FB8AF605EDF13DBFEE6C3A2DB372245E671DFE0D42CB1F0D0B8FE67A89D2F6",
"04445DD2DB6B80", "166BFD9F9BFAA451172566101580DF9894F582C4A4E258C15037AD2F35A475CF1D7FB817618623A6569F991931AFB2766984E21A18512A6D"],
'pk': "041DB46C145D0A36539C6544BD6D9B0AA62FF91EC48CBC6ABAE36E0089A46F0D08C8A715EA40A63313B92E90DDC1730230E0458A33276FB743"},
# TODO one more Mifare Plus EV1...
{'name': "Mifare Plus EV1",
# TODO one more Mifare Plus EV1...
'samples': ["042A2B221C5080", "BAC40CD88E9193C58ADA5055350C4F648EB5A7AEC4FCF9BD4CDD7B1C558DE5F59C6636F26286ED48622AAA2331D4DF1CEE23B57B94BDA631"],
'pk': "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"},
{'name': "NTAG413DNA",
@ -499,17 +502,19 @@ def selftests():
"04C46C222A6380", "344A806EBF704C05C19215D2F840529CE365AAD2D08A469A95896D75D477D9FAB02A0C827E9F215BD8EB0E56A3A9A008FB75D706AABBD4DA"],
'pk': "048A9B380AF2EE1B98DC417FECC263F8449C7625CECE82D9B916C992DA209D68422B81EC20B65A66B5102A61596AF3379200599316A00A1410"},
{'name': "Vivokey Spark1",
# ! tag signature bytes output by pm3 must be read right to left: echo $sig |sed 's/\(..\)/\1\n/g'|tac|tr -d '\n' (and it uses a SHA256)
# ! tag signature bytes output by pm3 must be read right to left:
# echo $sig |sed 's/\(..\)/\1\n/g'|tac|tr -d '\n'
# (and it uses a SHA256)
'samples': ["E0040118009C870C", "4B4E03E1211952EF6A5F9D84AB218CD4D7549D0CDF8CA8779F9AD16C9A9CBF3B",
"E0040118009B4D62", "25CF13747C3389EC7889DE916E3747584978511CC78B51CFB1883B494CBED7AB"],
'pk': "04d64bb732c0d214e7ec580736acf847284b502c25c0f7f2fa86aace1dada4387a"},
# ! tag UID is considered inversed: E0040118009B5FEE => EE5F9B00180104E0
# TODO one more ICODE-DNA...
{'name': "ICODE DNA, ICODE SLIX2",
# ! tag UID is considered inverted: E0040118009B5FEE => EE5F9B00180104E0
# TODO one more ICODE-DNA...
'samples': ["EE5F9B00180104E0", "32D9E7579CD77E6F1FA11419231E874826984C5F189FDE1421684563A9663377"],
'pk': "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
# uses secp256r1?, SHA-256,
# {'name': "Minecraft Earth",
# # uses secp256r1?, SHA-256,
# 'samples': ["aa", "DF0E506DFF8FCFC4B7B979D917644445F1230D2C7CDC342AFA842CA240C210BE7275F62073A9670F2DCEFC602CBEE771C2B4CD4A04F3D1EA11F49ABDF7E8B721"],
# 'pk': ""},
]
@ -541,6 +546,7 @@ def selftests():
print("[FAIL]")
print("Tests: [%s]" % ["FAIL", "OK"][succeeded])
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] == "selftests":
selftests()