-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathWebhookSignatureValidation.php
More file actions
106 lines (87 loc) · 3.17 KB
/
WebhookSignatureValidation.php
File metadata and controls
106 lines (87 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<?php
/**
* (c) 2023 - Bluem Plugin Support <pluginsupport@bluem.nl>
*
* This source file is subject to the license that is bundled
* with this source code in the file LICENSE.
*/
namespace Bluem\BluemPHP\Validators;
use Bluem\BluemPHP\Helpers\Now;
use DOMDocument;
use Exception;
use RobRichards\XMLSecLibs\XMLSecurityDSig;
use RobRichards\XMLSecLibs\XMLSecurityKey;
class WebhookSignatureValidation extends WebhookValidator
{
private const KEY_FOLDER = "/keys/";
public function __construct(
private string $env
) {
}
/**
* Validate webhook signature based on a key file
* available in the `keys` folder.
*/
public function validate(string $data): self
{
$public_key_file_path = dirname(__DIR__, 2) . self::KEY_FOLDER . $this->getKeyFileName();
$temp_file = tmpfile();
fwrite($temp_file, $data);
$temp_file_path = stream_get_meta_data($temp_file)['uri'];
// Load the XML to be verified
$doc = new DOMDocument();
$doc->load($temp_file_path);
// Create a new Security object
$objDSig = new XMLSecurityDSig();
// Locate the signature within the XML
try {
$objDSig->locateSignature($doc);
$objDSig->canonicalizeSignedInfo();
$objDSig->validateReference();
} catch (Exception $e) {
$this->addError('Reference Validation Failed: ' . $e->getMessage());
}
try {
// Load the public key
$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, ['type' => 'public']);
$objKey->loadKey($public_key_file_path, TRUE);
} catch (Exception $e) {
$this->addError('Could not load public key');
}
try {
// Check the signature
if (!$objDSig->verify($objKey)) {
$this->addError("Invalid signature");
}
// else, the signature is valid
} catch (Exception $e) {
$this->addError($e->getMessage());
}
fclose($temp_file);
return $this;
}
/**
* Determine filename certificate
*/
private function getKeyFileName(): string
{
// Define current date & time
$now = new Now();
$current_date = $now->format('Y-m-d');
$current_time = $now->format('H:i');
// Define the default filename
$prefix = 'webhook_bluem_nl_';
// Check the datetime for certificates
if ( ( $current_date === "2024-07-01" && $current_time >= "12:00" ) || $current_date > "2024-07-01")
{
$timestamp = '20240701';
} elseif ($this->env === BLUEM_ENVIRONMENT_TESTING && ( ( $current_date === "2023-06-28" && $current_time >= "08:00" ) || $current_date > "2023-06-28")) {
$timestamp = '202306140200-202407050159';
} elseif ($this->env === BLUEM_ENVIRONMENT_PRODUCTION && ( ( $current_date === "2023-07-04" && $current_time >= "08:00" ) || $current_date > "2023-07-04")) {
$timestamp = '202306140200-202407050159';
} else {
$timestamp = '202206090200-202307110159';
}
return $prefix . $timestamp . '.pem';
}
}