stlinkv2.py now works with newer PyUSB
[gnuk/gnuk.git] / tool / rsa.py
1 from binascii import hexlify, unhexlify
2 import string
3 from os import urandom
4
5 def read_key_from_file(file):
6     f = open(file)
7     n_str = f.readline()[:-1]
8     e_str = f.readline()[:-1]
9     p_str = f.readline()[:-1]
10     q_str = f.readline()[:-1]
11     f.close()
12     e = int(e_str, 16)
13     p = int(p_str, 16)
14     q = int(q_str, 16)
15     n = int(n_str, 16)
16     if n != p * q:
17         raise ValueError("wrong key", p, q, n)
18     return (unhexlify(n_str), unhexlify(e_str), unhexlify(p_str), unhexlify(q_str), e, p, q, n)
19
20 # egcd and modinv are from wikibooks
21 # https://en.wikibooks.org/wiki/Algorithm_Implementation/Mathematics/Extended_Euclidean_algorithm
22
23 def egcd(a, b):
24     if a == 0:
25         return (b, 0, 1)
26     else:
27         g, y, x = egcd(b % a, a)
28         return (g, x - (b // a) * y, y)
29
30 def modinv(a, m):
31     g, x, y = egcd(a, m)
32     if g != 1:
33         raise Exception('modular inverse does not exist')
34     else:
35         return x % m
36
37 def pkcs1_pad_for_sign(digestinfo):
38     byte_repr = '\x00' + '\x01' + string.ljust('', 256 - 19 - 32 - 3, '\xff') \
39         + '\x00' + digestinfo
40     return int(hexlify(byte_repr), 16)
41
42 def compute_signature(key, digestinfo):
43     e = key[4]
44     p = key[5]
45     q = key[6]
46     n = key[7]
47     p1 = p - 1
48     q1 = q - 1
49     h = p1 * q1
50     d = modinv(e, h)
51     dp = d % p1
52     dq = d % q1
53     qp = modinv(q, p)
54
55     input = pkcs1_pad_for_sign(digestinfo)
56     t1 = pow(input, dp, p)
57     t2 = pow(input, dq, q)
58     t = ((t1 - t2) * qp) % p
59     sig = t2 + t * q
60     return sig
61
62 def integer_to_bytes_256(i):
63     s = hex(i)[2:]
64     s = s.rstrip('L')
65     if len(s) & 1:
66         s = '0' + s
67     return string.rjust(unhexlify(s), 256, '\x00')
68
69 def get_raw_pubkey(key):
70     return key[0]