|
7 | 7 | import os |
8 | 8 | import time |
9 | 9 |
|
10 | | -from .sha256 import sha256 |
11 | 10 | from .curves import Point |
12 | 11 | from .bitcoin import BITCOIN |
13 | 12 |
|
14 | 13 | # ----------------------------------------------------------------------------- |
15 | | -# Secret key generation utilities |
| 14 | +# Secret key generation. We're going to leave secret key as just a super plain int |
16 | 15 |
|
17 | | -def random_bytes_os(): |
18 | | - """ |
19 | | - Use os provided entropy, e.g. on macs sourced from /dev/urandom, eg available as: |
20 | | - $ head -c 32 /dev/urandom |
21 | | -
|
22 | | - According to Apple Platform Security docs |
23 | | - https://support.apple.com/en-ie/guide/security/seca0c73a75b/web |
24 | | - the kernel CPRNG is a Fortuna-derived design targeting a 256-bit security level |
25 | | - where the entropy is sourced from: |
26 | | - - The Secure Enclave’s hardware RNG |
27 | | - - Timing-based jitter collected during boot |
28 | | - - Entropy collected from hardware interrupts |
29 | | - - A seed file used to persist entropy across boots |
30 | | - - Intel random instructions, i.e. RDSEED and RDRAND (macOS only) |
31 | | - """ |
32 | | - return os.urandom(32) |
33 | | - |
34 | | - |
35 | | -def random_bytes_user(): |
36 | | - """ |
37 | | - Collect some entropy from time and user and generate a key with SHA-256 |
38 | | - """ |
39 | | - entropy = '' |
40 | | - for i in range(5): |
41 | | - s = input("Enter some word #%d/5: " % (i+1,)) |
42 | | - entropy += s + '|' + str(int(time.time() * 1000000)) + '|' |
43 | | - return sha256(entropy.encode('ascii')) |
44 | | - |
45 | | - |
46 | | -def mastering_bitcoin_bytes(): |
47 | | - """ |
48 | | - The example from Mastering Bitcoin, Chapter 4 |
49 | | - https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch04.asciidoc |
50 | | - """ |
51 | | - sk = '3aba4162c7251c891207b747840551a71939b0de081f85c4e44cf7c13e41daa6' |
52 | | - return bytes.fromhex(sk) |
53 | | - |
54 | | - |
55 | | -def gen_secret_key(n: int, source: str = 'os') -> int: |
| 16 | +def gen_secret_key(n: int) -> int: |
56 | 17 | """ |
57 | 18 | n is the upper bound on the key, typically the order of the elliptic curve |
58 | 19 | we are using. The function will return a valid key, i.e. 1 <= key < n. |
59 | 20 | """ |
60 | | - |
61 | | - assert source in ['os', 'user', 'mastering'], "The source must be one of 'os' or 'user' or 'mastering'" |
62 | | - bytes_fn = { |
63 | | - 'os': random_bytes_os, |
64 | | - 'user': random_bytes_user, |
65 | | - 'mastering': mastering_bitcoin_bytes, |
66 | | - }[source] |
67 | | - |
68 | 21 | while True: |
69 | | - key = int.from_bytes(bytes_fn(), 'big') |
| 22 | + key = int.from_bytes(os.urandom(32), 'big') |
70 | 23 | if 1 <= key < n: |
71 | 24 | break # the key is valid, break out |
72 | | - |
73 | 25 | return key |
74 | 26 |
|
75 | 27 | # ----------------------------------------------------------------------------- |
@@ -125,12 +77,3 @@ def encode(self, compressed=True): |
125 | 77 | return prefix + self.x.to_bytes(32, 'big') |
126 | 78 | else: |
127 | 79 | return b'\x04' + self.x.to_bytes(32, 'big') + self.y.to_bytes(32, 'big') |
128 | | - |
129 | | -# ----------------------------------------------------------------------------- |
130 | | -# convenience functions |
131 | | - |
132 | | -def gen_key_pair(source: str = 'os'): |
133 | | - """ convenience function to quickly generate a secret/public keypair """ |
134 | | - sk = gen_secret_key(BITCOIN.gen.n, source) |
135 | | - pk = PublicKey.from_sk(sk) |
136 | | - return sk, pk |
0 commit comments