Skip to content

Instantly share code, notes, and snippets.

@devi
Last active August 29, 2015 14:00
Show Gist options
  • Select an option

  • Save devi/74cd70cc5582c5dcdc2f to your computer and use it in GitHub Desktop.

Select an option

Save devi/74cd70cc5582c5dcdc2f to your computer and use it in GitHub Desktop.
PHP port of cryptocat elliptic.js
<?php
/**
* Port of cryptocat elliptic.js
*
* https://github.com/cryptocat/cryptocat/blob/master/src/core/js/lib/elliptic.js
* commit: b4c87fb6ff20afb069d7ba951afaf9db5fd9c242
*/
class curve25519 {
// p25519 is the curve25519 prime: 2^255 - 19
private $p25519 = '57896044618658097711785492504343953926634992332820282019728792003956564819949';
// p25519Minus2 = 2^255 - 21
private $p25519Minus2 = '57896044618658097711785492504343953926634992332820282019728792003956564819947';
// p25519_a is a parameter of the elliptic curve
private $p25519_a = '486662';
// basePoint is the generator of the elliptic curve group
private $basePoint = '9';
// These variables are names for small, bigint constants
private $four = '4';
protected function gmp_mod2($n, $d) {
$res = gmp_div_r($n, $d);
if (gmp_cmp(0, $res) > 0) {
$res = gmp_add($d, $res);
}
return gmp_strval($res);
}
//return (x*y mod n) for bigInts x,y,n.
protected function multMod($x, $y, $n) {
return $this->gmp_mod2(gmp_mul($x, $y), $n);
}
//is x > y?
protected function greater($x, $y) {
return (gmp_cmp($x, $y) > 0);
}
// Gets a bit n, c
protected function getBit($x, $n) {
$i = floor($n / 15);
if ($i >= strlen($x)) {
return 0;
}
return ($x[$i] >> ($n % 15)) & 1;
}
// groupAdd adds two elements of the elliptic curve group in Montgomery form.
protected function groupAdd($x1, $xn, $zn, $xm, $zm) {
$xx = $this->multMod($xn, $xm, $this->p25519);
$zz = $this->multMod($zn, $zm, $this->p25519);
$d = null;
if ($this->greater($xx, $zz)) {
$d = gmp_sub($xx, $zz);
} else {
$d = gmp_sub($zz, $xx);
}
$sq = $this->multMod($d, $d, $this->p25519);
$outx = $this->multMod($sq, $this->four, $this->p25519);
$xz = $this->multMod($xm, $zn, $this->p25519);
$zx = $this->multMod($zm, $xn, $this->p25519);
if ($this->greater($xz, $zx)) {
$d = gmp_sub($xz, $zx);
} else {
$d = gmp_sub($zx, $xz);
}
$sq = $this->multMod($d, $d, $this->p25519);
$sq2 = $this->multMod($sq, $x1, $this->p25519);
$outz = $this->multMod($sq2, $this->four, $this->p25519);
return array($outx, $outz);
}
// groupDouble doubles a point in the elliptic curve group.
protected function groupDouble($x, $z) {
$xx = $this->multMod($x, $x, $this->p25519);
$zz = $this->multMod($z, $z, $this->p25519);
$d = null;
if ($this->greater($xx, $zz)) {
$d = gmp_sub($xx, $zz);
} else {
$d = gmp_sub($zz, $xx);
}
$outx = $this->multMod($d, $d, $this->p25519);
$s = gmp_add($xx, $zz);
$xz = $this->multMod($x, $z, $this->p25519);
$axz = gmp_mul($xz, $this->p25519_a);
$s = gmp_add($s, $axz);
$fourxz = gmp_mul($xz, $this->four);
$outz = $this->multMod($fourxz, $s, $this->p25519);
return array($outx, $outz);
}
// scalarMult calculates i*base in the elliptic curve.
public function scalarMult($scalar, $base) {
$x1 = '1';
$z1 = '0';
$x2 = $base;
$z2 = '1';
$point = $this->groupAdd($base, $x1, $z1, $x2, $z2);
$x1 = $point[0];
$z1 = $point[1];
$point = $this->groupDouble($x2, $z2);
$x2 = $point[0];
$z2 = $point[1];
for ($i = 253; $i >= 3; $i--) {
if ($this->getBit($scalar, $i)) {
$point = $this->groupAdd($base, $x1, $z1, $x2, $z2);
$x1 = $point[0];
$z1 = $point[1];
$point = $this->groupDouble($x2, $z2);
$x2 = $point[0];
$z2 = $point[1];
} else {
$point = $this->groupAdd($base, $x1, $z1, $x2, $z2);
$x2 = $point[0];
$z2 = $point[1];
$point = $this->groupDouble($x1, $z1);
$x1 = $point[0];
$z1 = $point[1];
}
}
for ($i = 2; $i >= 0; $i--) {
$point = $this->groupDouble($x1, $z1);
$x1 = $point[0];
$z1 = $point[1];
}
$z1inv = gmp_powm($z1, $this->p25519Minus2, $this->p25519);
$x = $this->multMod($z1inv, $x1, $this->p25519);
return $x;
}
public function scalarBaseMult($priv) {
return $this->scalarMult($priv, $this->basePoint);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment