Q:

Bitcoin wallet address and private key generator

I wanted to learn how to create a Bitcoin wallet in code. I used as reference this guide which has code examples in JavaScript.
I wrote my implementation in Python. Here is the resulting code:
#!/usr/bin/env python

'''
Creates BitCoin Wallet complaint credentials:
- Public Key
- Private Key
- Private Key (Wallet Import Format)
'''

import hashlib
import base58
import ecdsa

from ecdsa.keys import SigningKey
from utilitybelt import dev_random_entropy
from binascii import hexlify, unhexlify

def random_secret_exponent(curve_order):
    while True:
        random_hex = hexlify(dev_random_entropy(32))
        random_int = int(random_hex, 16)
        if random_int >= 1 and random_int < curve_order:
            return random_int

def generate_private_key():
    curve = ecdsa.curves.SECP256k1
    se = random_secret_exponent(curve.order)
    from_secret_exponent = ecdsa.keys.SigningKey.from_secret_exponent
    return hexlify(from_secret_exponent(se, curve, hashlib.sha256).to_string())

def generate_public_key(private_key_hex):
    hash160 = ripe_hash(private_key_hex)
    public_key_and_version_hex = b"04" + hash160 
    checksum = double_hash(public_key_and_version_hex)[:4]
    return base58.b58encode(public_key_and_version_hex + checksum)

def ripe_hash(key):
    ret = hashlib.new('ripemd160')
    ret.update(hashlib.sha256(key).digest())
    return ret.digest()

def double_hash(key):
    return hashlib.sha256(hashlib.sha256(key).digest()).digest()

def generate_private_key_wif(private_key_hex):
    private_key_and_version = b"80" + private_key_hex
    checksum = double_hash(private_key_and_version)[:8]
    hashed = private_key_and_version + checksum
    return base58.b58encode(private_key_and_version + checksum)

def main():
    private_key_hex = generate_private_key()
    public_key_hex = generate_public_key(private_key_hex)
    private_key_wif_hex = generate_private_key_wif(private_key_hex)
    print("Private Key: " + private_key_hex)
    print("Public Key: " + public_key_hex)
    print("Private Key (WIF Format): " + private_key_wif_hex)

if __name__ == '__main__':
    main()

How to run:
Private Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Public Key: 2Uc973e5adf5867512dd7a21638810bd53422
Private Key (WIF Format): xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

I have my concerns about the correctness of the generated keys, as well as for the private key in WIF format. In theory it should be a short string.

A:

IMPORTANT!!!
Not a Python tip, but rather a MUST when it comes to sensitive information (quote from @nzall's comment):

Those private keys should NEVER, EVER be posted in a location even
as remotely public as a code review site. More, replacing them
is not enough. For all purposes, you should now view the original keys as compromised and must NEVER EVER EVER use them again for
bitcoin storage. Doing so runs high risk of losing the bitcoins stored
in them

I just made this tip a bit more seeable for everybody.

Another three small observations, in addition to what @Graipher said.
In Python you can "chain" comparison operations which just means they are "and"ed together.
if random_int >= 1 and random_int < curve_order:
    return random_int

In your case, it'd be like this:
if 1 <= random_int < curve_order:
    return random_int

Read more about it here

More, I'd recommend you use .format() when it comes to printing:
print("Private Key: " + private_key_hex)
print("Public Key: " + public_key_hex)
print("Private Key (WIF Format): " + private_key_wif_hex)

Could be:
print("Private Key: {}".format(private_key_hex))
print("Public Key: {}".format(public_key_hex))
print("Private Key (WIF Format): {}".format(private_key_wif_hex))

You should also have two blank lines between your functions (instead of a single one)
This:
# ...
from binascii import hexlify, unhexlify

def random_secret_exponent(curve_order):
    while True:
        random_hex = hexlify(dev_random_entropy(32))
        random_int = int(random_hex, 16)
        if random_int >= 1 and random_int < curve_order:
            return random_int

def generate_private_key():
    curve = ecdsa.curves.SECP256k1
    se = random_secret_exponent(curve.order)
    from_secret_exponent = ecdsa.keys.SigningKey.from_secret_exponent
    return hexlify(from_secret_exponent(se, curve, hashlib.sha256).to_string())

# ...

Should be:
# ...
from binascii import hexlify, unhexlify

def random_secret_exponent(curve_order):
    while True:
        random_hex = hexlify(dev_random_entropy(32))
        random_int = int(random_hex, 16)
        if random_int >= 1 and random_int < curve_order:
            return random_int

def generate_private_key():
    curve = ecdsa.curves.SECP256k1
    se = random_secret_exponent(curve.order)
    from_secret_exponent = ecdsa.keys.SigningKey.from_secret_exponent
    return hexlify(from_secret_exponent(se, curve, hashlib.sha256).to_string())

# ...

For more details / suggestions / improvements regarding your code layout, you could take a look at PEP8, Python's official style guide.

A:

Three very small observations:

In your function generate_private_key_wif, you never use hashed, you re-compute it for the return value.
In a nice self-contained module like this one, you should definitely add docstrings to your functions. Have a look at PEP257 to see how they are defined.
You currently do from ecdsa.keys import SigningKey, but never use it. You also assign from_secret_exponent = ecdsa.keys.SigningKey.from_secret_exponent in your generate_private_key function. Instead do from_secret_exponent = SigningKey.from_secret_exponent or, probably better, split that line across two lines like this:

def generate_private_key():
    curve = ecdsa.curves.SECP256k1
    se = random_secret_exponent(curve.order)
    key = SigningKey.from_secret_exponent(se, curve, hashlib.sha256)
    return hexlify(key.to_string())

A:

You have an error in WIF generation, you need to decode it from hex and take only 4 bytes for checksum, not 8:
def generate_private_key_wif(private_key_hex):
    private_key_and_version = b"80" + private_key_hex
    private_key_and_version = codecs.decode(private_key_and_version, 'hex')
    checksum = double_hash(private_key_and_version)[:4]
    hashed = private_key_and_version + checksum
    return base58.b58encode(hashed)

