Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mnemonic seed initial imp. Several improvements. #6

Merged
merged 2 commits into from
Nov 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
__pycache__
build/
dist/
test_env/
*.egg-info

*.iml
*.pyc
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ confidence=
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=C0303,C0114,C0330,W0312,C0115,C0116,C0321,E1120,C0103,E0001
disable=C0303,C0114,C0330,W0312,C0115,C0116,C0321,E1120,C0103,E0001,W0311


[REPORTS]
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ validate:
pylint *.py

test:
python3 -m unittest tests/test.py
python3 -m unittest tests/*.py

build:
python3 setup.py sdist bdist_wheel
Expand Down
11 changes: 4 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
### v.0.1.2
Bitcoin Wallet Address Generator

This is a simple Bitcoin wallet address generator coded in Python 3.
This is a simple Bitcoin non-deterministic wallet address generator coded in Python 3.
It generates a Private Key in different formats (hex, wif and compressed wif) and corresponding Public Addresses, raw, P2WPKH addresses starting with prefix 1, P2SH addresses starting with prefix 3 as part of Segwit soft fork and Bech32 addresses with prefix bc1 P2WPKH and P2WSH.

## Installation
Expand All @@ -12,7 +12,7 @@ pip install bitcoinaddress

## Usage
###### Example 1
```
```python
from bitcoinaddress import Wallet

wallet = Wallet()
Expand Down Expand Up @@ -42,7 +42,7 @@ Public Address tb1 P2WPKH (TESTNET): tb1qv2m5c60h0vnjjuyefwlczla85ctjuev02n8ndc
```

###### Example 2
```
```python
from bitcoinaddress import Address, Key

key = Key()
Expand Down Expand Up @@ -81,11 +81,8 @@ print(address_dict)
```


## Authors
Pedro Fortes and others who contribute.


## License
## License and other
This software is distributed under the terms of the MIT License.
See the file 'LICENSE' in the root directory of the present distribution, or http://opensource.org/licenses/MIT.

Expand Down
4 changes: 2 additions & 2 deletions bitcoinaddress/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
# See the file 'LICENSE' in the root directory of the present distribution,
# or http://opensource.org/licenses/MIT.

from .key import Key
from .key.key import Key
from .address import Address
from .wallet import Wallet
from .wallet import Wallet
13 changes: 7 additions & 6 deletions bitcoinaddress/address.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import hashlib
import base58

from . import Key, segwit_addr
from bitcoinaddress.key import Key
from . import segwit_addr
from .util import doublehash256, hash160, ecdsa_secp256k1


Expand All @@ -30,7 +31,7 @@ def __init__(self, key: Key):

def generate(self) -> {}:

if self.privkey.hash is None:
if self.privkey.digest is None:
self.privkey.generate()

self._generate_publicaddress1()
Expand Down Expand Up @@ -98,9 +99,9 @@ def _generate_publicaddress_bech32_testnet(self):
self.pubaddrbc1_P2WSH_testnet = str(segwit_addr.encode('tb', 0x00, redeem_script_P2WSH))

def __generate_uncompressed_pubkey(self, prefix_a, prefix_b):
digest = self.privkey.hash.digest()
_digest = self.privkey.digest

_p = prefix_a + ecdsa_secp256k1(digest).to_string() # 1 + 32 bytes + 32 bytes
_p = prefix_a + ecdsa_secp256k1(_digest).to_string() # 1 + 32 bytes + 32 bytes
self.pubkey = str(binascii.hexlify(_p).decode('utf-8'))

m = prefix_b + hash160(_p).digest()
Expand All @@ -111,9 +112,9 @@ def __generate_uncompressed_pubkey(self, prefix_a, prefix_b):
def __generate_compressed_pubkey(self, prefix_even, prefix_odd):
prefix_a = prefix_odd

digest = self.privkey.hash.digest()
_digest = self.privkey.digest

ecdsa_digest = ecdsa_secp256k1(digest).to_string()
ecdsa_digest = ecdsa_secp256k1(_digest).to_string()

x_coord = ecdsa_digest[:int(len(ecdsa_digest) / 2)]
y_coord = ecdsa_digest[int(len(ecdsa_digest) / 2):]
Expand Down
72 changes: 0 additions & 72 deletions bitcoinaddress/key.py

This file was deleted.

8 changes: 8 additions & 0 deletions bitcoinaddress/key/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Bitcoin Address v0.1
# Copyright (c) 2020 - https://github.com/fortesp/bitcoinaddress
# This software is distributed under the terms of the MIT License.
# See the file 'LICENSE' in the root directory of the present distribution,
# or http://opensource.org/licenses/MIT.

from .key import Key
from .seed import Seed
96 changes: 96 additions & 0 deletions bitcoinaddress/key/key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Bitcoin Address v0.1
# Copyright (c) 2020 - https://github.com/fortesp/bitcoinaddress
# This software is distributed under the terms of the MIT License.
# See the file 'LICENSE' in the root directory of the present distribution,
# or http://opensource.org/licenses/MIT.

import hashlib
import base58
from binascii import hexlify, unhexlify
from .seed import Seed
from bitcoinaddress.util import doublehash256


class Key:

CHECKSUM_SIZE = 4

def __init__(self, seed=None):
self.seed = seed
self.digest = None
self.hex = None
self.wif = None
self.wif_c = None
self.wif_testnet = None
self.wif_c_testnet = None

def generate_from_hex(self, hex):
self.digest = unhexlify(hex)

self._generate_hex()
self._generate_wif()
self._generate_wif_testnet()
return self.__return()

def generate_from_wif(self, wif):
self.digest = self.__wif_to_digest(wif)

self._generate_hex()
self._generate_wif()
self._generate_wif_testnet()
return self.__return()

def generate(self):
self._generate_digest()
self._generate_hex()
self._generate_wif()
self._generate_wif_testnet()
return self.__return()

def _generate_digest(self):
if self.seed is None:
self.seed = Seed.random()
else:
if isinstance(self.seed, Seed):
self.seed = str(self.seed.data)

hash = hashlib.sha256(self.seed.encode())
self.digest = hash.digest()

def _generate_hex(self):
self.hex = hexlify(self.digest).decode()

def _generate_wif(self):
prefix = b'\x80'
suffix = b'\x01'
self.wif, self.wif_c = self.__generate_wif(prefix, suffix)

def _generate_wif_testnet(self):
prefix = b'\xEF'
suffix = b'\x01'
self.wif_testnet, self.wif_c_testnet = self.__generate_wif(prefix, suffix)

def __generate_wif(self, prefix, suffix):
_digest = prefix + self.digest

checksum = doublehash256(_digest).digest()[:Key.CHECKSUM_SIZE]
checksum_c = doublehash256(_digest + suffix).digest()[:Key.CHECKSUM_SIZE]

wif = base58.b58encode(_digest + checksum).decode('utf-8')
wif_c = base58.b58encode(_digest + suffix + checksum_c).decode('utf-8')
return wif, wif_c

def __wif_to_digest(self, wif):
return base58.b58decode(wif)[1:-Key.CHECKSUM_SIZE]

def __return(self):
return {'hex': self.hex, 'wif': self.wif, 'wifc': self.wif_c,
'testnet': {'hex': self.hex, 'wif': self.wif_testnet, 'wifc': self.wif_c_testnet}}

def __str__(self):
return """Private Key HEX: %s\n
\rPrivate Key WIF: %s
\rPrivate Key WIF compressed: %s
\rPrivate Key WIF (TESTNET): %s
\rPrivate Key WIF compressed (TESTNET): %s
""" % (self.hex, self.wif, self.wif_c, self.wif_testnet, self.wif_c_testnet)
33 changes: 33 additions & 0 deletions bitcoinaddress/key/seed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Bitcoin Address v0.1
# Copyright (c) 2020 - https://github.com/fortesp/bitcoinaddress
# This software is distributed under the terms of the MIT License.
# See the file 'LICENSE' in the root directory of the present distribution,
# or http://opensource.org/licenses/MIT.

import time
from random import getrandbits
from mnemonic import Mnemonic


class Seed:

def __init__(self, data=None, mnemonic=False):
self.data = data
self.mnemonic = mnemonic

def generate(self):
if self.mnemonic: # TODO
m = Mnemonic("english")
if self.data is None:
self.data = m.generate(strength=256)
else:
if self.data is None:
self.data = Seed.random()

@staticmethod
def random():
current_time = int(time.time())
return str(getrandbits(30000) - current_time)

def __str__(self):
return self.data
7 changes: 0 additions & 7 deletions bitcoinaddress/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
# or http://opensource.org/licenses/MIT.

import hashlib
import time
import random
import ecdsa


Expand All @@ -24,8 +22,3 @@ def ecdsa_secp256k1(digest):
# SECP256k1 - Bitcoin elliptic curve
sk = ecdsa.SigningKey.from_string(digest, curve=ecdsa.SECP256k1)
return sk.get_verifying_key()


def randomseed():
current_time = int(time.time())
return str(random.getrandbits(3000) - current_time)
10 changes: 10 additions & 0 deletions tests/test_address.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import unittest


# TODO - More coverage and refactoring
class TestAddress(unittest.TestCase):
pass


if __name__ == "__main__":
unittest.main()
Loading