summaryrefslogtreecommitdiff
path: root/docs/source/quickstart.rst
blob: e83a6a6f0ee6c2a68b0a23f166a3c92193e62711 (plain)
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")