@@ -36,17 +36,23 @@ class IncomingSignedRequest extends SignedRequest implements
3636 private string $ origin = '' ;
3737
3838 /**
39+ * @param string $body
40+ * @param IRequest $request
41+ * @param array $options
42+ *
3943 * @throws IncomingRequestException if incoming request is wrongly signed
40- * @throws SignatureNotFoundException if signature is not fully implemented
44+ * @throws SignatureException if signature is faulty
45+ * @throws SignatureNotFoundException if signature is not implemented
4146 */
4247 public function __construct (
4348 string $ body ,
4449 private readonly IRequest $ request ,
4550 private readonly array $ options = [],
4651 ) {
4752 parent ::__construct ($ body );
48- $ this ->verifyHeadersFromRequest ();
49- $ this ->extractSignatureHeaderFromRequest ();
53+ $ this ->verifyHeaders ();
54+ $ this ->extractSignatureHeader ();
55+ $ this ->reconstructSignatureData ();
5056 }
5157
5258 /**
@@ -59,7 +65,7 @@ public function __construct(
5965 * @throws IncomingRequestException
6066 * @throws SignatureNotFoundException
6167 */
62- private function verifyHeadersFromRequest (): void {
68+ private function verifyHeaders (): void {
6369 // confirm presence of date, content-length, digest and Signature
6470 $ date = $ this ->getRequest ()->getHeader ('date ' );
6571 if ($ date === '' ) {
@@ -105,7 +111,7 @@ private function verifyHeadersFromRequest(): void {
105111 *
106112 * @throws IncomingRequestException
107113 */
108- private function extractSignatureHeaderFromRequest (): void {
114+ private function extractSignatureHeader (): void {
109115 $ details = [];
110116 foreach (explode (', ' , $ this ->getRequest ()->getHeader ('Signature ' )) as $ entry ) {
111117 if ($ entry === '' || !strpos ($ entry , '= ' )) {
@@ -132,6 +138,36 @@ private function extractSignatureHeaderFromRequest(): void {
132138 }
133139 }
134140
141+ /**
142+ * @throws SignatureException
143+ * @throws SignatureElementNotFoundException
144+ */
145+ private function reconstructSignatureData (): void {
146+ $ usedHeaders = explode (' ' , $ this ->getSigningElement ('headers ' ));
147+ $ neededHeaders = array_merge (['date ' , 'host ' , 'content-length ' , 'digest ' ],
148+ array_keys ($ this ->options ['extraSignatureHeaders ' ] ?? []));
149+
150+ $ missingHeaders = array_diff ($ neededHeaders , $ usedHeaders );
151+ if ($ missingHeaders !== []) {
152+ throw new SignatureException ('missing entries in Signature.headers: ' . json_encode ($ missingHeaders ));
153+ }
154+
155+ $ estimated = ['(request-target): ' . strtolower ($ this ->request ->getMethod ()) . ' ' . $ this ->request ->getRequestUri ()];
156+ foreach ($ usedHeaders as $ key ) {
157+ if ($ key === '(request-target) ' ) {
158+ continue ;
159+ }
160+ $ value = (strtolower ($ key ) === 'host ' ) ? $ this ->request ->getServerHost () : $ this ->request ->getHeader ($ key );
161+ if ($ value === '' ) {
162+ throw new SignatureException ('missing header ' . $ key . ' in request ' );
163+ }
164+
165+ $ estimated [] = $ key . ': ' . $ value ;
166+ }
167+
168+ $ this ->setSignatureData ($ estimated );
169+ }
170+
135171 /**
136172 * @inheritDoc
137173 *
@@ -214,7 +250,7 @@ public function verify(): void {
214250 throw new SignatoryNotFoundException ('empty public key ' );
215251 }
216252
217- $ algorithm = SignatureAlgorithm::tryFrom ($ this ->getSigningElement ('algorithm ' )) ?? SignatureAlgorithm::SHA256 ;
253+ $ algorithm = SignatureAlgorithm::tryFrom ($ this ->getSigningElement ('algorithm ' )) ?? SignatureAlgorithm::RSA_SHA256 ;
218254 if (openssl_verify (
219255 implode ("\n" , $ this ->getSignatureData ()),
220256 base64_decode ($ this ->getSignature ()),
0 commit comments