# jesperborgstrup/Py-EC

Wrapper of the OpenSSL elliptic curve functions for easy Python manipulation
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
pyelliptic
.gitignore
__init__.py
asnhelper.py
bignum.py
curve.py
echelper.py
keypair.py
point.py
sample_lsag.py

# Py-EC

A wrapper of the OpenSSL elliptic curve functions for easy Python manipulation.

In Python, dealing directly with the OpenSSL library (through PyElliptic) easily becomes a hassle with the use of C pointers and string buffers.

To make things easier, I decided to make a wrapper for PyElliptic to make the manipulation of elliptic curves and points more Pythonic.

The wrapper has been tested with all recommended SEC curves (`secp192k1`, `secp192r1`, `secp224k1`, `secp224r1`, `secp256k1`, `secp256r1`, `secp384r1`, `secp521r1`, `sect163k1`, `sect163r1`, `sect163r2`, `sect233k1`, `sect233r1`, `sect239k1`, `sect283k1`, `sect283r1`, `sect409k1`, `sect409r1`, `sect571k1` and `sect571r1`).

Especially point addition and multiplication is way easier, as the following console example usage shows:

## Example use

``````>>> from curve import Curve
>>> c = Curve( 'secp256k1' )

>>> c
Curve<Equation: y^2 = x^3+7 (mod p), Field: Prime field, p: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F>

>>> c.p
115792089237316195423570985008687907853269984665640564039457584007908834671663L

>>> c.a
0

>>> c.b
7

>>> c.order
115792089237316195423570985008687907852837564279074904382605163141518161494337L

>>> c.G

>>> c.G.x
55066263022277343669578718895168534326250603453777594175500187360389116729240L

>>> c.G.y
32670510020758816978083085130507043184471273380659243275938904335757337482424L

>>> 4 * c.G + (255 * c.G)
Point<0xC2C80F844B70599812D625460F60340E3E6F36054A14546E6DC25D47376BEA9B, 0x86CA160D68F4D4E718B495B891D3B1B573B871A702B4CF6123ABD4483AA79C64>

>>> from keypair import KeyPair
>>> kp = KeyPair( c )

>>> kp

>>> kp.private_key
36442418189203456142546292588071998273845228785350611568921618467649899682927L

>>> kp.public_key
Point<0x13FCF42341462150B8366F11659E396DF88D19F65D533CEEAC78C9EC6F94B45D, 0x18DDDF6DCA0C097FC0359E680BAED36403D77657ABE7F76E64E1B787D90C485A>
``````

# API

## Curve

### Getting a curve instance

A curve can be initialized in three ways; by its name, id or by a pointer to an OpenSSL `EC_GROUP` instance:

``````>>> from curve import Curve

>>> Curve( curvename='secp256k1' )
Curve<Equation: y^2 = x^3+7 (mod p), Field: Prime field, p: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F>

>>> Curve( curveid=714 )
Curve<Equation: y^2 = x^3+7 (mod p), Field: Prime field, p: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F>

>>> from pyelliptic.openssl import OpenSSL
>>> Curve( openssl_group=OpenSSL.EC_GROUP_new_by_curve_name( 714 ) )
Curve<Equation: y^2 = x^3+7 (mod p), Field: Prime field, p: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F>
``````

### Properties of a curve

Depending on whether the curve is over a prime field, Fp, or a power-of-2 field, F2m, the curve has slightly different properties:

• `prime_type`: Either `'prime'` or `'power-of-two'`
• `G`: The base `Point` (or generator) of the curve.
• `order`: The order of the curve (amount of elements)
• `h`: The cofactor of the curve
• `a`: The curve coefficient a
• `b`: The curve coefficient b
• `p` (Only Fp): The prime p specifying the field
• `m` (Only F2m): The integer m specifying the field
• `poly_coeffs` (Only F2m): The degrees of the polynomials specifying the field
• `os_group`: A pointer to the underlying `EC_GROUP` instance.
``````>>> from curve import Curve
>>> c1 = Curve( 'secp256k1' )
>>> c2 = Curve( 'sect239k1' )

>>> c1
Curve<Equation: y^2 = x^3+7 (mod p), Field: Prime field, p: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F>
>>> c2
Curve<Equation: y^2+xy = x^3+1, Field: Power-of-two field, f(x): x^239+x^158+1>

>>> c1.field_type
'prime'
>>> c2.field_type
'power-of-two'

