Keys¶
Bit assumes the easiest way to reason about Bitcoin is in the basic unit of a private key and, therefore, all functionality (viewing balance, making transactions, etc.) is wrapped up in this class for convenience. You shouldn’t have to use anything else.
What is a private key?¶
A private key is a derived point on an elliptic curve. Bitcoin and other cryptocurrencies use the SEC defined curve secp256k1 due to its properties that allow for particularly fast computation. The secret part of a private key is essentially just a sequence of randomly generated bytes (32 max); nothing special by itself. The features come when you derive a point on the curve from that value.
This value must be kept secret or you risk losing your funds permanently!
Types¶
Bit defines 2 kinds of private keys: PrivateKey
, aliased as
simply Key
, and PrivateKeyTestnet
. Both classes
have the exact same functionality.
>>> from bit import Key, PrivateKey, PrivateKeyTestnet
>>>
>>> Key == PrivateKey
True
>>>
>>> dir(Key) == dir(PrivateKeyTestnet)
True
The only difference is the network operations for PrivateKeyTestnet
will use Bitcoin’s test network where coins have no value. As such, the derived
address will also be different.
Further, there are 2 kinds of multisignature keys: MultiSig
and
MultiSigTestnet
. They incorporate a private key class from above
into a multisignature contract.
Creation¶
Creation of a new private key is as simple as:
>>> from bit import Key
>>> key = Key()
To create a multisignature key a PrivateKey
(or
PrivateKeyTestnet
) must be provided in addition to a list or set
of public keys and the number of required signatures for the contract. The
public keys may be presented as strings in hex format or bytes.
The following code produces a multisignature contract requiring signatures from both key1 and key2 to spend from:
>>> from bit import Key, MultiSig
>>> key1 = Key()
>>> key2 = Key()
>>> multisig = MultiSig(key1, {key1.public_key, key2.public_key}, 2)
IMPORTANT:
When providing as argument public keys with a set such as above, then Bit will
sort the public keys internally in lexicographical order similar to how
Electrum behaves.
If the public keys are provided with a list, then the ordering of the public
keys of that list are used, similar to how Bitcoin Core behaves.
Calling public_keys()
will always return a list with the
public keys in the order they are being used by in the multisignature contract.
Public Point¶
Each unique value applied to the curve will yield a unique point. As this is a one-way function, there is no known way to derive the private value from the point.
You can see it like this:
>>> key.public_point
Point(x=97142194878787224003202190607135598251247304976930950188466413219499502457410, y=43606604972619611673144670688496329906728122067438546662512577612023859619611)
You will never use this directly.
Public Key¶
A public key is a public point serialized to bytes. By default all keys will use the compressed version unless you explicitly need otherwise. This reduces the size of each transaction and thus fees.
Access it like so:
>>> key.public_key
b'\x03\xd6\xc4\x88\xab[S\x1d_\xb1H\x12\xbe\x19C\x08\x16\x90~@\x9fv-\x95\xf0w\x87\xfdB\x81\xa3\xd2B'
You will also never use this directly. This value is only used internally to derive your address and is needed in the construction of every transaction.
Addresses¶
All keys possess a address()
property which is derived from your public key:
>>> key.address
'1KF3Vas28f5tnt3rj2fWyR89V9MPw51xhX'
This is what you share with others to receive payments.
Bit also allows to use nested Segwit addresses, which can be displayed with the
segwit_address()
property:
>>> key.segwit_address
'3DYf8JL9F6Lmz98gpvYMH5qVMXAEazSEEn'
The address of a multisignature key can be displayed in similar manner using the
same properties address()
and segwit_address()
:
>>> multisig.address
'328k6RPdgRTLJZe9JUZUanNnJPtWB8tkvM'
>>> multisig.segwit_address
'3AkJkY9XESnPPuX2ZMFotyGggbytxfNRVZ'
Formats¶
WIF¶
The wallet import format is the primary way of representing private keys. This format stores the secret value as well as some metadata such as whether or not the public key should be compressed.
To import a private key you can pass a key in wallet import format directly to the initializer:
>>> key = Key('L3jsepcttyuJK3HKezD4qqRKGtwc8d2d1Nw6vsoPDX9cMcUxqqMv')
>>> key.address
'1ExJJsNLQDNVVM1s1sdyt1o5P3GC5r32UG'
Export:
>>> key = Key()
>>> key.to_wif()
'KxVhypbvS3hEYPAP3pYuH1LtcfbdEUcugiqg7fNFUUnmEfWVXJV4'
If you don’t know what kind of private key your WIF represents, and you don’t want to force the use of a particular class, you can do this:
>>> from bit import wif_to_key
>>>
>>> key = wif_to_key('cU6s7jckL3bZUUkb3Q2CD9vNu8F1o58K5R5a3JFtidoccMbhEGKZ')
>>> print(key)
<PrivateKeyTestnet: muUFbvTKDEokGTVUjScMhw1QF2rtv5hxCz>
Hex¶
Import:
>>> key = Key.from_hex('c28a9f80738f770d527803a566cf6fc3edf6cea586c4fc4a5223a5ad797e1ac3')
>>> key.address
'1ExJJsNLQDNVVM1s1sdyt1o5P3GC5r32UG'
Export:
>>> key = Key()
>>> key.to_hex()
'738fc299281ba8d29f54cbc6b064f9b468e064a02fe6807af8367cbb25b20673'
Integer¶
Import:
>>> key = Key.from_int(87993618360805341115891506172036624893404292644470266399436498750715784469187)
>>> key.address
'1ExJJsNLQDNVVM1s1sdyt1o5P3GC5r32UG'
Export:
>>> key = Key()
>>> key.to_int()
100038680087491563809217308525458351872289809954309021777847614847412668376286
PEM¶
Import:
>>> key = Key.from_pem(...)
>>> key.address
'1ExJJsNLQDNVVM1s1sdyt1o5P3GC5r32UG'
Export:
>>> key = Key()
>>> key.to_pem()
b'-----BEGIN PRIVATE KEY-----\nMIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQg93tloWnF8UvDLeK2n0OE\nyf/Si6O73rm33ctZHVhTIBGhRANCAARG3vtgCf5SGfIkwcvuAxNvO/tdy8HnWqS3\nUM+KrWUPpPnHeysZbO6zrG4tN/VBeV2p3whYU6dUhSueOXUPB2Oo\n-----END PRIVATE KEY-----\n'
DER¶
Import:
>>> key = Key.from_der(...)
>>> key.address
'1ExJJsNLQDNVVM1s1sdyt1o5P3GC5r32UG'
Export:
>>> key = Key()
>>> key.to_der()
b'0\x81\x84\x02\x01\x000\x10\x06\x07*\x86H\xce=\x02\x01\x06\x05+\x81\x04\x00\n\x04m0k\x02\x01\x01\x04 ld\x8f\xd4\xc0\x19\xbd^\xa1\xf7f\xee\x8b9j\x1c\xd3ZX\x89\x1b\x04\x13|e\xe7|g\x84:\xcf\xab\xa1D\x03B\x00\x04\xb6\x1a\x9bQ\x0c?\xe3\xb7\x80\x05,\xcf7\x01{\xf9,"\xb6\xdf\xe5\xbb\x0b+\x9b\xc5\x07@2\xa1\x8a\x01R<\x86\t\x1c\x02\x0fd\x8d\x90\xb5\x99w\xc5\x84(#\xfdr>^\xd3\xb5|\x9d1\xa1\x9c/\x04\xf5\xdd'
- Previous topic: Installation
- Next topic: Network