Issues (27)

src/Crypto/CryptoService.php (1 issue)

Severity
1
<?php declare(strict_types = 1);
2
3
namespace SlevomatCsobGateway\Crypto;
4
5
use const OPENSSL_ALGO_SHA256;
6
use function base64_decode;
7
use function base64_encode;
8
use function file_get_contents;
9
10
class CryptoService
11
{
12
13
	public const HASH_METHOD = OPENSSL_ALGO_SHA256;
14
15
	/** @var string */
16
	private $privateKeyFile;
17
18
	/** @var string */
19
	private $bankPublicKeyFile;
20
21
	/** @var string|null */
22
	private $privateKeyPassword;
23
24 6
	public function __construct(
25
		string $privateKeyFile,
26
		string $bankPublicKeyFile,
27
		string $privateKeyPassword = ''
28
	)
29
	{
30 6
		$this->privateKeyFile = $privateKeyFile;
31 6
		$this->bankPublicKeyFile = $bankPublicKeyFile;
32 6
		$this->privateKeyPassword = $privateKeyPassword;
33 6
	}
34
35
	/**
36
	 * @param mixed[] $data
37
	 * @param SignatureDataFormatter $signatureDataFormatter
38
	 * @return string
39
	 *
40
	 * @throws PrivateKeyFileException
41
	 * @throws SigningFailedException
42
	 */
43 4
	public function signData(array $data, SignatureDataFormatter $signatureDataFormatter): string
44
	{
45 4
		$message = $signatureDataFormatter->formatDataForSignature($data);
46
47
		/** @var string $privateKey */
48 4
		$privateKey = file_get_contents($this->privateKeyFile);
49 4
		$privateKeyId = openssl_pkey_get_private($privateKey, (string) $this->privateKeyPassword);
50 4
		if ($privateKeyId === false) {
51 1
			throw new PrivateKeyFileException($this->privateKeyFile);
52
		}
53
54 3
		$ok = openssl_sign($message, $signature, $privateKeyId, self::HASH_METHOD);
55 3
		if (!$ok) {
0 ignored issues
show
The condition $ok is always false.
Loading history...
56 1
			throw new SigningFailedException($data);
57
		}
58
59 2
		$signature = base64_encode($signature);
60 2
		openssl_free_key($privateKeyId);
61
62 2
		return $signature;
63
	}
64
65
	/**
66
	 * @param mixed[] $data
67
	 * @param string $signature
68
	 * @param SignatureDataFormatter $signatureDataFormatter
69
	 * @return bool
70
	 *
71
	 * @throws PublicKeyFileException
72
	 * @throws VerificationFailedException
73
	 */
74 4
	public function verifyData(array $data, string $signature, SignatureDataFormatter $signatureDataFormatter): bool
75
	{
76 4
		$message = $signatureDataFormatter->formatDataForSignature($data);
77
78 4
		$publicKey = (string) file_get_contents($this->bankPublicKeyFile);
79 4
		$publicKeyId = openssl_pkey_get_public($publicKey);
80 4
		if ($publicKeyId === false) {
81 1
			throw new PublicKeyFileException($this->bankPublicKeyFile);
82
		}
83
84 3
		$signature = base64_decode($signature, true);
85 3
		if ($signature === false) {
86
			throw new VerificationFailedException($data, 'Unable to decode signature.');
87
		}
88
89 3
		$verifyResult = openssl_verify($message, $signature, $publicKeyId, self::HASH_METHOD);
90 3
		openssl_free_key($publicKeyId);
91 3
		if ($verifyResult === -1) {
92 1
			throw new VerificationFailedException($data, openssl_error_string());
93
		}
94
95 2
		return $verifyResult === 1;
96
	}
97
98
}
99