@@ -61,15 +61,27 @@ public function __construct(string $scopeName, string $region)
6161
6262 public function presign (Request $ request , Credentials $ credentials , RequestContext $ context ): void
6363 {
64- $ now = $ context ->getCurrentDate () ?? new \DateTimeImmutable ();
65- $ expires = $ context ->getExpirationDate () ?? (new \DateTimeImmutable ($ now ->format (\DateTimeInterface::ATOM )))->add (new \DateInterval ('PT1H ' ));
64+ if (null === $ now = $ context ->getCurrentDate ()) {
65+ $ now = new \DateTimeImmutable ();
66+ } else {
67+ $ now = new \DateTimeImmutable ($ now ->format (\DateTimeInterface::ATOM ));
68+ }
69+ // Signer date have to be UTC https://docs.aws.amazon.com/general/latest/gr/sigv4-date-handling.html
70+ $ now = $ now ->setTimezone (new \DateTimeZone ('UTC ' ));
71+ $ expires = $ context ->getExpirationDate () ?? $ now ->add (new \DateInterval ('PT1H ' ));
6672
6773 $ this ->handleSignature ($ request , $ credentials , $ now , $ expires , true );
6874 }
6975
7076 public function sign (Request $ request , Credentials $ credentials , RequestContext $ context ): void
7177 {
72- $ now = $ context ->getCurrentDate () ?? new \DateTimeImmutable ();
78+ if (null === $ now = $ context ->getCurrentDate ()) {
79+ $ now = new \DateTimeImmutable ();
80+ } else {
81+ $ now = new \DateTimeImmutable ($ now ->format (\DateTimeInterface::ATOM ));
82+ }
83+ // Signer date have to be UTC https://docs.aws.amazon.com/general/latest/gr/sigv4-date-handling.html
84+ $ now = $ now ->setTimezone (new \DateTimeZone ('UTC ' ));
7385
7486 $ this ->handleSignature ($ request , $ credentials , $ now , $ now , false );
7587 }
@@ -105,19 +117,19 @@ private function handleSignature(Request $request, Credentials $credentials, \Da
105117 $ credentialString = \implode ('/ ' , $ credentialScope );
106118 $ signingKey = $ this ->buildSigningKey ($ credentials , $ credentialScope );
107119
108- // signature is passed by reference to convertBodyToStream
109- $ signature = '' ;
110120 if ($ isPresign ) {
111121 // Should be called before `buildBodyDigest` because this method may alter the body
112122 $ this ->convertBodyToQuery ($ request );
113123 } else {
124+ // $signature does not exists but passed by reference then computed buildSignature
125+ $ signature = '' ;
114126 $ this ->convertBodyToStream ($ request , $ now , $ credentialString , $ signingKey , $ signature );
115127 }
116128
117129 $ bodyDigest = $ this ->buildBodyDigest ($ request , $ isPresign );
118130
119131 if ($ isPresign ) {
120- // Should be called after `buildBodyDigest` because header this method may remove `x-amz-content-sha256`
132+ // Should be called after `buildBodyDigest` because this method may remove the header `x-amz-content-sha256`
121133 $ this ->convertHeaderToQuery ($ request );
122134 }
123135
@@ -196,16 +208,16 @@ private function buildTime(Request $request, \DateTimeInterface $now, \DateTimeI
196208 throw new InvalidArgument ('The expiration date of presigned URL must be in the future ' );
197209 }
198210
199- $ request ->setQueryAttribute ('X-Amz-Date ' , gmdate ('Ymd\THis\Z ' , $ now -> getTimestamp () ));
211+ $ request ->setQueryAttribute ('X-Amz-Date ' , $ now -> format ('Ymd\THis\Z ' ));
200212 $ request ->setQueryAttribute ('X-Amz-Expires ' , $ duration );
201213 } else {
202- $ request ->setHeader ('X-Amz-Date ' , gmdate ('Ymd\THis\Z ' , $ now -> getTimestamp () ));
214+ $ request ->setHeader ('X-Amz-Date ' , $ now -> format ('Ymd\THis\Z ' ));
203215 }
204216 }
205217
206218 private function buildCredentialString (Request $ request , Credentials $ credentials , \DateTimeInterface $ now , bool $ isPresign ): array
207219 {
208- $ credentialScope = [gmdate ( ' Ymd ' , $ now ->getTimestamp () ), $ this ->region , $ this ->scopeName , 'aws4_request ' ];
220+ $ credentialScope = [$ now ->format ( ' Ymd ' ), $ this ->region , $ this ->scopeName , 'aws4_request ' ];
209221
210222 if ($ isPresign ) {
211223 $ request ->setQueryAttribute ('X-Amz-Credential ' , $ credentials ->getAccessKeyId () . '/ ' . implode ('/ ' , $ credentialScope ));
@@ -380,7 +392,7 @@ private function buildStringToSign(\DateTimeInterface $now, string $credentialSt
380392 {
381393 return implode ("\n" , [
382394 self ::ALGORITHM_REQUEST ,
383- gmdate ('Ymd\THis\Z ' , $ now -> getTimestamp () ),
395+ $ now -> format ('Ymd\THis\Z ' ),
384396 $ credentialString ,
385397 hash ('sha256 ' , $ canonicalRequest ),
386398 ]);
@@ -393,7 +405,7 @@ private function buildChunkStringToSign(\DateTimeInterface $now, string $credent
393405
394406 return implode ("\n" , [
395407 self ::ALGORITHM_CHUNK ,
396- gmdate ('Ymd\THis\Z ' , $ now -> getTimestamp () ),
408+ $ now -> format ('Ymd\THis\Z ' ),
397409 $ credentialString ,
398410 $ signature ,
399411 $ emptyHash ,
0 commit comments