Skip to content

Commit

Permalink
feat: implement bit and decodepoint
Browse files Browse the repository at this point in the history
  • Loading branch information
recanman committed Jun 2, 2024
1 parent a7b9059 commit a76b1ab
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 1 deletion.
32 changes: 32 additions & 0 deletions src/Ed25519.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ public function encodePoint(Point $P): string
return bin2hex($result);
}

/**
* Returns the bit at position i of the hash h.
*/
public function bit(string $h, BigInteger $i): int
{
return (ord($h[(int) $i->div(8)]) >> $i->mod(8)->toDec()) & 1;
}

/**
* Returns the decimal representation of the input's hash (SHA-512).
*/
Expand Down Expand Up @@ -242,6 +250,30 @@ public function decodeint(string $s): BigInteger
$result = new BigInteger(bin2hex($s), 16);
return new BigInteger($result->toDec());
}

/**
* Decodes a point on the Edwards25519 curve from a hexadecimal string.
*/
public function decodepoint(string $encoded): Point
{
// Convert to little-endian
$encoded = strrev(hex2bin($encoded));

$y = $this->decodeint($encoded);
$x = $this->xrecover($y);

if ($x->binaryAnd(new BigInteger("1"))->cmp($this->bit($encoded, $this->b->sub(1))) != 0) {
$x = $this->q->sub($x);
}

$P = new Point($x, $y);

if (!$this->isoncurve($P)) {
throw new Exception("Decoding point that is not on curve");
}

return $P;
}
// The code below is by the Monero-Integrations team

/**
Expand Down
20 changes: 19 additions & 1 deletion tests/unit/Ed25519Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class Ed25519Test extends TestCase
private $testHintInput = "100";
private $testHintOutput = "5249739319241077611146023738646316455244634195485061850472191081926985295157468499557719456094638265400023549952640721037286035956983479601959945106531843";

private $testEncodedB = "005866666666666666666666666666666666666666666666666666666666666666";
private $testEncodedB = "5866666666666666666666666666666666666666666666666666666666666666";
private $testBitInput = "fffffffffffffffffffffffffffffffX";

protected function setUp(): void
{
Expand Down Expand Up @@ -85,6 +86,15 @@ public function testEncodePoint(): void
$this->assertEquals($this->testEncodedB, $result);
}

public function testBit(): void
{
$result = $this->ed25519->bit($this->testBitInput, new BigInteger(255));
$this->assertEquals(0, $result);

$result = $this->ed25519->bit($this->testBitInput, new BigInteger(254));
$this->assertEquals(1, $result);
}

public function testHint(): void
{
$result = $this->ed25519->Hint(new BigInteger($this->testHintInput));
Expand All @@ -107,4 +117,12 @@ public function testDecodeInt(): void
$this->assertEquals('100', $point->toString());
}

public function testDecodePoint(): void
{
$point = $this->ed25519->decodepoint($this->testEncodedB);
$this->assertEquals($this->ed25519->B, $point);

$this->expectException(TypeError::class);
$point = $this->ed25519->decodepoint("invalid");
}
}

0 comments on commit a76b1ab

Please sign in to comment.