forked from deceze/Kunststube-CSRFP
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSignatureGenerator.php
103 lines (82 loc) · 2.94 KB
/
SignatureGenerator.php
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
<?php
namespace Kunststube\CSRFP;
class SignatureGenerator {
protected $validityWindow = '-24 hours',
$data = array(),
$crypto,
$secret;
public function __construct($secret, ICryptoProvider $crypto = null) {
if (!$crypto) {
require_once __DIR__ . DIRECTORY_SEPARATOR . 'CryptoProvider.php';
$crypto = new CryptoProvider;
}
$this->secret = $secret;
$this->crypto = $crypto;
$this->setValidityWindow($this->validityWindow);
}
public function setValidityWindow($window) {
switch (true) {
case is_int($window) :
$this->validityWindow = $window;
break;
case is_string($window) :
$this->validityWindow = strtotime($window);
break;
case $window instanceof \DateTime :
$this->validityWindow = $window->getTimestamp();
break;
default :
throw new \InvalidArgumentException(sprintf('Invalid argument of type %s', gettype($window)));
}
}
public function addValue($value) {
$this->data[] = $value;
}
public function addKeyValue($key, $value) {
$this->data[$key] = $value;
}
public function setData(array $data) {
$this->data = $data;
}
public function getSignature() {
$timestamp = time();
$token = $this->generateToken();
$signature = $this->generateSignature($timestamp, $token);
return "$timestamp:$token:$signature";
}
public function validateSignature($signatureToken) {
$args = explode(':', $signatureToken);
if (count($args) != 3) {
throw new \InvalidArgumentException("'$signatureToken' is not a valid signature format");
}
list($timestamp, $token, $signature) = $args;
if ($timestamp < $this->validityWindow) {
return false;
}
return $this->generateSignature($timestamp, $token) === $signature;
}
protected function generateSignature($timestamp, $token) {
if (!is_numeric($timestamp)) {
throw new \InvalidArgumentException('$timestamp must be an integer');
}
$timestamp = (int)$timestamp;
$array = $object = array();
foreach ($this->data as $key => $value) {
if (is_int($key)) {
$array[] = $value;
} else {
$object[$key] = $value;
}
}
sort($array);
ksort($object);
$data = json_encode(compact('timestamp', 'token', 'array', 'object'));
return $this->hexToBase64($this->crypto->hash($data, $this->secret));
}
protected function generateToken() {
return $this->hexToBase64($this->crypto->getRandomHexString(128));
}
protected function hexToBase64($hex) {
return base64_encode(pack('H*', $hex));
}
}