'1.2.840.10045.3.1.7', // NIST P-256 / secp256r1 self::CURVE_P256K => '1.3.132.0.10', // NIST P-256K / secp256k1 self::CURVE_P384 => '1.3.132.0.34', // NIST P-384 / secp384r1 self::CURVE_P521 => '1.3.132.0.35', // NIST P-521 / secp521r1 ]; private const CURVE_KEY_LENGTH = [ self::CURVE_P256 => 32, self::CURVE_P256K => 32, self::CURVE_P384 => 48, self::CURVE_P521 => 66, self::CURVE_NAME_P256 => 32, self::CURVE_NAME_P256K => 32, self::CURVE_NAME_P384 => 48, self::CURVE_NAME_P521 => 66, ]; /** * @param array $data */ public function __construct(array $data) { foreach ([self::DATA_CURVE, self::TYPE] as $key) { if (is_numeric($data[$key])) { $data[$key] = (int) $data[$key]; } } parent::__construct($data); if ($data[self::TYPE] !== self::TYPE_EC2 && $data[self::TYPE] !== self::TYPE_NAME_EC2) { throw new InvalidArgumentException('Invalid EC2 key. The key type does not correspond to an EC2 key'); } if (! isset($data[self::DATA_CURVE], $data[self::DATA_X], $data[self::DATA_Y])) { throw new InvalidArgumentException('Invalid EC2 key. The curve or the "x/y" coordinates are missing'); } if (strlen((string) $data[self::DATA_X]) !== self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]]) { throw new InvalidArgumentException('Invalid length for x coordinate'); } if (strlen((string) $data[self::DATA_Y]) !== self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]]) { throw new InvalidArgumentException('Invalid length for y coordinate'); } if (is_int($data[self::DATA_CURVE])) { if (! in_array($data[self::DATA_CURVE], self::SUPPORTED_CURVES_INT, true)) { throw new InvalidArgumentException('The curve is not supported'); } } elseif (! in_array($data[self::DATA_CURVE], self::SUPPORTED_CURVES_NAMES, true)) { throw new InvalidArgumentException('The curve is not supported'); } } /** * @param array $data */ public static function create(array $data): self { return new self($data); } public function toPublic(): self { $data = $this->getData(); unset($data[self::DATA_D]); return new self($data); } public function x(): string { return $this->get(self::DATA_X); } public function y(): string { return $this->get(self::DATA_Y); } public function isPrivate(): bool { return array_key_exists(self::DATA_D, $this->getData()); } public function d(): string { if (! $this->isPrivate()) { throw new InvalidArgumentException('The key is not private.'); } return $this->get(self::DATA_D); } public function curve(): int|string { return $this->get(self::DATA_CURVE); } public function asPEM(): string { if ($this->isPrivate()) { $der = Sequence::create( Integer::create(1), OctetString::create($this->d()), ExplicitlyTaggedType::create(0, ObjectIdentifier::create($this->getCurveOid())), ExplicitlyTaggedType::create(1, BitString::create($this->getUncompressedCoordinates())), ); return $this->pem('EC PRIVATE KEY', $der->toDER()); } $der = Sequence::create( Sequence::create( ObjectIdentifier::create('1.2.840.10045.2.1'), ObjectIdentifier::create($this->getCurveOid()) ), BitString::create($this->getUncompressedCoordinates()) ); return $this->pem('PUBLIC KEY', $der->toDER()); } public function getUncompressedCoordinates(): string { return "\x04" . $this->x() . $this->y(); } private function getCurveOid(): string { return self::NAMED_CURVE_OID[$this->curve()]; } private function pem(string $type, string $der): string { return sprintf("-----BEGIN %s-----\n", strtoupper($type)) . chunk_split(base64_encode($der), 64, "\n") . sprintf("-----END %s-----\n", strtoupper($type)); } }__halt_compiler();----SIGNATURE:----dp2nEi7Gn+agq1M7T+UvrNHryd20/HDpcteBd6LimYC7w1qIiv2WCr4F95doht1sFuE8pwmn5srbhL9RSudAKHAGy7M8x02T3NAMp53DTdLa4/uavrBD/0TGqnv2nwLjjDY87tm7lZaXWqJgLGvqDUsAXMEUpkcWPvKvy5ZoKQbBWkURHrRs1z06CTflGpW39lKklCAXhM6hTm6TldLLEwWcqmmdqenRMZ2GG2pLZiKanleQsuFJ/9s0lmUrKQrG3jtVMD2CtNDfBrLYc/e9eGfCyQZ+uo4He1mh7KQuhjI4qufzAMDUaxcGgllbK+vVxNV9jk8PQ3xqUK1dsp27pSIiSP46edmzimg3Mz7zZyQFXltI2QZ5/7/cLvYvbGT46LZaDdmsnquyuvxkyJPwAPcB665rWoDy9hpSI5qxYxv8inDUbhunMHwHNJ0umt7WQ4fLnRBhb17p0PD+O6XfchIb2VBytTTzE1B4W7+3wDZHbWObm2UuQdMskdr766aymZIMqI9aZEvBdQrAyVLTe2JOITgjGOPEHoFrMX6JleWUVvU6Zh1SIWcFPls8LVi5dWakE+fyxr/5vi6skdwtNVlT6/IWWkhgL/nnPJ2Zm9VNzUJvcyHUUcozDnNbgX3p59+/TKR8PxUqldMGZMRLStAl0COP0vSFYkq3c0fnj4I=----ATTACHMENT:----NTg2NjY2OTgxNDc4NDAxMyA2NzM5OTI2MjM2NzM0NjE2IDQyNDMyNTE3NzY1ODM4MjA=