-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTokenBase.php
138 lines (110 loc) · 4.04 KB
/
TokenBase.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<?php
namespace rogoss\OAuth;
require_once __DIR__ . "/TokenException.php";
class TokenBase {
// Token Fields
//==========================================================================
/** @property string Idealy the User-Agent, that the Token was created for */
protected string $sAgent = "";
//==========================================================================
/** @property string the SHA256 Representation of the Tokens Agent */
protected string $sAgentToken = "";
/** @property string Additional content, that can for example describe the areas, this token is valid in */
protected string $sContent = "";
/** @property int The number of Seconds, the Token will stay valid */
protected int $iTTL = 0;
// Signature Secret
//==========================================================================
private string $sSecret = "";
/**
* @param string $sSignaturSecret a Salt-String, that the contents actual signature will we wrapped in
*/
public function __construct($sSignaturSecret = "")
{
if (!empty($sSignaturSecret) && strlen($sSignaturSecret) < 10)
throw new TokenException("given secret is to short must at least be 10 characters", TokenException::SECRET_TO_SHORT);
$this->sSecret = $sSignaturSecret;
}
private function toUnsignedArray() : array {
$aTokenContent = [];
$sTokenMode = "";
if (!empty($this->sAgentToken)) {
$aTokenContent["a"] = $this->sAgentToken;
$sTokenMode .= "a";
}
if ($this->iTTL > 0) {
$aTokenContent["ttl"] = $this->iTTL;
$sTokenMode .= "t";
}
if (!empty($this->sContent)) {
$aTokenContent["c"] = $this->sContent;
$sTokenMode .= 'c';
}
$aTokenContent['m'] = $sTokenMode;
return $aTokenContent;
}
protected function getSignature() : string {
return $this->signArray($this->toUnsignedArray());
}
protected function hashAgent($sAgent): string {
return hash("sha256", $sAgent);
}
/**
* @param array $aToken - an array containing all Values, for a given token
* @return string
*/
private function signArray(array &$aToken): string {
$sSignaturContent =
($aToken['a'] ?? '')
. ($aToken['m'] ?? '')
. ($aToken['ttl'] ?? '')
. ($aToken['c'] ?? '');
if (empty($this->sSecret))
return hash("sha256", $sSignaturContent);
$aSignaturSplitHash = str_split(hash("sha256", $sSignaturContent), 1);
$iSplitHashLength = count($aSignaturSplitHash);
$iFoundNums = 0;
$iFoundSum = 0;
for ($a = 0; $a < $iSplitHashLength; $a++) {
switch ($aSignaturSplitHash[$a]) {
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
$iFoundNums++;
$iFoundSum += intval($aSignaturSplitHash[$a]);
}
}
$iMagicNr = floor($iFoundSum / $iFoundSum);
$aToken['s'] = hash(
"sha256",
substr($this->sSecret, 0, $iMagicNr)
. $sSignaturContent
. substr($this->sSecret, $iMagicNr - 1)
);
return $aToken['s'];
}
/**
* Returns a String representation of this token (Including a signature)
* @param bool $bBase64 - if true, the result will be base64 encoded
*
* @return string - either a JSON-String or Base64-String, depended on $bBase64
*/
public function toString($bBase64 = false): string
{
$aToken = $this->toUnsignedArray();
$this->signArray($aToken);
$sOutput = json_encode($aToken);
return $bBase64 ? base64_encode($sOutput) : $sOutput;
}
public function __toString()
{
return $this->toString();
}
}