CryptographyService   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 100
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 98.08%

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 7
dl 0
loc 100
ccs 51
cts 52
cp 0.9808
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 3
A getPkpCode() 0 28 3
A getBkpCode() 0 6 1
A addWSESignature() 0 17 1
A verifyPublicKey() 0 12 3
1
<?php declare(strict_types = 1);
2
3
namespace SlevomatEET\Cryptography;
4
5
use DOMDocument;
6
use RobRichards\WsePhp\WSSESoap;
7
use RobRichards\XMLSecLibs\XMLSecurityDSig;
8
use RobRichards\XMLSecLibs\XMLSecurityKey;
9
use const OPENSSL_ALGO_SHA256;
10
use function is_file;
11
12
class CryptographyService
13
{
14
15
	/** @var string */
16
	private $privateKeyFile;
17
18
	/** @var string */
19
	private $privateKeyPassword;
20
21
	/** @var string */
22
	private $publicKeyFile;
23
24
	/** @var bool */
25
	private $publicKeyVerified;
26
27 9
	public function __construct(string $privateKeyFile, string $publicKeyFile, string $privateKeyPassword = '')
28
	{
29 9
		if (!is_file($privateKeyFile)) {
30 1
			throw new PrivateKeyFileNotFoundException($privateKeyFile);
31
		}
32 8
		if (!is_file($publicKeyFile)) {
33 1
			throw new PublicKeyFileNotFoundException($publicKeyFile);
34
		}
35 7
		$this->privateKeyFile = $privateKeyFile;
36 7
		$this->publicKeyFile = $publicKeyFile;
37 7
		$this->privateKeyPassword = $privateKeyPassword;
38 7
	}
39
40
	/**
41
	 * @param mixed[] $body
42
	 * @return string
43
	 */
44 3
	public function getPkpCode(array $body): string
45
	{
46
		$values = [
47 3
			$body['dic_popl'],
48 3
			$body['id_provoz'],
49 3
			$body['id_pokl'],
50 3
			$body['porad_cis'],
51 3
			$body['dat_trzby'],
52 3
			$body['celk_trzba'],
53
		];
54
55 3
		$plaintext = implode('|', $values);
56
57 3
		$privateKey = (string) file_get_contents($this->privateKeyFile);
58 3
		$privateKeyId = openssl_pkey_get_private($privateKey, $this->privateKeyPassword);
59 3
		if ($privateKeyId === false) {
60 1
			throw new PrivateKeyFileException($this->privateKeyFile);
61
		}
62
63 2
		$ok = openssl_sign($plaintext, $signature, $privateKeyId, OPENSSL_ALGO_SHA256);
64 2
		if (!$ok) {
65 1
			throw new SigningFailedException($values);
66
		}
67
68 1
		openssl_free_key($privateKeyId);
69
70 1
		return $signature;
71
	}
72
73 1
	public function getBkpCode(string $pkpCode): string
74
	{
75 1
		$bkp = strtoupper(sha1($pkpCode));
76
77 1
		return implode('-', str_split($bkp, 8));
78
	}
79
80 4
	public function addWSESignature(string $request): string
81
	{
82 4
		$publicKey = (string) file_get_contents($this->publicKeyFile);
83 4
		$this->verifyPublicKey($publicKey);
84 3
		$securityKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, ['type' => 'private']);
85 3
		$document = new DOMDocument('1.0');
86 3
		$document->loadXML($request);
87 3
		$wse = new WSSESoap($document);
88 3
		$securityKey->passphrase = $this->privateKeyPassword;
89 3
		$securityKey->loadKey($this->privateKeyFile, true);
90 3
		$wse->addTimestamp();
91 3
		$wse->signSoapDoc($securityKey, ['algorithm' => XMLSecurityDSig::SHA256]);
92 2
		$binaryToken = $wse->addBinaryToken($publicKey);
93 2
		$wse->attachTokentoSig($binaryToken);
94
95 2
		return $wse->saveXML();
96
	}
97
98 4
	private function verifyPublicKey(string $fileContents): void
99
	{
100 4
		if ($this->publicKeyVerified) {
101
			return;
102
		}
103 4
		$publicKeyResource = openssl_get_publickey($fileContents);
104 4
		if ($publicKeyResource === false) {
105 1
			throw new InvalidPublicKeyException($this->publicKeyFile, (string) openssl_error_string());
106
		}
107 3
		openssl_free_key($publicKeyResource);
108 3
		$this->publicKeyVerified = true;
109 3
	}
110
111
}
112