1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
===============
Getting started
===============
The library has just one mandatory dependency: ``six``.
If you install ``python-ecdsa`` through pip, it should automatically
install ``six`` too.
To install it you can run the following command:
.. code:: bash
pip install ecdsa
The high level API provided by the library is primarily in the
:py:class:`~ecdsa.keys` module.
There you will find the :py:class:`~ecdsa.keys.SigningKey` (the class
that enables handling of the private keys) and the
:py:class:`~ecdsa.keys.VerifyingKey` (the class that enables handling of
the public keys).
To handle shared key derivation, the :py:class:`~ecdsa.ecdh.ECDH` class
is used.
Finally, in case use of custom elliptic curves is necessary, the
:py:class:`~ecdsa.curves.Curve` class may be needed.
Key generation
==============
To generate a key, import the :py:class:`~ecdsa.keys.SigningKey` and
call the :py:func:`~ecdsa.keys.SigningKey.generate` function in it:
.. code:: python
from ecdsa.keys import SigningKey
key = SigningKey.generate()
By default, that will create a key that uses the NIST P-192 curve. To
select a more secure curve, like NIST P-256, import it from the
:py:mod:`ecdsa.curves` or from the :py:mod:`ecdsa` module:
.. code:: python
from ecdsa import SigningKey, NIST256p
key = SigningKey.generate(curve=NIST256p)
Private key storage and retrieval
=================================
To store a key as string or file, you can serialise it using many formats,
in general we recommend the PKCS#8 PEM encoding.
If you have a :py:class:`~ecdsa.keys.SigningKey` object in ``key`` and
want to save it to a file like ``priv_key.pem`` you can run the following
code:
.. code:: python
with open("priv_key.pem", "wb") as f:
f.write(key.to_pem(format="pkcs8"))
.. warning::
Not specifying the ``format=pkcs8`` will create a file that uses the legacy
``ssleay`` file format which is most commonly used by applications
that use OpenSSL, as that was originally the only format supported by it.
For a long time though OpenSSL supports the PKCS# 8 format too.
To read that file back, you can run code like this:
.. code:: python
from ecdsa import SigningKey
with open("priv_key.pem") as f:
key = SigningKey.from_pem(f.read())
.. tip::
As the format is self-describing, the parser will automatically detect
if the provided file is in the ``ssleay`` or the ``pkcs8`` format
and process it accordingly.
Public key derivation
=====================
To get the public key associated with the given private key, either
call the :py:func:`~ecdsa.keys.SigningKey.get_verifying_key` method or
access the ``verifying_key`` attribute in
:py:class:`~ecdsa.keys.SigningKey` directly:
.. code:: python
from ecdsa import SigningKey, NIST256p
private_key = SigningKey.generate(curve=NIST256p)
public_key = private_key.verifying_key
Public key storage and retrieval
================================
Similarly to private keys, public keys can be stored in files:
.. code:: python
from ecdsa import SigningKey
private_key = SigningKey.generate()
public_key = private_key.verifying_key
with open("pub_key.pem", "wb") as f:
f.write(public_key.to_pem())
And read from files:
.. code:: python
from ecdsa import VerifyingKey
with open("pub_key.pem") as f:
public_key = VerifyingKey.from_pem(f.read())
Signing
=======
To sign a byte string stored in variable ``message`` using SigningKey in
``private_key``, SHA-256, get a signature in the DER format and save it to a
file, you can use the following code:
.. code:: python
from hashlib import sha256
from ecdsa.util import sigencode_der
sig = private_key.sign_deterministic(
message,
hashfunc=sha256,
sigencode=sigencode_der
)
with open("message.sig", "wb") as f:
f.write(sig)
.. note::
As cryptographic hashes (SHA-256, SHA3-256, etc.) operate on *bytes* not
text strings, any text needs to be serialised into *bytes* before it can
be signed. This is because encoding of string "text" results in very
different bytes when it's encoded using UTF-8 and when it's encoded using
UCS-2.
Verifying
=========
To verify a signature of a byte string in ``message`` using a VerifyingKey
in ``public_key``, SHA-256 and a DER signature in a ``message.sig`` file,
you can use the following code:
.. code:: python
from hashlib import sha256
from ecdsa import BadSignatureError
from ecdsa.util import sigdecode_der
with open("message.sig", "rb") as f:
sig = f.read()
try:
ret = public_key.verify(sig, message, sha256, sigdecode=sigdecode_der)
assert ret
print("Valid signature")
except BadSignatureError:
print("Incorrect signature")
|