/
SignS3Upload.php
96 lines (75 loc) · 2.76 KB
/
SignS3Upload.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
<?php
namespace A17\Twill\Services\Uploader;
use Illuminate\Config\Repository as Config;
class SignS3Upload
{
private $bucket;
private $secret;
/**
* @var Config
*/
protected $config;
/**
* @param Config $config
*/
public function __construct(Config $config)
{
$this->config = $config;
}
public function fromPolicy($policy, SignUploadListener $listener, $disk = 'libraries')
{
$policyObject = json_decode($policy, true);
$policyJson = json_encode($policyObject);
$this->bucket = $this->config->get('filesystems.disks.' . $disk . '.bucket');
$this->secret = $this->config->get('filesystems.disks.' . $disk . '.secret');
$signedPolicy = $this->signPolicy($policyJson);
if ($signedPolicy) {
return $listener->uploadIsSigned($signedPolicy);
}
return $listener->uploadIsNotValid();
}
private function signPolicy($policyJson)
{
$policyObject = json_decode($policyJson, true);
if ($this->isValid($policyObject)) {
$encodedPolicy = base64_encode($policyJson);
$signedPolicy = array(
'policy' => $encodedPolicy,
'signature' => $this->signV4Policy($policyObject, $encodedPolicy),
);
return $signedPolicy;
}
return null;
}
private function isValid($policy)
{
$expectedMaxSize = null;
$conditions = $policy["conditions"];
$bucket = null;
$parsedMaxSize = null;
for ($i = 0; $i < count($conditions); ++$i) {
$condition = $conditions[$i];
if (isset($condition["bucket"])) {
$bucket = $condition["bucket"];
} else if (isset($condition[0]) && $condition[0] == "content-length-range") {
$parsedMaxSize = $condition[2];
}
}
return $bucket == $this->bucket && $parsedMaxSize == (string) $expectedMaxSize;
}
private function signV4Policy($policy, $encodedPolicy)
{
foreach ($policy["conditions"] as $condition) {
if (isset($condition["x-amz-credential"])) {
$credentialCondition = $condition["x-amz-credential"];
}
}
$pattern = "/.+\/(.+)\\/(.+)\/s3\/aws4_request/";
preg_match($pattern, $credentialCondition, $matches);
$dateKey = hash_hmac('sha256', $matches[1], 'AWS4' . $this->secret, true);
$dateRegionKey = hash_hmac('sha256', $matches[2], $dateKey, true);
$dateRegionServiceKey = hash_hmac('sha256', 's3', $dateRegionKey, true);
$signingKey = hash_hmac('sha256', 'aws4_request', $dateRegionServiceKey, true);
return hash_hmac('sha256', $encodedPolicy, $signingKey);
}
}