Welcome to ECPy’s documentation!¶
Status¶
Version: | 0.8 |
---|---|
Authors: | Cedric Mesnil, <cedric.mesnil@ubinity.com> |
License: | Apache 2.0 |
Install¶
ECPy is originally coded for Python 3, but run under python 2.7 (and maybe 2.6) by using future. If you run Python 2, please install the future into the present:
pip install future
Then install ECPy:
- Rebuild from git clone:
- python3 setup.py sdist
- cd dist
- tar xzvf ECPy-M.m.tar.gz
- python3 setup install
- Install from dist package:
- Download last dist tarball
- tar xzvf ECPy-M.m.tar.gz
- python3 setup.py install
Overview¶
ECPy (pronounced ekpy), is a pure python Elliptic Curve library. It provides ECDSA, EDDSA, ECSchnorr signature as well as Point operation.
ECDSA sample
from ecpy.curves import Curve,Point
from ecpy.keys import ECPublicKey, ECPrivateKey
from ecpy.ecdsa import ECDSA
cv = Curve.get_curve('secp256k1')
pu_key = ECPublicKey(Point(0x65d5b8bf9ab1801c9f168d4815994ad35f1dcb6ae6c7a1a303966b677b813b00,
0xe6b865e529b8ecbf71cf966e900477d49ced5846d7662dd2dd11ccd55c0aff7f,
cv))
pv_key = ECPrivateKey(0xfb26a4e75eec75544c0f44e937dcf5ee6355c7176600b9688c667e5c283b43c5,
cv)
signer = ECDSA()
sig = signer.sign(b'01234567890123456789012345678912',pv_key)
assert(signer.verify(b'01234567890123456789012345678912',sig,pu_key))
Point sample
from ecpy.curves import Curve,Point
cv = Curve.get_curve('secp256k1')
P = Point(0x65d5b8bf9ab1801c9f168d4815994ad35f1dcb6ae6c7a1a303966b677b813b00,
0xe6b865e529b8ecbf71cf966e900477d49ced5846d7662dd2dd11ccd55c0aff7f,
cv)
k = 0xfb26a4e75eec75544c0f44e937dcf5ee6355c7176600b9688c667e5c283b43c5
Q = k*P
R = P+Q
Supported Curves & Signature¶
- ECPy support the following curves
- Short Weierstrass form: y²=x³+a*x+b
- Twisted Edward a*x²+y2=1+d*x²*y²
See pyec.Curve. get_curve_names
ECPy supports the following
Types¶
ECPY use binary bytes and int as primary types.
Other main types are Point
, Curve
, Key
, ECDSA
, EDDSA
, ECSchnorr
. Borromean
.
See API details...
API¶
curves module¶
Elliptic Curve and Point manipulation
-
class
ecpy.curves.
Curve
(parameters)[source]¶ Bases:
object
Elliptic Curve abstraction
You should not directly create such Object. Use get_curve to get the predefined curve or create a well-know type of curve with your parameters
- Supported well know elliptic curve are:
- Short Weierstrass form: y²=x³+a*x+b
- Twisted Edward a*x²+y2=1+d*x²*y²
-
name
¶ str
curve name, the one given to get_curve or return by get_curve_names
-
size
¶ int
bit size of curve
-
a
¶ int
first curve parameter
-
b d
int
second curve parameter
-
field
¶ int
curve field
-
generator
¶ Point
curve point generator
-
order
¶ int
order of generator
-
add_point
(P, Q)[source]¶ Returns the sum of P and Q
This function ignores the default curve attach to P and Q, and assumes P and Q are on this curve.
Parameters: Returns: A new Point R = P+Q
Return type: Raises: ECPyException
– with “Point not on curve”, if Point R is not on curve, thus meaning either P or Q was not on.
-
static
get_curve
(name)[source]¶ Return a Curve object according to its name
Parameters: name (str) – curve name to retrieve Returns: Curve object Return type: Curve
-
static
get_curve_names
()[source]¶ Returns all known curve names
Returns: list of names as str Return type: tuple
-
is_on_curve
(P)[source]¶ Check if P is on this curve
This function ignores the default curve attach to P
Parameters: P (Point) – Point to check Returns: True if P is on curve, False else Return type: bool
-
mul_point
(k, P)[source]¶ Returns the scalar multiplication P with k.
This function ignores the default curve attach to P and Q, and assumes P and Q are on this curve.
Parameters: Returns: A new Point R = k*Q
Return type: Raises: ECPyException
– with “Point not on curve”, if Point R is not- on curve, thus meaning P was not on.
-
sub_point
(P, Q)[source]¶ Returns the difference of P and Q
This function ignores the default curve attach to P and Q, and assumes P and Q are on this curve.
Parameters: Returns: A new Point R = P-Q
Return type: Raises: ECPyException
– with “Point not on curve”, if Point R is not on curve, thus meaning either P or Q was not on.
-
class
ecpy.curves.
Point
(x, y, curve, check=True)[source]¶ Bases:
object
Immutable Elliptic Curve Point.
A Point support the following operator:
- + : Point Addition, with automatic doubling support.
- * : Scalar multiplication, can write as k*P or P*k, with P :class:Point and k :class:int
- ==: Point comparison
-
x
¶ int
Affine x coordinate
-
y
¶ int
Affine y coordinate
-
curve
¶ Curve
Curve on which the point is define
Parameters: Raises: ECPyException
– if check=True and x,y is not on curve
-
class
ecpy.curves.
TwistedEdwardCurve
(domain)[source]¶ Bases:
ecpy.curves.Curve
An elliptic curve defined by the equation: a*x²+y²=1+d*x²*y²
- The given domain must be a dictionary providing the following keys/values:
- name (str) : curve unique name
- size (int) : bit size
- a (int) : a equation coefficient
- d (int) : b equation coefficient
- field (inf) : field value
- generator (int[2]) : x,y coordinate of generator
- order (int) : order of generator
Parameters: domain (dict) – a dictionary providing curve domain parameters -
decode_point
(eP)[source]¶ Decodes a point P according to draft_irtf-cfrg-eddsa-04.
Parameters: - eP (bytes) – encoded point
- curve (Curve) – curve on witch point is
- Returns
- Point : decoded point
-
encode_point
(P)[source]¶ Encodes a point P according to draft_irtf-cfrg-eddsa-04.
Parameters: P – point to encode - Returns
- bytes : encoded point
-
class
ecpy.curves.
WeierstrassCurve
(domain)[source]¶ Bases:
ecpy.curves.Curve
An elliptic curve defined by the equation: y²=x³+a*x+b.
- The given domain must be a dictionary providing the following keys/values:
- name (str) : curve unique name
- size (int) : bit size
- a (int) : a equation coefficient
- b (int) : b equation coefficient
- field (inf) : field value
- generator (int[2]) : x,y coordinate of generator
- order (int) : order of generator
- cofactor (int) : cofactor
Parameters: domain (dict) – a dictionary providing curve parameters
keys module¶
-
class
ecpy.keys.
ECPrivateKey
(d, curve)[source]¶ Bases:
object
Public EC key.
Can be used for both ECDSA and EDDSA signature
- Attributes
- d (int) : private key scalar curve (Curve) : curve
Parameters: -
get_public_key
()[source]¶ Returns the public key corresponding to this private key
Returns: public key Return type: ECPublicKey
ECDSA module¶
-
class
ecpy.ecdsa.
ECDSA
(fmt='DER')[source]¶ Bases:
object
ECDSA signer.
Parameters: fmt (str) – in/out signature format. See ecpy.formatters
-
sign
(msg, pv_key)[source]¶ Signs a message hash.
Parameters: - msg (bytes) – the message hash to sign
- pv_key (ecpy.keys.ECPrivateKey) – key to use for signing
-
sign_k
(msg, pv_key, k)[source]¶ Signs a message hash with provided random
Parameters: - msg (bytes) – the hash of message to sign
- pv_key (ecpy.keys.ECPrivateKey) – key to use for signing
- k (ecpy.keys.ECPrivateKey) – random to use for signing
-
sign_rfc6979
(msg, pv_key, hasher)[source]¶ Signs a message hash according to RFC6979
Parameters: - msg (bytes) – the message hash to sign
- pv_key (ecpy.keys.ECPrivateKey) – key to use for signing
- hasher (hashlib) – hasher conform to hashlib interface
-
verify
(msg, sig, pu_key)[source]¶ Verifies a message signature.
Parameters: - msg (bytes) – the message hash to verify the signature
- sig (bytes) – signature to verify
- pu_key (ecpy.keys.ECPublicKey) – key to use for verifying
-
EDDSA module¶
-
class
ecpy.eddsa.
EDDSA
(hasher, fmt='EDDSA')[source]¶ Bases:
object
EDDSA signer implemenation according to:
- IETF draft-irtf-cfrg-eddsa-05.
Parameters: - hasher (hashlib) – callable constructor returning an object with update(), digest() interface. Example: hashlib.sha256, hashlib.sha512...
- fmt (str) – in/out signature format. See
ecpy.formatters
.
-
sign
(msg, pv_key)[source]¶ Signs a message.
Parameters: - msg (bytes) – the message to sign
- pv_key (ecpy.keys.ECPrivateKey) – key to use for signing
-
verify
(msg, sig, pu_key)[source]¶ Verifies a message signature.
Parameters: - msg (bytes) – the message to verify the signature
- sig (bytes) – signature to verify
- pu_key (ecpy.keys.ECPublicKey) – key to use for verifying
ECSchnorr module¶
-
class
ecpy.ecschnorr.
ECSchnorr
(hasher, option='ISO', fmt='DER')[source]¶ Bases:
object
ECSchnorr signer implementation according to:
In order to select the specification to be conform to, choose the corresponding string option: “BSI”, “ISO”, “ISOx”, “LIBSECP”
Signature:
- “BSI”: compute r,s according to to BSI :
- k = RNG(1:n-1)
- Q = [k]G
- r = H(M ||Qx) If r = 0 mod n, goto 1.
- s = k - r.d mod n If s = 0 goto 1.
- Output (r, s)
- “ISO”: compute r,s according to ISO :
- k = RNG(1:n-1)
- Q = [k]G If r = 0 mod n, goto 1.
- r = H(Qx||Qy||M).
- s = (k + r.d) mod n If s = 0 goto 1.
- Output (r, s)
- “ISOx”: compute r,s according to optimized ISO variant:
- k = RNG(1:n-1)
- Q = [k]G If r = 0 mod n, goto 1.
- r = H(Qx||Qy||M).
- s = (k + r.d) mod n If s = 0 goto 1.
- Output (r, s)
- “LIBSECP”: compute r,s according to bitcoin lib:
- k = RNG(1:n-1)
- Q = [k]G if Qy is odd, negate k and goto 2
- r = Qx % n
- h = H(r || m). if h == 0 or h >= order goto 1
- s = k - h.d.
- Output (r, s)
Verification
- “BSI”: verify r,s according to to BSI :
- Verify that r in {0, . . . , 2**t - 1} and s in {1, 2, . . . , n - 1}. If the check fails, output False and terminate.
- Q = [s]G + [r]W If Q = 0, output Error and terminate.
- v = H(M||Qx)
- Output True if v = r, and False otherwise.
- “ISO”: verify r,s according to ISO :
- check...
- Q = [s]G - [r]W If Q = 0, output Error and terminate.
- v = H(Qx||Qy||M).
- Output True if v = r, and False otherwise.
- “ISOx”: verify r,s according to optimized ISO variant:
- check...
- Q = [s]G - [r]W If Q = 0, output Error and terminate.
- v = H(Qx||M).
- Output True if v = r, and False otherwise.
- “LIBSECP”:
- Signature is invalid if s >= order. Signature is invalid if r >= p.
- h = H(r || m). Signature is invalid if h == 0 or h >= order.
- R = [h]Q + [s]G. Signature is invalid if R is infinity or R’s y coordinate is odd.
- Signature is valid if the serialization of R’s x coordinate equals r.
Default is “ISO”
Parameters: - hasher (hashlib) – callable constructor returning an object with update(), digest() interface. Example: hashlib.sha256, hashlib.sha512...
- option (str) – one of “BSI”,”ISO”,”ISOx”,”LIBSECP”
- fmt (str) – in/out signature format. See
ecpy.formatters
-
sign
(msg, pv_key)[source]¶ Signs a message hash.
Parameters: - hash_msg (bytes) – the message hash to sign
- pv_key (ecpy.keys.ECPrivateKey) – key to use for signing
-
sign_k
(msg, pv_key, k)[source]¶ Signs a message hash with provided random
Parameters: - hash_msg (bytes) – the message hash to sign
- pv_key (ecpy.keys.ECPrivateKey) – key to use for signing
- k (ecpy.keys.ECPrivateKey) – random to use for signing
-
verify
(msg, sig, pu_key)[source]¶ Verifies a message signature.
Parameters: - msg (bytes) – the message hash to verify the signature
- sig (bytes) – signature to verify
- pu_key (ecpy.keys.ECPublicKey) – key to use for verifying
Borromean module¶
-
class
ecpy.borromean.
Borromean
(fmt='BTUPLE')[source]¶ Bases:
object
Borromean Ring signer implementation according to:
https://github.com/Blockstream/borromean_paper/blob/master/borromean_draft_0.01_9ade1e49.pdf
ElementsProject implementation has some tweaks compared to PDF. This implementation is ElementsProject compliant.
For now, only secp256k1+sha256 is supported. This constraint will be release soon.
Parameters: fmt (str) – in/out signature format. See ecpy.formatters
. IGNORED.-
sign
(msg, rings, pv_keys, pv_keys_index)[source]¶ Signs a message hash.
The public rings argument is a tuple of public key array. In other words each element of the ring tuple is an array containing the public keys list of that ring
A Private key must be given for each provided ring. For each private key, the corresponding public key is specified by its index in the ring.
- Exemple:
let r1 be the first ring with 2 keys: pu11, pu12 let 21 be the second ring with 3 keys: pu21,pu22,pu23 let say we want to produce a signature with sec12 and sec21 sign should be called as:
borromean.sign(m, ([pu11,pu12],[pu21,pu22,pu23]), [sec12, sec21], [1,0])
The return value is a tuple (e0, [s0,s1....]). Each value is encoded as binary (bytes).
Parameters: - msg (bytes) – the message hash to sign
- rings (tuple of (ecpy.keys.ECPublicKey[]) – public key rings
- pv_keys (ecpy.keys.ECPrivateKey[]) – key to use for signing
- pv_keys_index (int[]) –
Returns: signature
Return type: (e0, [s0,s1....])
-
ecrand module¶
-
ecpy.ecrand.
rnd
(q)[source]¶ Returns a random number less than q, with the same bits length than q
Parameters: q (int) – field/modulo Returns: random Return type: int
-
ecpy.ecrand.
rnd_rfc6979
(hashmsg, secret, q, hasher, V=None)[source]¶ Generates a deterministic value according to RF6979.
See https://tools.ietf.org/html/rfc6979#section-3.2
if V == None, this is the first try, so compute the initial value for V. Else it means the previous value has been rejected by the caller, so generate the next one!
Warning: the hashmsg parameter is the message hash, not the message itself. In other words, hashmsg is equal to h1 in the rfc6979, section-3.2, step a.
Parameters: The function returns a couple (k,V) with k the expected value and V is the continuation value to pass to next cal if k is rejected.
Returns: (k,V) Return type: tuple
formatters module¶
-
ecpy.formatters.
decode_sig
(sig, fmt='DER')[source]¶ encore signature according format
Parameters: - rs (bytes,ints,tuple) – r,s value
- fmt (str) – ‘DER’|’BTUPLE’|’ITUPLES’|’RAW’|’EDDSA
Returns: (r,s)
Return type: ints
-
ecpy.formatters.
encode_sig
(r, s, fmt='DER', size=0)[source]¶ encore signature according format
Parameters: Returns: TLV for DER encoding
Return type: bytes
Returns: (r,s) for BTUPLE encoding
Return type: bytes
Returns: (r,s) for ITUPLE encoding
Return type: ints
Returns: r|s for RAW encoding
Return type: bytes