Skip to content

Commit 4d9ed5d

Browse files
committed
Expand quickstart - add basic operations
1 parent 0d26993 commit 4d9ed5d

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed

docs/source/quickstart.rst

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ The library has just one mandatory dependency: ``six``.
66
If you install ``python-ecdsa`` through pip, it should automatically
77
install ``six`` too.
88

9+
To install it you can run the following command:
10+
11+
.. code:: bash
12+
13+
pip install ecdsa
14+
915
The high level API provided by the library is primarily in the
1016
:py:class:`~ecdsa.keys` module.
1117
There you will find the :py:class:`~ecdsa.keys.SigningKey` (the class
@@ -19,3 +25,154 @@ is used.
1925
Finally, in case use of custom elliptic curves is necessary, the
2026
:py:class:`~ecdsa.curves.Curve` class may be needed.
2127

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

0 commit comments

Comments
 (0)