Completed
Push — master ( 70be8d...b5e6ba )
by Jan
05:24
created

CryptographyService   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 100
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 100%

Importance

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