Fast elliptic curve digital signatures
Project description
Contents
About
This is a python package for doing fast elliptic curve cryptography, specifically digital signatures.
Security
There is no nonce reuse, no branching on secret material, and all points are validated before any operations are performed on them. Timing side challenges are mitigated via Montgomery point multiplication. Nonces are generated per RFC6979. The default curve used throughout the package is P256 which provides 128 bits of security. If you require a higher level of security you can specify the curve parameter in a method to use a curve over a bigger field e.g. P384. All that being said, crypto is tricky and I’m not beyond making mistakes. Please use a more established and reviewed library for security critical applications. Open an issue or email me if you see any security issue or risk with this library.
Python Versions Supported
The initial release of this package was targeted at python2.7. Earlier versions may work but have no guarantee of correctness or stability. As of release 1.2.1+ python3 is supported as well. Due to python2’s EOL on January 1st 2020 release 2.x of this package only supports python3.5+.
Operating Systems Supported
This package is targeted at the Linux and MacOS operating systems. Due to the the dependency on the GMP C library building this package on Windows is difficult and no official support or distributions are provided for Windows OSes. See issue11 for what users have done to get things building.
Supported Primitives
Curves over Prime Fields
Name  Class  Proposed By 

P192 / secp192r1  fastecdsa.curve.P192 
NIST / NSA 
P224 / secp224r1  fastecdsa.curve.P224 
NIST / NSA 
P256 / secp256r1  fastecdsa.curve.P256 
NIST / NSA 
P384 / secp384r1  fastecdsa.curve.P384 
NIST / NSA 
P521 / secp521r1  fastecdsa.curve.P521 
NIST / NSA 
secp192k1  fastecdsa.curve.secp192k1 
Certicom 
secp224k1  fastecdsa.curve.secp224k1 
Certicom 
secp256k1 (bitcoin curve)  fastecdsa.curve.secp256k1 
Certicom 
brainpoolP160r1  fastecdsa.curve.brainpoolP160r1 
BSI 
brainpoolP192r1  fastecdsa.curve.brainpoolP192r1 
BSI 
brainpoolP224r1  fastecdsa.curve.brainpoolP224r1 
BSI 
brainpoolP256r1  fastecdsa.curve.brainpoolP256r1 
BSI 
brainpoolP320r1  fastecdsa.curve.brainpoolP320r1 
BSI 
brainpoolP384r1  fastecdsa.curve.brainpoolP384r1 
BSI 
brainpoolP512r1  fastecdsa.curve.brainpoolP512r1 
BSI 
Arbitrary Curves
As of version 1.5.1 construction of arbitrary curves in Weierstrass form
(y^2 = x^3 + ax + b (mod p)
) is supported. I advise against using custom curves for any
security critical applications. It’s up to you to make sure that the parameters you pass here are
correct, no validation of the base point is done, and in general no sanity checks are done. Use
at your own risk.
from fastecdsa.curve import Curve curve = Curve( name, # (str): The name of the curve p, # (long): The value of p in the curve equation. a, # (long): The value of a in the curve equation. b, # (long): The value of b in the curve equation. q, # (long): The order of the base point of the curve. gx, # (long): The x coordinate of the base point of the curve. gy, # (long): The y coordinate of the base point of the curve. oid # (str): The object identifier of the curve (optional). )
Hash Functions
Any hash function in the hashlib
module (md5, sha1, sha224, sha256, sha384, sha512
)
will work, as will any hash function that implements the same interface / core functionality as the
those in hashlib
. For instance, if you wish to use SHA3 as the hash function the
pysha3
package will work with this library as long as it is at version >=1.0b1 (as previous
versions didn’t work with the hmac
module which is used in nonce generation). Note
that sha3_224, sha3_256, sha3_384, sha3_512
are all in hashlib
as of python3.6.
Performance
Curves over Prime Fields
Currently it does elliptic curve arithmetic significantly faster than the ecdsa
package. You can see the times for 1,000 signature and verification operations over
various curves below. These were run on an early 2014 MacBook Air with a 1.4 GHz Intel
Core i5.
Curve  fastecdsa time 
ecdsa time 
Speedup 
P192  3.62s  1m35.49s  ~26x 
P224  4.50s  2m13.42s  ~29x 
P256  6.15s  2m52.43s  ~28x 
P384  12.11s  6m21.01s  ~31x 
P521  22.21s  11m39.53s  ~31x 
secp256k1  5.92s  2m57.19s  ~30x 
Benchmarking
If you’d like to benchmark performance on your machine you can do so using the command:
$ python setup.py benchmark
This will use the timeit
module to benchmark 1000 signature and verification operations
for each curve supported by this package. Alternatively, if you have not cloned the repo but
have installed the package via e.g. pip
you can use the following command:
$ python m fastecdsa.benchmark
Installing
You can use pip: $ pip install fastecdsa
or clone the repo and use
$ python setup.py install
. Note that you need to have a C compiler.
You also need to have GMP on your system as the underlying
C code in this package includes the gmp.h
header (and links against gmp
via the lgmp
flag). You can install all dependencies as follows:
apt
$ sudo aptget install pythondev libgmp3dev
yum
$ sudo yum install pythondevel gmpdevel
Usage
Generating Keys
You can use this package to generate keys if you like. Recall that private keys on elliptic curves are integers, and public keys are points i.e. integer pairs.
from fastecdsa import keys, curve """The reason there are two ways to generate a keypair is that generating the public key requires a point multiplication, which can be expensive. That means sometimes you may want to delay generating the public key until it is actually needed.""" # generate a keypair (i.e. both keys) for curve P256 priv_key, pub_key = keys.gen_keypair(curve.P256) # generate a private key for curve P256 priv_key = keys.gen_private_key(curve.P256) # get the public key corresponding to the private key we just generated pub_key = keys.get_public_key(priv_key, curve.P256)
Signing and Verifying
Some basic usage is shown below:
from fastecdsa import curve, ecdsa, keys from hashlib import sha384 m = "a message to sign via ECDSA" # some message ''' use default curve and hash function (P256 and SHA2) ''' private_key = keys.gen_private_key(curve.P256) public_key = keys.get_public_key(private_key, curve.P256) # standard signature, returns two integers r, s = ecdsa.sign(m, private_key) # should return True as the signature we just generated is valid. valid = ecdsa.verify((r, s), m, public_key) ''' specify a different hash function to use with ECDSA ''' r, s = ecdsa.sign(m, private_key, hashfunc=sha384) valid = ecdsa.verify((r, s), m, public_key, hashfunc=sha384) ''' specify a different curve to use with ECDSA ''' private_key = keys.gen_private_key(curve.P224) public_key = keys.get_public_key(private_key, curve.P224) r, s = ecdsa.sign(m, private_key, curve=curve.P224) valid = ecdsa.verify((r, s), m, public_key, curve=curve.P224) ''' using SHA3 via pysha3>=1.0b1 package ''' import sha3 # pip install [user] pysha3==1.0b1 from hashlib import sha3_256 private_key, public_key = keys.gen_keypair(curve.P256) r, s = ecdsa.sign(m, private_key, hashfunc=sha3_256) valid = ecdsa.verify((r, s), m, public_key, hashfunc=sha3_256)
Arbitrary Elliptic Curve Arithmetic
The Point
class allows arbitrary arithmetic to be performed over curves. The two main
operations are point addition and point multiplication (by a scalar) which can be done via the
standard python operators (+
and *
respectively):
# example taken from the document below (section 4.3.2): # https://koclab.cs.ucsb.edu/teaching/cren/docs/w02/nistroutines.pdf from fastecdsa.curve import P256 from fastecdsa.point import Point xs = 0xde2444bebc8d36e682edd27e0f271508617519b3221a8fa0b77cab3989da97c9 ys = 0xc093ae7ff36e5380fc01a5aad1e66659702de80f53cec576b6350b243042a256 S = Point(xs, ys, curve=P256) xt = 0x55a8b00f8da1d44e62f6b3b25316212e39540dc861c89575bb8cf92e35e0986b yt = 0x5421c3209c2d6c704835d82ac4c3dd90f61a8a52598b9e7ab656e9d8c8b24316 T = Point(xt, yt, curve=P256) # Point Addition R = S + T # Point Subtraction: (xs, ys)  (xt, yt) = (xs, ys) + (xt, yt) R = S  T # Point Doubling R = S + S # produces the same value as the operation below R = 2 * S # S * 2 works fine too i.e. order doesn't matter d = 0xc51e4753afdec1e6b6c6a5b992f43f8dd0c7a8933072708b6522468b2ffb06fd # Scalar Multiplication R = d * S # S * d works fine too i.e. order doesn't matter e = 0xd37f628ece72a462f0145cbefe3f0b355ee8332d37acdd83a358016aea029db7 # Joint Scalar Multiplication R = d * S + e * T
Importing and Exporting Keys
You can also export keys as files, ASN.1 encoded and formatted per RFC5480 and RFC5915. Both private keys and public keys can be exported as follows:
from fastecdsa.curve import P256 from fastecdsa.keys import export_key, gen_keypair d, Q = gen_keypair(P256) # save the private key to disk export_key(d, curve=P256, filepath='/path/to/exported/p256.key') # save the public key to disk export_key(Q, curve=P256, filepath='/path/to/exported/p256.pub')
Keys stored in this format can also be imported. The import function will figure out if the key is a public or private key and parse it accordingly:
from fastecdsa.keys import import_key # if the file is a private key then parsed_d is a long and parsed_Q is a Point object # if the file is a public key then parsed_d will be None parsed_d, parsed_Q = import_key('/path/to/file.key')
Other encoding formats can also be specified, such as SEC1 for public keys. This is done using
classes found in the fastecdsa.encoding
package, and passing them as keyword args to
the key functions:
from fastecdsa.curve import P256 from fastecdsa.encoding.sec1 import SEC1Encoder from fastecdsa.keys import export_key, gen_keypair, import_key _, Q = gen_keypair(P256) export_key(Q, curve=P256, filepath='/path/to/p256.key', encoder=SEC1Encoder) parsed_Q = import_key('/path/to/p256.key', curve=P256, public=True, decoder=SEC1Encoder)
Encoding Signatures
DER encoding of ECDSA signatures as defined in RFC2459 is also supported. The
fastecdsa.encoding.der
provides the DEREncoder
class which encodes signatures:
from fastecdsa.encoding.der import DEREncoder r, s = 0xdeadc0de, 0xbadc0de encoded = DEREncoder.encode_signature(r, s) decoded_r, decoded_s = DEREncoder.decode_signature(encoded)
Acknowledgements
Thanks to those below for contributing improvements:
 boneyard93501
 clouds56
 mkus
 sirk390
 targon
 NotStatilko
 bbbrumley
 luinxz
 JJChiDguez
 J08nY
 trevorcrypto
 sylvainpelissier
Project details
Release history Release notifications  RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Filename, size  File type  Python version  Upload date  Hashes 

Filename, size fastecdsa2.2.3.tar.gz (48.5 kB)  File type Source  Python version None  Upload date  Hashes View 
Filename, size fastecdsa2.2.3cp310cp310macosx_11_0_x86_64.whl (56.9 kB)  File type Wheel  Python version cp310  Upload date  Hashes View 
Filename, size fastecdsa2.2.3cp39cp39macosx_11_0_x86_64.whl (56.9 kB)  File type Wheel  Python version cp39  Upload date  Hashes View 
Filename, size fastecdsa2.2.3cp38cp38macosx_11_0_x86_64.whl (56.9 kB)  File type Wheel  Python version cp38  Upload date  Hashes View 
Filename, size fastecdsa2.2.3cp37cp37mmacosx_11_0_x86_64.whl (56.9 kB)  File type Wheel  Python version cp37  Upload date  Hashes View 
Filename, size fastecdsa2.2.3cp36cp36mmacosx_11_0_x86_64.whl (56.9 kB)  File type Wheel  Python version cp36  Upload date  Hashes View 
Hashes for fastecdsa2.2.3cp310cp310macosx_11_0_x86_64.whl
Algorithm  Hash digest  

SHA256  c1f27c5b37aee4bafa8ee304f6da3382ba90200a6998764b3cedba506ef03ff5 

MD5  012caf5678026fb2b82b72ced6a88b07 

BLAKE2256  ef137ceff8af2229ffd46f575e35a0e02696e79fd733c5bf5ce666ddc4ed64d0 
Hashes for fastecdsa2.2.3cp39cp39macosx_11_0_x86_64.whl
Algorithm  Hash digest  

SHA256  376af4d45ae82a2e9c25f0a0d9b50c7d63ba881e273ab69db184a0493c688619 

MD5  38a6ebf382b044ced9faa672ee2f0348 

BLAKE2256  7712599ddc1b42550f23370f41cd43fabb7a88a8ca10494d9130a9532bb14faf 
Hashes for fastecdsa2.2.3cp38cp38macosx_11_0_x86_64.whl
Algorithm  Hash digest  

SHA256  943aac1b35633a0ffea1bfe1509ec0fa35095a8021a85d3a5c323fe90e2a6038 

MD5  35ac5fa4a3c454de2a8d90cc9bb9872c 

BLAKE2256  551b2552e560eca9258623f35ff8d4170e2c6380a3f9006ff17ac1b8752597a2 
Hashes for fastecdsa2.2.3cp37cp37mmacosx_11_0_x86_64.whl
Algorithm  Hash digest  

SHA256  0cb1ecbd63a7898a616e1fe5bd5fe164b7a3db764a98886c6eafc226efc19477 

MD5  a95582a457d26fade35b326529bba5be 

BLAKE2256  5eedcde50be396125b040e312f79ff27d5100cc47d30b778b7bb4ddd311d3f99 
Hashes for fastecdsa2.2.3cp36cp36mmacosx_11_0_x86_64.whl
Algorithm  Hash digest  

SHA256  05676e917fea8d56f15a7f00c81560d9a6be83767435dca17cc2a62741276656 

MD5  a69d800bba3fd98e4e55eb6f666d9e14 

BLAKE2256  bb10d03ab823e590359eb70faee5b7267bac072f72a5c6eaa9e8b4131b4f1412 