>>> c1.G
>>> c2.G
Point<0x29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC, 0x76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA>

>>> c1.order
115792089237316195423570985008687907852837564279074904382605163141518161494337L
>>> c1.h
1
>>> c1.a
0
>>> c1.b
7

>>> c1.p
115792089237316195423570985008687907853269984665640564039457584007908834671663L

>>> c2.m
239
>>> c2.poly_coeffs
[158]
``````

## Point

### Getting a point instance

You can get the base point from the `G` property of a curve as described above:

``````>>> from curve import Curve
>>> Curve( 'secp256k1' ).G
``````

You can also create a point on a curve from either (1) the x and y coordinates of the point or (2) by a pointer to an OpenSSL `EC_POINT` instance:

``````>>> from curve import Curve
>>> from point import Point
>>> c = Curve( 'secp256k1' )

>>> Point( c, x=255, y=255 ) # Invalid coordinates, only a demonstration
Point<0xFF, 0xFF>

>>> from pyelliptic.openssl import OpenSSL
>>> Point( c, openssl_point=OpenSSL.EC_POINT_new( c.os_group ) )
Point<0x0, 0x0>
``````

Finally, you can hash a string directly onto a curve (using the 'try-and-increment' method for finding points close to a certain x coordinate):

``````>>> from curve import Curve
>>> c = Curve( 'secp256k1' )

>>> c.hash_to_point( 'somestring' )

>>> c.hash_to_point( 'someotherstring' )
Point<0xB661EE62474532EF1C8EA78B1CE3634E2EEC06B8E256E46A5CE25DF0FFABF332, 0x1DAB745A01B745CA9BF276D8E990E8EF11CFA954C5956DF9BF4C0684FABB00A6>
``````

### Performing arithmetics

Point addition and multiplication is intuitive:

``````>>> from curve import Curve
>>> c = Curve( 'secp256k1' )

>>> c.G

>>> 2 * c.G
Point<0xC6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5, 0x1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A>

>>> c.G + c.G
Point<0xC6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5, 0x1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A>

>>> ( 5 * c.G ) + ( 256 * c.G )
``````

### Properties of a point

• `x`: The x coordinate
• `y`: The y coordinate
• `os_point`: A pointer to the underlying `EC_POINT` instance.

## Key pair

A key pair is a structure that contains a private and a public key for a given curve.

### Getting a key pair instance

A key pair for a curve can be generated randomly or by providing a private key:

``````>>> from curve import Curve
>>> from keypair import KeyPair
>>> c = Curve( 'secp256k1' )

>>> KeyPair( c ) # Random key pair
KeyPair<Private:0x94087552C3C72CC867E555854B9DD6392A611A40C168B0C6B7AEFC63DD9F5818, Public:Point<0x7C3FF4B9AE4D4EFCD22185F5ED7B6C8EF79CFF83AC0A3DFA4A258CDDBFC2AC3E, 0xEBFD9904CB8398524022BCDC268D6B03207737F35E7591EE5ACEE338D5272733>>

>>> KeyPair( c, private_key=12345 )
KeyPair<Private:0x3039, Public:Point<0xF01D6B9018AB421DD410404CB869072065522BF85734008F105CF385A023A80F, 0xEBA29D0F0C5408ED681984DC525982ABEFCCD9F7FF01DD26DA4999CF3F6A295>>
``````

Alternatively, you can provide a pointer to an OpenSSL `EC_KEY` instance:

``````>>> from curve import Curve
>>> from keypair import KeyPair
>>> from pyelliptic.openssl import OpenSSL
>>> c = Curve( 'secp256k1' )
>>> k = OpenSSL.EC_KEY_new_by_curve_name( 714 )
>>> OpenSSL.EC_KEY_generate_key( k )
1

>>> KeyPair( c, os_key=k )
KeyPair<Private:0xECBCB11DB69B0A8876986571E336A4F486E7B2C355712D2FA32C9836A153AAA, Public:Point<0x732F6911AC325F41CEAB478D4D5AE3EB033A06EA8ECC03AF58CF2FF022A1FE
5, 0x156B3C906BB70070B946F8565C425FEA00EA3350A71073F5B4818C96D41610C6>>
``````

### Properties of a key pair

• `private_key`: The private key (an integer)
• `public_key`: The public key (a `Point`)
• `os_key`: A pointer to the underlying `EC_KEY` instance.