• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

src/H27-Aug-2020-11,3378,958

LICENSEH A D20-Jan-20151.1 KiB2520

MANIFEST.inH A D06-Nov-2019104 43

NEWSH A D27-Aug-202010 KiB244197

PKG-INFOH A D27-Aug-202029 KiB622509

README.mdH A D27-Aug-202023.4 KiB597485

setup.cfgH A D27-Aug-2020234 1612

setup.pyH A D12-Mar-20201.5 KiB4739

versioneer.pyH A D12-Mar-202067.3 KiB1,9041,487

README.md

1# Pure-Python ECDSA
2
3[![build status](https://travis-ci.org/warner/python-ecdsa.png)](http://travis-ci.org/warner/python-ecdsa)
4[![Coverage Status](https://coveralls.io/repos/warner/python-ecdsa/badge.svg)](https://coveralls.io/r/warner/python-ecdsa)
5[![condition coverage](https://img.shields.io/badge/condition%20coverage-81%25-yellow)](https://travis-ci.org/warner/python-ecdsa/jobs/626479178#L776)
6[![Latest Version](https://img.shields.io/pypi/v/ecdsa.svg?style=flat)](https://pypi.python.org/pypi/ecdsa/)
7![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat)
8
9
10This is an easy-to-use implementation of ECDSA cryptography (Elliptic Curve
11Digital Signature Algorithm), implemented purely in Python, released under
12the MIT license. With this library, you can quickly create keypairs (signing
13key and verifying key), sign messages, and verify the signatures. The keys
14and signatures are very short, making them easy to handle and incorporate
15into other protocols.
16
17## Features
18
19This library provides key generation, signing, and verifying, for five
20popular NIST "Suite B" GF(p) (_prime field_) curves, with key lengths of 192,
21224, 256, 384, and 521 bits. The "short names" for these curves, as known by
22the OpenSSL tool (`openssl ecparam -list_curves`), are: `prime192v1`,
23`secp224r1`, `prime256v1`, `secp384r1`, and `secp521r1`. It includes the
24256-bit curve `secp256k1` used by Bitcoin. There is also support for the
25regular (non-twisted) variants of Brainpool curves from 160 to 512 bits. The
26"short names" of those curves are: `brainpoolP160r1`, `brainpoolP192r1`,
27`brainpoolP224r1`, `brainpoolP256r1`, `brainpoolP320r1`, `brainpoolP384r1`,
28`brainpoolP512r1`.
29No other curves are included, but it is not too hard to add support for more
30curves over prime fields.
31
32## Dependencies
33
34This library uses only Python and the 'six' package. It is compatible with
35Python 2.6, 2.7 and 3.3+. It also supports execution on the alternative
36implementations like pypy and pypy3.
37
38If `gmpy2` or `gmpy` is installed, they will be used for faster arithmetic.
39Either of them can be installed after this library is installed,
40`python-ecdsa` will detect their presence on start-up and use them
41automatically.
42
43To run the OpenSSL compatibility tests, the 'openssl' tool must be in your
44`PATH`. This release has been tested successfully against OpenSSL 0.9.8o,
451.0.0a, 1.0.2f and 1.1.1d (among others).
46
47
48## Installation
49
50This library is available on PyPI, it's recommended to install it using `pip`:
51
52```
53pip install ecdsa
54```
55
56In case higher performance is wanted and using native code is not a problem,
57it's possible to specify installation together with `gmpy2`:
58
59```
60pip install ecdsa[gmpy2]
61```
62
63or (slower, legacy option):
64```
65pip install ecdsa[gmpy]
66```
67
68## Speed
69
70The following table shows how long this library takes to generate keypairs
71(`keygen`), to sign data (`sign`), and to verify those signatures (`verify`).
72All those values are in seconds.
73For convenience, the inverses of those values are also provided:
74how many keys per second can be generated (`keygen/s`), how many signatures
75can be made per second (`sign/s`) and how many signatures can be verified
76per second (`verify/s`). The size of raw signature (generally the smallest
77way a signature can be encoded) is also provided in the `siglen` column.
78Use `tox -e speed` to generate this table on your own computer.
79On an Intel Core i7 4790K @ 4.0GHz I'm getting the following performance:
80
81```
82                  siglen    keygen   keygen/s      sign     sign/s    verify   verify/s
83        NIST192p:     48   0.00035s   2893.02   0.00038s   2620.53   0.00069s   1458.92
84        NIST224p:     56   0.00043s   2307.11   0.00048s   2092.00   0.00088s   1131.33
85        NIST256p:     64   0.00056s   1793.70   0.00061s   1639.87   0.00113s    883.79
86        NIST384p:     96   0.00116s    864.33   0.00124s    806.29   0.00233s    429.87
87        NIST521p:    132   0.00221s    452.16   0.00234s    427.31   0.00460s    217.19
88       SECP256k1:     64   0.00056s   1772.65   0.00061s   1628.73   0.00110s    912.13
89 BRAINPOOLP160r1:     40   0.00026s   3801.86   0.00029s   3401.11   0.00052s   1930.47
90 BRAINPOOLP192r1:     48   0.00034s   2925.73   0.00038s   2634.34   0.00070s   1438.06
91 BRAINPOOLP224r1:     56   0.00044s   2287.98   0.00048s   2083.87   0.00088s   1137.52
92 BRAINPOOLP256r1:     64   0.00056s   1774.11   0.00061s   1628.25   0.00112s    890.71
93 BRAINPOOLP320r1:     80   0.00081s   1238.18   0.00087s   1146.71   0.00151s    661.95
94 BRAINPOOLP384r1:     96   0.00117s    855.47   0.00124s    804.56   0.00241s    414.83
95 BRAINPOOLP512r1:    128   0.00223s    447.99   0.00234s    427.49   0.00437s    229.09
96
97                       ecdh     ecdh/s
98        NIST192p:   0.00110s    910.70
99        NIST224p:   0.00143s    701.17
100        NIST256p:   0.00178s    560.44
101        NIST384p:   0.00383s    261.03
102        NIST521p:   0.00745s    134.23
103       SECP256k1:   0.00168s    596.23
104 BRAINPOOLP160r1:   0.00085s   1174.02
105 BRAINPOOLP192r1:   0.00113s    883.47
106 BRAINPOOLP224r1:   0.00145s    687.82
107 BRAINPOOLP256r1:   0.00195s    514.03
108 BRAINPOOLP320r1:   0.00277s    360.80
109 BRAINPOOLP384r1:   0.00412s    242.58
110 BRAINPOOLP512r1:   0.00787s    127.12
111```
112
113To test performance with `gmpy2` loaded, use `tox -e speedgmpy2`.
114On the same machine I'm getting the following performance with `gmpy2`:
115```
116                  siglen    keygen   keygen/s      sign     sign/s    verify   verify/s
117        NIST192p:     48   0.00017s   5945.50   0.00018s   5544.66   0.00033s   3002.54
118        NIST224p:     56   0.00021s   4742.14   0.00022s   4463.52   0.00044s   2248.59
119        NIST256p:     64   0.00024s   4155.73   0.00025s   3994.28   0.00047s   2105.34
120        NIST384p:     96   0.00041s   2415.06   0.00043s   2316.41   0.00085s   1177.18
121        NIST521p:    132   0.00072s   1391.14   0.00074s   1359.63   0.00140s    716.31
122       SECP256k1:     64   0.00024s   4216.50   0.00025s   3994.52   0.00047s   2120.57
123 BRAINPOOLP160r1:     40   0.00014s   7038.99   0.00015s   6501.55   0.00029s   3397.79
124 BRAINPOOLP192r1:     48   0.00017s   5983.18   0.00018s   5626.08   0.00035s   2843.62
125 BRAINPOOLP224r1:     56   0.00021s   4727.54   0.00022s   4464.86   0.00043s   2326.84
126 BRAINPOOLP256r1:     64   0.00024s   4221.00   0.00025s   4010.26   0.00049s   2046.40
127 BRAINPOOLP320r1:     80   0.00032s   3142.14   0.00033s   3009.15   0.00061s   1652.88
128 BRAINPOOLP384r1:     96   0.00041s   2415.98   0.00043s   2340.35   0.00083s   1198.77
129 BRAINPOOLP512r1:    128   0.00064s   1567.27   0.00066s   1526.33   0.00127s    788.51
130
131                       ecdh     ecdh/s
132        NIST192p:   0.00051s   1960.26
133        NIST224p:   0.00067s   1502.97
134        NIST256p:   0.00073s   1376.12
135        NIST384p:   0.00132s    758.68
136        NIST521p:   0.00231s    433.23
137       SECP256k1:   0.00072s   1387.18
138 BRAINPOOLP160r1:   0.00042s   2366.60
139 BRAINPOOLP192r1:   0.00049s   2026.80
140 BRAINPOOLP224r1:   0.00067s   1486.52
141 BRAINPOOLP256r1:   0.00076s   1310.31
142 BRAINPOOLP320r1:   0.00101s    986.16
143 BRAINPOOLP384r1:   0.00131s    761.35
144 BRAINPOOLP512r1:   0.00211s    473.30
145```
146
147(there's also `gmpy` version, execute it using `tox -e speedgmpy`)
148
149For comparison, a highly optimised implementation (including curve-specific
150assembly for some curves), like the one in OpenSSL 1.1.1d, provides following
151performance numbers on the same machine.
152Run `openssl speed ecdsa` and `openssl speed ecdh` to reproduce it:
153```
154                              sign    verify    sign/s verify/s
155 192 bits ecdsa (nistp192)   0.0002s   0.0002s   4785.6   5380.7
156 224 bits ecdsa (nistp224)   0.0000s   0.0001s  22475.6   9822.0
157 256 bits ecdsa (nistp256)   0.0000s   0.0001s  45069.6  14166.6
158 384 bits ecdsa (nistp384)   0.0008s   0.0006s   1265.6   1648.1
159 521 bits ecdsa (nistp521)   0.0003s   0.0005s   3753.1   1819.5
160 256 bits ecdsa (brainpoolP256r1)   0.0003s   0.0003s   2983.5   3333.2
161 384 bits ecdsa (brainpoolP384r1)   0.0008s   0.0007s   1258.8   1528.1
162 512 bits ecdsa (brainpoolP512r1)   0.0015s   0.0012s    675.1    860.1
163
164                               op      op/s
165 192 bits ecdh (nistp192)   0.0002s   4853.4
166 224 bits ecdh (nistp224)   0.0001s  15252.1
167 256 bits ecdh (nistp256)   0.0001s  18436.3
168 384 bits ecdh (nistp384)   0.0008s   1292.7
169 521 bits ecdh (nistp521)   0.0003s   2884.7
170 256 bits ecdh (brainpoolP256r1)   0.0003s   3066.5
171 384 bits ecdh (brainpoolP384r1)   0.0008s   1298.0
172 512 bits ecdh (brainpoolP512r1)   0.0014s    694.8
173```
174
175Keys and signature can be serialized in different ways (see Usage, below).
176For a NIST192p key, the three basic representations require strings of the
177following lengths (in bytes):
178
179    to_string:  signkey= 24, verifykey= 48, signature=48
180    compressed: signkey=n/a, verifykey= 25, signature=n/a
181    DER:        signkey=106, verifykey= 80, signature=55
182    PEM:        signkey=278, verifykey=162, (no support for PEM signatures)
183
184## History
185
186In 2006, Peter Pearson announced his pure-python implementation of ECDSA in a
187[message to sci.crypt][1], available from his [download site][2]. In 2010,
188Brian Warner wrote a wrapper around this code, to make it a bit easier and
189safer to use. Hubert Kario then included an implementation of elliptic curve
190cryptography that uses Jacobian coordinates internally, improving performance
191about 20-fold. You are looking at the README for this wrapper.
192
193[1]: http://www.derkeiler.com/Newsgroups/sci.crypt/2006-01/msg00651.html
194[2]: http://webpages.charter.net/curryfans/peter/downloads.html
195
196## Testing
197
198To run the full test suite, do this:
199
200    tox -e coverage
201
202On an Intel Core i7 4790K @ 4.0GHz, the tests take about 16 seconds to execute.
203The test suite uses
204[`hypothesis`](https://github.com/HypothesisWorks/hypothesis) so there is some
205inherent variability in the test suite execution time.
206
207One part of `test_pyecdsa.py` checks compatibility with OpenSSL, by
208running the "openssl" CLI tool, make sure it's in your `PATH` if you want
209to test compatibility with it.
210
211## Security
212
213This library was not designed with security in mind. If you are processing
214data that needs to be protected we suggest you use a quality wrapper around
215OpenSSL. [pyca/cryptography](https://cryptography.io) is one example of such
216a wrapper. The primary use-case of this library is as a portable library for
217interoperability testing and as a teaching tool.
218
219**This library does not protect against side channel attacks.**
220
221Do not allow attackers to measure how long it takes you to generate a keypair
222or sign a message. Do not allow attackers to run code on the same physical
223machine when keypair generation or signing is taking place (this includes
224virtual machines). Do not allow attackers to measure how much power your
225computer uses while generating the keypair or signing a message. Do not allow
226attackers to measure RF interference coming from your computer while generating
227a keypair or signing a message. Note: just loading the private key will cause
228keypair generation. Other operations or attack vectors may also be
229vulnerable to attacks. **For a sophisticated attacker observing just one
230operation with a private key will be sufficient to completely
231reconstruct the private key**.
232
233Please also note that any Pure-python cryptographic library will be vulnerable
234to the same side channel attacks. This is because Python does not provide
235side-channel secure primitives (with the exception of
236[`hmac.compare_digest()`][3]), making side-channel secure programming
237impossible.
238
239This library depends upon a strong source of random numbers. Do not use it on
240a system where `os.urandom()` does not provide cryptographically secure
241random numbers.
242
243[3]: https://docs.python.org/3/library/hmac.html#hmac.compare_digest
244
245## Usage
246
247You start by creating a `SigningKey`. You can use this to sign data, by passing
248in data as a byte string and getting back the signature (also a byte string).
249You can also ask a `SigningKey` to give you the corresponding `VerifyingKey`.
250The `VerifyingKey` can be used to verify a signature, by passing it both the
251data string and the signature byte string: it either returns True or raises
252`BadSignatureError`.
253
254```python
255from ecdsa import SigningKey
256sk = SigningKey.generate() # uses NIST192p
257vk = sk.verifying_key
258signature = sk.sign(b"message")
259assert vk.verify(signature, b"message")
260```
261
262Each `SigningKey`/`VerifyingKey` is associated with a specific curve, like
263NIST192p (the default one). Longer curves are more secure, but take longer to
264use, and result in longer keys and signatures.
265
266```python
267from ecdsa import SigningKey, NIST384p
268sk = SigningKey.generate(curve=NIST384p)
269vk = sk.verifying_key
270signature = sk.sign(b"message")
271assert vk.verify(signature, b"message")
272```
273
274The `SigningKey` can be serialized into several different formats: the shortest
275is to call `s=sk.to_string()`, and then re-create it with
276`SigningKey.from_string(s, curve)` . This short form does not record the
277curve, so you must be sure to pass to `from_string()` the same curve you used
278for the original key. The short form of a NIST192p-based signing key is just 24
279bytes long. If a point encoding is invalid or it does not lie on the specified
280curve, `from_string()` will raise `MalformedPointError`.
281
282```python
283from ecdsa import SigningKey, NIST384p
284sk = SigningKey.generate(curve=NIST384p)
285sk_string = sk.to_string()
286sk2 = SigningKey.from_string(sk_string, curve=NIST384p)
287print(sk_string.hex())
288print(sk2.to_string().hex())
289```
290
291Note: while the methods are called `to_string()` the type they return is
292actually `bytes`, the "string" part is leftover from Python 2.
293
294`sk.to_pem()` and `sk.to_der()` will serialize the signing key into the same
295formats that OpenSSL uses. The PEM file looks like the familiar ASCII-armored
296`"-----BEGIN EC PRIVATE KEY-----"` base64-encoded format, and the DER format
297is a shorter binary form of the same data.
298`SigningKey.from_pem()/.from_der()` will undo this serialization. These
299formats include the curve name, so you do not need to pass in a curve
300identifier to the deserializer. In case the file is malformed `from_der()`
301and `from_pem()` will raise `UnexpectedDER` or` MalformedPointError`.
302
303```python
304from ecdsa import SigningKey, NIST384p
305sk = SigningKey.generate(curve=NIST384p)
306sk_pem = sk.to_pem()
307sk2 = SigningKey.from_pem(sk_pem)
308# sk and sk2 are the same key
309```
310
311Likewise, the `VerifyingKey` can be serialized in the same way:
312`vk.to_string()/VerifyingKey.from_string()`, `to_pem()/from_pem()`, and
313`to_der()/from_der()`. The same `curve=` argument is needed for
314`VerifyingKey.from_string()`.
315
316```python
317from ecdsa import SigningKey, VerifyingKey, NIST384p
318sk = SigningKey.generate(curve=NIST384p)
319vk = sk.verifying_key
320vk_string = vk.to_string()
321vk2 = VerifyingKey.from_string(vk_string, curve=NIST384p)
322# vk and vk2 are the same key
323
324from ecdsa import SigningKey, VerifyingKey, NIST384p
325sk = SigningKey.generate(curve=NIST384p)
326vk = sk.verifying_key
327vk_pem = vk.to_pem()
328vk2 = VerifyingKey.from_pem(vk_pem)
329# vk and vk2 are the same key
330```
331
332There are a couple of different ways to compute a signature. Fundamentally,
333ECDSA takes a number that represents the data being signed, and returns a
334pair of numbers that represent the signature. The `hashfunc=` argument to
335`sk.sign()` and `vk.verify()` is used to turn an arbitrary string into
336fixed-length digest, which is then turned into a number that ECDSA can sign,
337and both sign and verify must use the same approach. The default value is
338`hashlib.sha1`, but if you use NIST256p or a longer curve, you can use
339`hashlib.sha256` instead.
340
341There are also multiple ways to represent a signature. The default
342`sk.sign()` and `vk.verify()` methods present it as a short string, for
343simplicity and minimal overhead. To use a different scheme, use the
344`sk.sign(sigencode=)` and `vk.verify(sigdecode=)` arguments. There are helper
345functions in the `ecdsa.util` module that can be useful here.
346
347It is also possible to create a `SigningKey` from a "seed", which is
348deterministic. This can be used in protocols where you want to derive
349consistent signing keys from some other secret, for example when you want
350three separate keys and only want to store a single master secret. You should
351start with a uniformly-distributed unguessable seed with about `curve.baselen`
352bytes of entropy, and then use one of the helper functions in `ecdsa.util` to
353convert it into an integer in the correct range, and then finally pass it
354into `SigningKey.from_secret_exponent()`, like this:
355
356```python
357import os
358from ecdsa import NIST384p, SigningKey
359from ecdsa.util import randrange_from_seed__trytryagain
360
361def make_key(seed):
362  secexp = randrange_from_seed__trytryagain(seed, NIST384p.order)
363  return SigningKey.from_secret_exponent(secexp, curve=NIST384p)
364
365seed = os.urandom(NIST384p.baselen) # or other starting point
366sk1a = make_key(seed)
367sk1b = make_key(seed)
368# note: sk1a and sk1b are the same key
369assert sk1a.to_string() == sk1b.to_string()
370sk2 = make_key(b"2-"+seed)  # different key
371assert sk1a.to_string() != sk2.to_string()
372```
373
374In case the application will verify a lot of signatures made with a single
375key, it's possible to precompute some of the internal values to make
376signature verification significantly faster. The break-even point occurs at
377about 100 signatures verified.
378
379To perform precomputation, you can call the `precompute()` method
380on `VerifyingKey` instance:
381```python
382from ecdsa import SigningKey, NIST384p
383sk = SigningKey.generate(curve=NIST384p)
384vk = sk.verifying_key
385vk.precompute()
386signature = sk.sign(b"message")
387assert vk.verify(signature, b"message")
388```
389
390Once `precompute()` was called, all signature verifications with this key will
391be faster to execute.
392
393## OpenSSL Compatibility
394
395To produce signatures that can be verified by OpenSSL tools, or to verify
396signatures that were produced by those tools, use:
397
398```python
399# openssl ecparam -name prime256v1 -genkey -out sk.pem
400# openssl ec -in sk.pem -pubout -out vk.pem
401# echo "data for signing" > data
402# openssl dgst -sha256 -sign sk.pem -out data.sig data
403# openssl dgst -sha256 -verify vk.pem -signature data.sig data
404# openssl dgst -sha256 -prverify sk.pem -signature data.sig data
405
406import hashlib
407from ecdsa import SigningKey, VerifyingKey
408from ecdsa.util import sigencode_der, sigdecode_der
409
410with open("vk.pem") as f:
411   vk = VerifyingKey.from_pem(f.read())
412
413with open("data", "rb") as f:
414   data = f.read()
415
416with open("data.sig", "rb") as f:
417   signature = f.read()
418
419assert vk.verify(signature, data, hashlib.sha256, sigdecode=sigdecode_der)
420
421with open("sk.pem") as f:
422   sk = SigningKey.from_pem(f.read(), hashlib.sha256)
423
424new_signature = sk.sign_deterministic(data, sigencode=sigencode_der)
425
426with open("data.sig2", "wb") as f:
427   f.write(new_signature)
428
429# openssl dgst -sha256 -verify vk.pem -signature data.sig2 data
430```
431
432Note: if compatibility with OpenSSL 1.0.0 or earlier is necessary, the
433`sigencode_string` and `sigdecode_string` from `ecdsa.util` can be used for
434respectively writing and reading the signatures.
435
436The keys also can be written in format that openssl can handle:
437
438```python
439from ecdsa import SigningKey, VerifyingKey
440
441with open("sk.pem") as f:
442    sk = SigningKey.from_pem(f.read())
443with open("sk.pem", "wb") as f:
444    f.write(sk.to_pem())
445
446with open("vk.pem") as f:
447    vk = VerifyingKey.from_pem(f.read())
448with open("vk.pem", "wb") as f:
449    f.write(vk.to_pem())
450```
451
452## Entropy
453
454Creating a signing key with `SigningKey.generate()` requires some form of
455entropy (as opposed to
456`from_secret_exponent`/`from_string`/`from_der`/`from_pem`,
457which are deterministic and do not require an entropy source). The default
458source is `os.urandom()`, but you can pass any other function that behaves
459like `os.urandom` as the `entropy=` argument to do something different. This
460may be useful in unit tests, where you want to achieve repeatable results. The
461`ecdsa.util.PRNG` utility is handy here: it takes a seed and produces a strong
462pseudo-random stream from it:
463
464```python
465from ecdsa.util import PRNG
466from ecdsa import SigningKey
467rng1 = PRNG(b"seed")
468sk1 = SigningKey.generate(entropy=rng1)
469rng2 = PRNG(b"seed")
470sk2 = SigningKey.generate(entropy=rng2)
471# sk1 and sk2 are the same key
472```
473
474Likewise, ECDSA signature generation requires a random number, and each
475signature must use a different one (using the same number twice will
476immediately reveal the private signing key). The `sk.sign()` method takes an
477`entropy=` argument which behaves the same as `SigningKey.generate(entropy=)`.
478
479## Deterministic Signatures
480
481If you call `SigningKey.sign_deterministic(data)` instead of `.sign(data)`,
482the code will generate a deterministic signature instead of a random one.
483This uses the algorithm from RFC6979 to safely generate a unique `k` value,
484derived from the private key and the message being signed. Each time you sign
485the same message with the same key, you will get the same signature (using
486the same `k`).
487
488This may become the default in a future version, as it is not vulnerable to
489failures of the entropy source.
490
491## Examples
492
493Create a NIST192p keypair and immediately save both to disk:
494
495```python
496from ecdsa import SigningKey
497sk = SigningKey.generate()
498vk = sk.verifying_key
499with open("private.pem", "wb") as f:
500    f.write(sk.to_pem())
501with open("public.pem", "wb") as f:
502    f.write(vk.to_pem())
503```
504
505Load a signing key from disk, use it to sign a message (using SHA-1), and write
506the signature to disk:
507
508```python
509from ecdsa import SigningKey
510with open("private.pem") as f:
511    sk = SigningKey.from_pem(f.read())
512with open("message", "rb") as f:
513    message = f.read()
514sig = sk.sign(message)
515with open("signature", "wb") as f:
516    f.write(sig)
517```
518
519Load the verifying key, message, and signature from disk, and verify the
520signature (assume SHA-1 hash):
521
522```python
523from ecdsa import VerifyingKey, BadSignatureError
524vk = VerifyingKey.from_pem(open("public.pem").read())
525with open("message", "rb") as f:
526    message = f.read()
527with open("signature", "rb") as f:
528    sig = f.read()
529try:
530    vk.verify(sig, message)
531    print "good signature"
532except BadSignatureError:
533    print "BAD SIGNATURE"
534```
535
536Create a NIST521p keypair:
537
538```python
539from ecdsa import SigningKey, NIST521p
540sk = SigningKey.generate(curve=NIST521p)
541vk = sk.verifying_key
542```
543
544Create three independent signing keys from a master seed:
545
546```python
547from ecdsa import NIST192p, SigningKey
548from ecdsa.util import randrange_from_seed__trytryagain
549
550def make_key_from_seed(seed, curve=NIST192p):
551    secexp = randrange_from_seed__trytryagain(seed, curve.order)
552    return SigningKey.from_secret_exponent(secexp, curve)
553
554sk1 = make_key_from_seed("1:%s" % seed)
555sk2 = make_key_from_seed("2:%s" % seed)
556sk3 = make_key_from_seed("3:%s" % seed)
557```
558
559Load a verifying key from disk and print it using hex encoding in
560uncompressed and compressed format (defined in X9.62 and SEC1 standards):
561
562```python
563from ecdsa import VerifyingKey
564
565with open("public.pem") as f:
566    vk = VerifyingKey.from_pem(f.read())
567
568print("uncompressed: {0}".format(vk.to_string("uncompressed").hex()))
569print("compressed: {0}".format(vk.to_string("compressed").hex()))
570```
571
572Load a verifying key from a hex string from compressed format, output
573uncompressed:
574
575```python
576from ecdsa import VerifyingKey, NIST256p
577
578comp_str = '022799c0d0ee09772fdd337d4f28dc155581951d07082fb19a38aa396b67e77759'
579vk = VerifyingKey.from_string(bytearray.fromhex(comp_str), curve=NIST256p)
580print(vk.to_string("uncompressed").hex())
581```
582
583ECDH key exchange with remote party
584
585```python
586from ecdsa import ECDH, NIST256p
587
588ecdh = ECDH(curve=NIST256p)
589ecdh.generate_private_key()
590local_public_key = ecdh.get_public_key()
591#send `local_public_key` to remote party and receive `remote_public_key` from remote party
592with open("remote_public_key.pem") as e:
593    remote_public_key = e.read()
594ecdh.load_received_public_key_pem(remote_public_key)
595secret = ecdh.generate_sharedsecret_bytes()
596```
597