Replacing the Rusty Core of the Internet with FP
OpenSSL Usage
* Does not include IMAP and other apps that also use OpenSSL
OpenSSL Coverage
OpenSSL Coverage
OpenSSL Vulnerabilities
NOPE
Agenda
Elliptic Curves
Laws and properties of Elliptic Curves
Discrete Logarithm Problem
Scala Implementation of Elliptic Curve
Elliptic Curve Cryptography
y^2 = x^3 + ax + b
y2=x3+ax+b
Point Addition
R = P + Q
R=P+Q
Commutative
P + Q = Q + P
P+Q=Q+P
Inverse
-Q + Q = O
−Q+Q=O
Associative
( P + Q ) + R = P + ( Q + R )
(P+Q)+R=P+(Q+R)
Identity
P + O = P
P+O=P
Point Multiplication
Point Multiplication
Point Multiplication
Point Multiplication
Elliptic Curve Diffie Hellman
Elliptic Curve Diffie Hellman
nP * m = mP * n
nP∗m=mP∗n
Shared Key:
Evaluated Mod Prime
Elliptic Point Multiplication
mul pt 0 = InfinityPoint
mul pt 1 = pt
mul pt n
| even n = mul (double pt) (n `div` 2)
| otherwise = add (mul (double pt) (n `div` 2)) pt
What's "large"?
115792089237316195423570985008687907853269984665640564039457584007908834671663
Atoms in Universe
10000000000000000000000000000000000000000000000000000000000000000000000000000000
Secp256k1 prime
Discrete Log Problem
Given a point \(Q\) which is a multiple of \(P\) find the \(n\) that was used to get to \(Q\)
$$nP = Q$$
Solve for n
For educational purposes only!
Finite Field
case class Fp private(i:BigInt) extends AnyVal
object Fp {
final val Prime = ??? //Huge prime, around 256 bits long
def create(i:BigInt): Fp = Fp(mod(i, Prime))
}
implicit val fieldForFp: Field[Fp] = new Field.WithDefaultGCD[Fp] {
def negate(x: Fp): Fp = create(-x.value)
val zero: Fp = create(0)
def plus(x: Fp, y: Fp): Fp = create(x.value + y.value)
def times(x: Fp, y: Fp): Fp = create(x.value * y.value)
def div(x: Fp, y: Fp): Fp = create(x.value * multInverse(y.value, Prime))
val one: Fp = create(1)
}
Finite Field
Points
sealed abstract class AffinePoint[+A]
case class APoint[A](x:A, y:A) extends AffinePoint[A]
case object Infinity extends AffinePoint[Nothing]
Points
sealed abstract class HomogeneousPoint[+A]
case class HPoint[A](x:A, y:A, z:A) extends HomogeneousPoint[A]
case object Infinity extends HomogeneousPoint[Nothing]
Point Add
def add[A: Field: Eq](p1: AffinePoint[A], p2: AffinePoint[A]) =
(p1,p2) match {
case (Infinity, p) => p
case (p, Infinity) => p
case (p1, p2) if p1 === p2 => double(p1)
case (APoint(_, y1), APoint(_, y2)) if (y1 == -y2) => Infinity
case (APoint(x1, y1), APoint(x2, y2)) =>
val m = (y1 - y2) * (Field[A].one / (x1 - x2))
val x3 = -x1 - x2 + (m.pow(2))
val y3 = -y1 + m * (x1 - x3)
APoint(x3, y3)
}
Point Double
def double[A: Field: Eq](p: AffinePoint[A]): AffinePoint[A] = p match {
case Infinity => Infinity
case APoint(_, y) if y === Field[A].zero => Infinity
case APoint(x, y) =>
val twoYInverse = Field[A].one / (y * 2)
val m = 3 * x.pow(2) * twoYInverse
val x2 = -2 * x + m.pow(2)
val y2 = -y + m * (x - x2)
APoint(x2, y2)
}
Point Times
def sumN[A: AdditiveMonoid](a: A, n: BigInt): A = {
@annotation.tailrec
def loop(a: A, k: BigInt, extra: A): A =
if (k == 1) a + extra else {
val x = if ((k & 1) == 1) a + extra else extra
loop(a + a, k >> 1, x)
}
if (n == 0) AdditiveMonoid[A].zero else if (n == 1) a else loop(a, n - 1, a)
}
Point Group
implicit def aGroup[A: Field: Eq] = new AdditiveCommutativeGroup[AffinePoint[A]] {
def plus(x: AffinePoint[A], y: AffinePoint[A]): AffinePoint[A] = add(x,y)
val zero: AffinePoint[A] = Infinity
def negate(p: AffinePoint[A]): AffinePoint[A] = p match {
case Infinity => Infinity
case APoint(x, y) => APoint(x, -y)
}
}
So what?
-
This is all just algebra. Nothing complex!
-
We can now test our points for any Field!
-
Parametricy ensures we're not doing crazy hacks.
-
Laws on fields and groups keep us safe.
-
Property based testing.
-
What about SPEED?!?
-
BigInt is slow
-
Radix 51 trick using CPU pipelining
-
Use real newtypes to save allocations
-
Abandon the JVM
-
Cryptonite in Haskell (using GMP)
-
What now?
- Don't be scared of Crypto.
- Don't invent your own algorithms.
- Choose implementations which are well tested.
- Old Crypto is not good Crypto.
Replacing the Rusty Core with FP
By Colt Frederickson
Replacing the Rusty Core with FP
- 1,928