Elliptic curve cryptography code in python

crypto

This repository covers both fundamentals of public key cryptography algorithms, tutorials and implementations. I've created this repository during the capture of the following online courses published on Udemy.

Elliptic Curve Cryptography Masterclass

Public Key Cryptography From Scratch In Python

Cryptography Basics From Scratch In Python

Public Key Cryptography From Scratch In Python

1- Diffie Hellman Key Exchange Algorithm Code

2- RSA for Encryption, Digital Signature and Key Exchange Code, Tutorial

3- El Gamal for Encryption and Digital Signature Code

4- Digital Signature Algorithm (DSA) Code

5- Discrete Logarighm Problem Code

Elliptic Curve Cryptography Masterclass In Python

1- Elliptic Curve Cryptography with Python Code, Tutorial, Video

This code covers key exchange, digital signature, symmetric encryption, order of group (number of points in finite field) and elliptic curve discrete logarithm problem. This is dependent to EccCore.py.

2- Edwards Curve Digital Signature Algorithm Code, Tutorial

Edwards curves offer faster calculations than regular elliptic curve forms.

3- Finding Bitcoin Address Code, Tutorial, Configuration

A bitcoin address consists of a public key.

4- Elliptic Curve ElGamal Code

Previously, we have implemented symmetric encryption but in that case we encrypt and decrypt a point on the curve. Now, we will transform a text message to a elliptic curve point and apply encryption. However, this is a de facto implementation because decryption requires to solve ECDLP.

Elliptic Curve Cryptography Masterclass In Java

1- Elliptic Curve Cryptography with Java Up-to-date Code, Legacy Code

This java project is dependent to entity objects.

Cryptography Basics From Scratch In Python

1- Caesar Cipher Code

2- Substitution Cipher Code

3- Affine Cipher Code

4- Homophonic Substitution Cipher Code

5- Permutation Cipher Code

6- Hill Cipher Code, Tutorial

7- Vigénere Cipher Code

8- Kasiski Examination Code

9- Enigma Machine Video

Support

There are many ways to support a project - starring the GitHub repos is one.

License

This repository is licensed under MIT license - see LICENSE for more details

