まずは、ベースとなる形だけ記述しておきます。
(今後使用するモジュールは最初に全部書いておきました)
イメージとしては、このコードが実行された時に秘密鍵、公開鍵、アドレスを作り出します。
#!/usr/bin/env python3
# coding: utf-8
import secrets
import ecdsa
import hashlib
import base58
class Generater():
    def __init__(self):
        p = 2**256-2**32-2**9-2**8-2**7-2**6-2**4-1
        privkey = self.new_privkey()
        pubkey = self.new_pubkey()
        address = self.new_address()
    def new_privkey(self, p):
        pass
    def new_pubkey(self, privkey):
        pass
    def new_address(self, version, pubkey):
        pass
address = Generater()
    
では順番に見ていきます。まずは、秘密鍵です。
秘密鍵は  
p より小さい数字(ランダムに選び出した)になります。
    def new_privkey(self, p):
            privkey = secrets.randbelow(p)
            privkey = format(privkey, 'x')
            print("PrivateKey = " + privkey)
            return privkey
    | 名称 | 内容 | 
|---|---|
| randbelow | 引数より小さい数字をランダムに選んでくれます。乱数の選び方は、OSによって依存しているので、安全に乱数を出力できるようにしましょう | 
| format | 16進数表示に変換します | 
| bytes.fromhex | 16進数からバイト列に変換します | 
続いて、公開鍵の説明になります。公開鍵は先ほどの秘密鍵とECDSAを用いて生成します。関数 new_pubkey に引数として先ほどの秘密鍵を指定します。
    def new_pubkey(self, privkey):
            bin_privkey = bytes.fromhex(privkey)
            signing_key = ecdsa.SigningKey.from_string(bin_privkey, curve = ecdsa.SECP256k1)
            verifying_key = signing_key.get_verifying_key()
            pubkey = bytes.fromhex("04") + verifying_key.to_string()
            pubkey = pubkey.hex()
            print("PublicKey = " + pubkey)
            return pubkey
    | 名称 | 内容 | 
|---|---|
| bytes.fromhex | 16進数からバイト列に変換します | 
| ecdsa.SigningKey | ECDSAを用いて楕円曲線から公開鍵となる値を計算する | 
| pubkey | プレフィックスとして16進数で"04"を先頭に、ECDSAで計算結果列を後ろに付けます。最後に全体を16進数表記にすれば完成 | 
アドレスは、今回はビットコインアドレスの作り方を真似ました。引数として、先ほどの公開鍵とバージョンを指定するようにしています。ビットコインアドレスの場合16進数で "00" になります。
    def new_address(self, version, pubkey):
            ba = bytes.fromhex(pubkey)
            digest = hashlib.sha256(ba).digest()
            new_digest = hashlib.new('ripemd160')
            new_digest.update(digest)
            pubkey_hash = new_digest.digest()
            pre_address = version + pubkey_hash
            address = hashlib.sha256(pre_address).digest()
            address = hashlib.sha256(address).digest()
            checksum = address[:4]
            address = pre_address + checksum
            address = base58.b58encode(address)
            address = address.decode()
            print("Address = " + address + "\n")
            return address
      
ここから注意点がたくさん出てきます。まず、アドレスを作る際にチェックサムが必要になります。チェックサムを生成するために、公開鍵のハッシュ値が必要です。  
  
また、チェックサムは  
  
この address の前から 4バイトになります。
| 名称 | 内容 | 
|---|---|
| ba | 16進数公開鍵をバイト列に変換 | 
| digest | baをsha256でハッシュ化してできたものを文字列にして代入 | 
| pubkey_hash | digestをripemd160でハッシュ値を取り、文字列として代入 | 
| pre_address | version(引数) + pubkey_hash | 
| b58encode | b58encodeする | 
| decode | デコードする | 
これで以上になります。全体像を最後に貼り付けておきます。
#!/usr/bin/env python3
# coding: utf-8
import secrets
import ecdsa
import hashlib
import base58
class Generater():
    def __init__(self):
        p = 2**256-2**32-2**9-2**8-2**7-2**6-2**4-1
        privkey = self.new_privkey(p)
        pubkey = self.new_pubkey(privkey)
        address = self.new_address(bytes.fromhex("00"), pubkey)
    def new_privkey(self, p):
        privkey = secrets.randbelow(p)
        privkey = format(privkey, 'x')
        print("PrivateKey = " + privkey)
        return privkey
    def new_pubkey(self, privkey):
        bin_privkey = bytes.fromhex(privkey)
        signing_key = ecdsa.SigningKey.from_string(bin_privkey, curve = ecdsa.SECP256k1)
        verifying_key = signing_key.get_verifying_key()
        pubkey = bytes.fromhex("04") + verifying_key.to_string()
        pubkey = pubkey.hex()
        print("PublicKey = " + pubkey)
        return pubkey
    def new_address(self, version, pubkey):
        ba = bytes.fromhex(pubkey)
        digest = hashlib.sha256(ba).digest()
        new_digest = hashlib.new('ripemd160')
        new_digest.update(digest)
        pubkey_hash = new_digest.digest()
        pre_address = version + pubkey_hash
        address = hashlib.sha256(pre_address).digest()
        address = hashlib.sha256(address).digest()
        checksum = address[:4]
        address = pre_address + checksum
        address = base58.b58encode(address)
        address = address.decode()
        print("Address = " + address + "\n")
        return address
address = Generater()
    
では、実行して見ましょう。
PrivateKey = c31ad13427f28c429c443d6058129051614875ab5f576364e0e2866e3ab87aae
PublicKey = 048813b6143a1316041ff1fb4f3af6061a05f7803ef01e32cf3ff1a71422f95a6d600638c460a49f5c6125b11cbc5bdfff30c0545c6f208d9a1fa6ed504b2d2c29
Address = 176wVvyL4NzecB9nm7DmuQ3x5rfqXCo1n5
      
Address が「1」から始まっていれば成功です。