| 609 | |
| 610 | |
| 611 | class PrivateKey: |
| 612 | |
| 613 | def __init__(self, secret): |
| 614 | self.secret = secret |
| 615 | self.point = secret * G |
| 616 | |
| 617 | def hex(self): |
| 618 | return '{:x}'.format(self.secret).zfill(64) |
| 619 | |
| 620 | def sign(self, z): |
| 621 | k = self.deterministic_k(z) |
| 622 | # r is the x coordinate of the resulting point k*G |
| 623 | r = (k * G).x.num |
| 624 | # remember 1/k = pow(k, N-2, N) |
| 625 | k_inv = pow(k, N - 2, N) |
| 626 | # s = (z+r*secret) / k |
| 627 | s = (z + r * self.secret) * k_inv % N |
| 628 | if s > N / 2: |
| 629 | s = N - s |
| 630 | # return an instance of Signature: |
| 631 | # Signature(r, s) |
| 632 | return Signature(r, s) |
| 633 | |
| 634 | def deterministic_k(self, z): |
| 635 | k = b'\x00' * 32 |
| 636 | v = b'\x01' * 32 |
| 637 | if z > N: |
| 638 | z -= N |
| 639 | z_bytes = z.to_bytes(32, 'big') |
| 640 | secret_bytes = self.secret.to_bytes(32, 'big') |
| 641 | s256 = hashlib.sha256 |
| 642 | k = hmac.new(k, v + b'\x00' + secret_bytes + z_bytes, s256).digest() |
| 643 | v = hmac.new(k, v, s256).digest() |
| 644 | k = hmac.new(k, v + b'\x01' + secret_bytes + z_bytes, s256).digest() |
| 645 | v = hmac.new(k, v, s256).digest() |
| 646 | while True: |
| 647 | v = hmac.new(k, v, s256).digest() |
| 648 | candidate = int.from_bytes(v, 'big') |
| 649 | if candidate >= 1 and candidate < N: |
| 650 | return candidate |
| 651 | k = hmac.new(k, v + b'\x00', s256).digest() |
| 652 | v = hmac.new(k, v, s256).digest() |
| 653 | |
| 654 | def wif(self, compressed=True, testnet=False): |
| 655 | # convert the secret from integer to a 32-bytes in big endian using num.to_bytes(32, 'big') |
| 656 | secret_bytes = self.secret.to_bytes(32, 'big') |
| 657 | # prepend b'\xef' on testnet, b'\x80' on mainnet |
| 658 | if testnet: |
| 659 | prefix = b'\xef' |
| 660 | else: |
| 661 | prefix = b'\x80' |
| 662 | # append b'\x01' if compressed |
| 663 | if compressed: |
| 664 | suffix = b'\x01' |
| 665 | else: |
| 666 | suffix = b'' |
| 667 | # encode_base58_checksum the whole thing |
| 668 | return encode_base58_checksum(prefix + secret_bytes + suffix) |
no outgoing calls