# Basics of Elliptic Curve Cryptography import collections def inv(n, q): """div on PN modulo a/b mod q as a * inv(b, q) mod q >>> assert n * inv(n, q) % q == 1 """ for i in range(q): if (n * i) % q == 1: return i pass assert False, "unreached" pass def sqrt(n, q): """sqrt on PN modulo: it may not exist >>> assert (sqrt(n, q) ** 2) % q == n """ assert n < q for i in range(1, q): if i * i % q == n: return (i, q - i) pass raise Exception("not found") Coord = collections.namedtuple("Coord", ["x", "y"]) class EC(object): """System of Elliptic Curve""" def __init__(self, a, b, q): """elliptic curve as: (y**2 = x**3 + a * x + b) mod q - a, b: params of curve formula - q: prime number """ assert 0 < a and a < q and 0 < b and b < q and q > 2 assert (4 * (a ** 3) + 27 * (b ** 2)) % q != 0 self.a = a self.b = b self.q = q # just as unique ZERO value representation for "add": (not on curve) self.zero = Coord(0, 0) pass def is_valid(self, p): if p == self.zero: return True l = (p.y ** 2) % self.q r = ((p.x ** 3) + self.a * p.x + self.b) % self.q return l == r def at(self, x): """find points on curve at x - x: int < q - returns: ((x, y), (x,-y)) or not found exception >>> a, ma = ec.at(x) >>> assert a.x == ma.x and a.x == x >>> assert a.x == ma.x and a.x == x >>> assert ec.neg(a) == ma >>> assert ec.is_valid(a) and ec.is_valid(ma) """ assert x < self.q ysq = (x ** 3 + self.a * x + self.b) % self.q y, my = sqrt(ysq, self.q) return Coord(x, y), Coord(x, my) def neg(self, p): """negate p >>> assert ec.is_valid(ec.neg(p)) """ return Coord(p.x, -p.y % self.q) def add(self, p1, p2): """<add> of elliptic curve: negate of 3rd cross point of (p1,p2) line >>> c = ec.add(a, b) >>> assert ec.is_valid(a) >>> assert ec.add(c, ec.neg(b)) == a """ if p1 == self.zero: return p2 if p2 == self.zero: return p1 if p1.x == p2.x and p1.y != p2.y: # p1 + -p1 == 0 return self.zero if p1.x == p2.x: # p1 + p1: use tangent line of p1 as (p1,p1) line l = (3 * p1.x * p1.x + self.a) * inv(2 * p1.y, self.q) % self.q pass else: l = (p2.y - p1.y) * inv(p2.x - p1.x, self.q) % self.q pass x = (l * l - p1.x - p2.x) % self.q y = (l * (p1.x - x) - p1.y) % self.q return Coord(x, y) def mul(self, p, n): """n times <mul> of elliptic curve >>> m = ec.mul(n, p) >>> assert ec.is_valid(m) """ r = self.zero for i in range(n): r = self.add(r, p) pass return r pass class ElGamal(object): """El Gamal Encryption pub key encryption as replacing (mulmod, powmod) to (ec.add, ec.mul) """ def __init__(self, ec): self.ec = ec pass def gen(self, priv, pub1): """generate pub key - priv: priv key as (random) int < ec.q - pub1: (random) a point on ec - returns: pub key as (pub1, pub2) as points on ec """ assert self.ec.is_valid(pub1) return (pub1, self.ec.mul(pub1, priv)) def enc(self, plain, pub, r): """encrypt - plain: data as a point on ec - pub: pubkey as (pub1, pub2) as points on ec - r: randam int < ec.q - returns: (cipher1, ciper2) as points on ec """ assert self.ec.is_valid(plain) return (self.ec.mul(pub[0], r), self.ec.add(plain, self.ec.mul(pub[1], r))) def dec(self, cipher, priv): """decrypt - chiper: (chiper1, chiper2) as points on ec - priv: private key as int < ec.q - returns: plain as a point on ec """ return self.ec.add(cipher[1], self.ec.neg(self.ec.mul(cipher[0], priv))) pass class ECDH(object): """Elliptic Curve Diffie Hellman (Key Agreement) """ def __init__(self, ec, g): assert ec.is_valid(g) self.ec = ec pass def gen(self, priv): """generate pub key""" return self.ec.mul(self.g, priv) def secret(self, priv, pub): """calc secret key for the pair""" assert self.ec.is_valid(pub) return self.ec.mul(pub, priv) pass if __name__ == "__main__": # enc/dec usage ec = EC(1, 18, 19) eg = ElGamal(ec) priv = 5 pub1, _ = ec.at(7) plain, _ = ec.at(1) pub = eg.gen(priv, pub1) cipher = eg.enc(plain, pub, 15) decoded = eg.dec(cipher, priv) assert decoded == plain assert cipher != pub # ecdh usage g, _ = ec.at(7) # shared ecdh = ECDH(ec, g) apriv = 15 apub = ecdh.gen(apriv) bpriv = 3 bpub = ecdh.gen(bpriv) cpriv = 7 cpub = ecdh.gen(cpriv) # same secret on each pair assert ecdh.secret(apriv, bpub) == ecdh.secret(bpriv, apub) assert ecdh.secret(apriv, cpub) == ecdh.secret(cpriv, apub) assert ecdh.secret(bpriv, cpub) == ecdh.secret(cpriv, bpub) # not same secret on other pair assert ecdh.secret(apriv, cpub) != ecdh.secret(apriv, bpub) assert ecdh.secret(bpriv, apub) != ecdh.secret(bpriv, cpub) assert ecdh.secret(cpriv, bpub) != ecdh.secret(cpriv, apub) pass