jaroslavtyc/granam-gpwebpay

View on GitHub
GpWebPay/DigestSigner.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php declare(strict_types=1);

namespace Granam\GpWebPay;

use Granam\Strict\Object\StrictObject;

class DigestSigner extends StrictObject implements DigestSignerInterface
{

    private \Granam\GpWebPay\SettingsInterface $settings;
    /** @var resource */
    private $privateKeyResource;
    /** @var resource */
    private $publicKeyResource;

    /**
     * @param SettingsInterface $settings
     * @throws \Granam\GpWebPay\Exceptions\PrivateKeyFileCanNotBeRead
     * @throws \Granam\GpWebPay\Exceptions\PublicKeyFileCanNotBeRead
     */
    public function __construct(SettingsInterface $settings)
    {
        $this->settings = $settings;
    }

    /**
     * @param array|string[] $partsOfDigest
     * @return string Digest as encrypted content of the request for its validation on GpWebPay side
     * @throws \Granam\GpWebPay\Exceptions\PrivateKeyUsageFailed
     * @throws \Granam\GpWebPay\Exceptions\CanNotSignDigest
     */
    public function createSignedDigest(array $partsOfDigest): string
    {
        $digestText = \implode('|', $partsOfDigest);
        if (!\openssl_sign($digestText, $digest, $this->getPrivateKeyResource())) {
            throw new Exceptions\CanNotSignDigest('Can not sign ' . $digestText);
        }

        return \base64_encode($digest);
    }

    /**
     * @return resource
     * @throws \Granam\GpWebPay\Exceptions\PrivateKeyUsageFailed
     */
    private function getPrivateKeyResource()
    {
        if (\is_resource($this->privateKeyResource)) {
            return $this->privateKeyResource;
        }
        $key = \file_get_contents($this->settings->getPrivateKeyFile());
        if (!($this->privateKeyResource = \openssl_pkey_get_private($key, $this->settings->getPrivateKeyPassword()))) {
            $errorMessage = "'{$this->settings->getPrivateKeyFile()}' is not valid PEM private key";
            if ($this->settings->getPrivateKeyPassword() !== '') {
                $errorMessage = "Password for private key is incorrect (or $errorMessage)";
            }
            throw new Exceptions\PrivateKeyUsageFailed($errorMessage);
        }

        return $this->privateKeyResource;
    }

    /**
     * @param array|string[] $expectedPartsOfDigest
     * @param string $digestToVerify
     * @return bool
     * @throws \Granam\GpWebPay\Exceptions\ResponseDigestCanNotBeVerified
     * @throws \Granam\GpWebPay\Exceptions\PublicKeyUsageFailed
     */
    public function verifySignedDigest(string $digestToVerify, array $expectedPartsOfDigest): bool
    {
        $expectedDigest = \implode('|', $expectedPartsOfDigest);
        $decodedDigestToVerify = base64_decode($digestToVerify);
        if (\openssl_verify($expectedDigest, $decodedDigestToVerify, $this->getPublicKeyResource()) !== 1) {
            throw new Exceptions\ResponseDigestCanNotBeVerified(
                'Given digest does not match expected ' . $expectedDigest
            );
        }

        return true;
    }

    /**
     * @return resource
     * @throws \Granam\GpWebPay\Exceptions\PublicKeyUsageFailed
     */
    private function getPublicKeyResource()
    {
        if (\is_resource($this->publicKeyResource)) {
            return $this->publicKeyResource;
        }
        $publicKey = \file_get_contents($this->settings->getPublicKeyFile());
        if (!($this->publicKeyResource = \openssl_pkey_get_public($publicKey))) {
            throw new Exceptions\PublicKeyUsageFailed(
                "'{$this->settings->getPublicKeyFile()}' is not valid PEM public key."
            );
        }

        return $this->publicKeyResource;
    }
}