/** * @param GeneratorPoint $G * @param $hash * @return int|string */ public function truncateHash(GeneratorPoint $G, $hash) { $hexSize = strlen($this->adapter->decHex($hash)); $hashBits = $this->adapter->baseConvert($hash, 10, 2); if (strlen($hashBits) < $hexSize * 4) { $hashBits = str_pad($hashBits, $hexSize * 4, '0', STR_PAD_LEFT); } $messageHash = $this->adapter->baseConvert(substr($hashBits, 0, NumberSize::bnNumBits($this->adapter, $G->getOrder())), 2, 10); return $messageHash; }
/** * Returns the number of bits used to store this number. Non-singicant upper bits are not counted. * * @param MathAdapterInterface $adapter * @param int|string $x * @return number * * @link https://www.openssl.org/docs/crypto/BN_num_bytes.html */ public static function bnNumBits(MathAdapterInterface $adapter, $x) { if ($adapter->cmp($x, '0') == 0) { return 0; } $log2 = 0; while ($x = $adapter->rightShift($x, 1)) { $log2++; } return $log2 + 1; }
/** * @param MathAdapterInterface $math * @param NamedCurveFp $c * @return Sequence */ private function getCurveAsn(MathAdapterInterface $math, NamedCurveFp $c) { $a = new OctetString($math->decHex($math->mod($c->getA(), $c->getPrime()))); $b = new OctetString($math->decHex($math->mod($c->getB(), $c->getPrime()))); try { $seed = CurveRandomSeed::getSeed($c); return new Sequence($a, $b, new BitString($seed)); } catch (\Exception $e) { return new Sequence($a, $b); } }
/** * @param CurveFpInterface $curve * @param string $data * @return PointInterface */ public function unserialize(CurveFpInterface $curve, $data) { if (substr($data, 0, 2) != '04') { throw new \InvalidArgumentException('Invalid data: only uncompressed keys are supported.'); } $data = substr($data, 2); $dataLength = strlen($data); $x = $this->adapter->hexDec(substr($data, 0, $dataLength / 2)); $y = $this->adapter->hexDec(substr($data, $dataLength / 2)); return $curve->getPoint($x, $y); }
/** * Parse $bytes bytes from the string, and return the obtained buffer * * @param integer $bytes * @param bool $flipBytes * @return Buffer * @throws \Exception */ public function readBytes($bytes, $flipBytes = false) { $string = substr($this->string, $this->getPosition(), $bytes); $length = strlen($string); if ($length == 0) { throw new ParserOutOfRange('Could not parse string of required length (empty)'); } elseif ($this->math->cmp($length, $bytes) !== 0) { throw new ParserOutOfRange('Could not parse string of required length (too short)'); } $this->position += $bytes; if ($flipBytes) { $string = Buffertools::flipBytes($string); } return new Buffer($string, $length, $this->math); }
/** * {@inheritDoc} * @see \Mdanter\Ecc\PointInterface::__toString() */ public function __toString() { if ($this->infinity) { return '[ (infinity) on ' . (string) $this->curve . ' ]'; } return "[ (" . $this->adapter->toString($this->x) . "," . $this->adapter->toString($this->y) . ') on ' . (string) $this->curve . ' ]'; }
/** * @param string $data * {@inheritDoc} * @see \Mdanter\Ecc\Serializer\PrivateKeySerializerInterface::parse() * @throws \FG\ASN1\Exception\ParserException */ public function parse($data) { $asnObject = Object::fromBinary($data); if (!$asnObject instanceof Sequence || $asnObject->getNumberofChildren() !== 4) { throw new \RuntimeException('Invalid data.'); } $children = $asnObject->getChildren(); $version = $children[0]; if ($version->getContent() != 1) { throw new \RuntimeException('Invalid data: only version 1 (RFC5915) keys are supported.'); } $key = $this->adapter->hexDec($children[1]->getContent()); $oid = $children[2]->getContent(); $generator = CurveOidMapper::getGeneratorFromOid($oid); return $generator->getPrivateKeyFrom($key); }
/** * @dataProvider getDeterministicSign2Data */ public function testDeterministicSign2($curve, $size, $algo, $privKey, $message, $eK, $eR, $eS) { //echo "Try {$test->curve} / {$test->algorithm} / '{$test->message}'\n"; $G = CurveFactory::getGeneratorByName($curve); // Initialize private key and message hash (decimal) $privateKey = $G->getPrivateKeyFrom($this->math->hexDec($privKey)); $hashHex = hash($algo, $message); $messageHash = $this->math->hexDec($hashHex); // Derive K $drbg = RandomGeneratorFactory::getHmacRandomGenerator($privateKey, $messageHash, $algo); $k = $drbg->generate($G->getOrder()); $this->assertEquals($this->math->hexdec($eK), $k, 'k'); $hexSize = strlen($hashHex); $hashBits = $this->math->baseConvert($messageHash, 10, 2); if (strlen($hashBits) < $hexSize * 4) { $hashBits = str_pad($hashBits, $hexSize * 4, '0', STR_PAD_LEFT); } $messageHash = $this->math->baseConvert(substr($hashBits, 0, $size), 2, 10); $signer = new Signer($this->math); $sig = $signer->sign($privateKey, $messageHash, $k); // R and S should be correct $sR = $this->math->hexDec($eR); $sS = $this->math->hexDec($eS); $this->assertTrue($signer->verify($privateKey->getPublicKey(), $sig, $messageHash)); $this->assertSame($sR, $sig->getR(), 'r'); $this->assertSame($sS, $sig->getS(), 's'); }
/** * Initialize a new instance. * * @param MathAdapterInterface $adapter * @param GeneratorPoint $generator * @param PointInterface $point * @throws \LogicException * @throws \RuntimeException */ public function __construct(MathAdapterInterface $adapter, GeneratorPoint $generator, PointInterface $point) { $this->curve = $generator->getCurve(); $this->generator = $generator; $this->point = $point; $this->adapter = $adapter; $n = $generator->getOrder(); if ($n == null) { throw new \LogicException("Generator must have order."); } if (!$point->mul($n)->isInfinity()) { throw new \RuntimeException("Generator point order is bad."); } if ($adapter->cmp($point->getX(), 0) < 0 || $adapter->cmp($n, $point->getX()) <= 0 || $adapter->cmp($point->getY(), 0) < 0 || $adapter->cmp($n, $point->getY()) <= 0) { throw new \RuntimeException("Generator point has x and y out of range."); } }
/** * @test * * @uses Lcobucci\JWT\Signer\Ecdsa::__construct * @uses Lcobucci\JWT\Signer\Key * * @covers Lcobucci\JWT\Signer\Ecdsa::doVerify * @covers Lcobucci\JWT\Signer\Ecdsa::createSigningHash * @covers Lcobucci\JWT\Signer\Ecdsa::extractSignature */ public function doVerifyShouldDelegateToEcdsaSignerUsingPublicKey() { $signer = $this->getSigner(); $key = new Key('testing'); $publicKey = $this->getMock(PublicKeyInterface::class); $this->parser->expects($this->once())->method('getPublicKey')->with($key)->willReturn($publicKey); $this->adapter->expects($this->exactly(3))->method('hexDec')->willReturn('123'); $this->signer->expects($this->once())->method('verify')->with($publicKey, $this->isInstanceOf(Signature::class), $this->isType('string'))->willReturn(true); $this->assertTrue($signer->doVerify('testing', 'testing2', $key)); }
/** * {@inheritDoc} * @see \Mdanter\Ecc\EcMathInterface::cmp() */ public function cmp($input) { $type = $this->identify($input); if ($this->dataType == 'point' && $type == 'point') { return $this->data->cmp($input); } if ($this->dataType == 'int' && $type == 'int') { return $this->math->cmp($this->data, $input); } throw new \LogicException('Cannot compare values of different types'); }
/** * @dataProvider getB24Params * @testdox Test 192-bit generated curve points against ECDSAVS section B2.4 samples */ public function testP192CurveEcdsavsB24SignatureValidityTest(MathAdapterInterface $math, $msg, $Qx, $Qy, $R, $S, $expected) { $msg = $math->hexDec($msg); $Qx = $math->hexDec($Qx); $Qy = $math->hexDec($Qy); $R = $math->hexDec($R); $S = $math->hexDec($S); $generator = EccFactory::getNistCurves($math)->generator192(); $publicKey = $generator->getPublicKeyFrom($Qx, $Qy); $signer = new Signer($math); $actual = $signer->verify($publicKey, new Signature($R, $S), $math->digestInteger($msg)); $this->assertEquals($expected, $actual); }
/** * Extracts R and S values from given data * * @param string $value * * @return \Mdanter\Ecc\Crypto\Signature\Signature */ private function extractSignature($value) { $length = $this->getSignatureLength(); $value = unpack('H*', $value)[1]; return new Signature($this->adapter->hexDec(substr($value, 0, $length)), $this->adapter->hexDec(substr($value, $length))); }
/** * @param bool $hex * @return int|string */ public function getHash($hex = false) { $hash = hash($this->algo, $this->content, false); return $hex ? $hash : $this->adapter->hexDec($hash); }
/** * @return int|string */ public function getInt() { return $this->math->hexDec($this->getHex()); }
/** * @dataProvider getAdapters */ public function testModFunction(MathAdapterInterface $math) { // $o->compressed, $o->decompressed public key. // Check that we can compress a key properly (tests $math->mod()) foreach ($this->compression_data as $o) { $prefix = substr($o->decompressed, 0, 2); // will be 04. $this->assertEquals('04', $prefix); // hex encoded (X,Y) coordinate of ECDSA public key. $x = substr($o->decompressed, 2, 64); $y = substr($o->decompressed, 66, 64); // y % 2 == 0 - true: y is even(02) / false: y is odd(03) $mod = $math->mod($math->hexDec($y), 2); $compressed = '0' . ($mod == 0 ? '2' : '3') . $x; // Check that the mod function reported the parity for the y value. $this->assertTrue($compressed === $o->compressed); } }
/** * Hash the data, returning a decimal. * * @param $string - a binary string to hash * @return int|string */ public function hashDec($string) { $hex = $this->hash($string, false); return $this->math->hexDec($hex); }
/** * @dataProvider getIntegers */ public function testDigestInteger(MathAdapterInterface $math, $integer, $result) { $this->assertEquals($result, $math->digestInteger($integer)); }
/** * * @dataProvider getMultAdapters */ public function testMultiply2(MathAdapterInterface $math, $p, $a, $b, $x, $y, $m, $ex, $ey) { $c = new CurveFp($p, $a, $b, $math); $p1 = $c->getPoint($x, $y); $p3 = $p1->mul($m); $this->assertFalse($p3->isInfinity()); $this->assertEquals($ex, $math->mod($p3->getX(), $p)); $this->assertEquals($ey, $math->mod($p3->getY(), $p)); }
/** * {@inheritDoc} * @see \Mdanter\Ecc\MathAdapter::toString() */ public function toString($value) { return $this->adapter->toString($value); }
/** * @param $value * * @return int|string */ private function convertHexToDec($value) { return $this->adapter->hexDec($value); }
/** * @param $integer * @param $bitSize * @return int|string */ public function getTwosComplement($integer, $bitSize) { return $this->math->add($this->math->pow(2, $bitSize), $integer); }
/** * Extracts R and S values from given data * * @param string $value * * @return \Mdanter\Ecc\Crypto\Signature\Signature */ private function extractSignature(string $value) : \Mdanter\Ecc\Crypto\Signature\Signature { $length = $this->getSignatureLength(); $value = unpack('H*', $value)[1]; return new Signature($this->adapter->hexDec(substr($value, 0, $length)), $this->adapter->hexDec(substr($value, $length))); }
/** * @param int|string $max * @return int|string */ public function generate($max) { $bytes = NumberSize::getFlooredByteSize($this->adapter, $max); $iv = mcrypt_create_iv($bytes, \MCRYPT_DEV_URANDOM); return $this->adapter->hexDec(bin2hex($iv)); }