dateTimeProvider = $dateTimeProvider; $this->psr7Factory = new DiactorosFactory(); } /** * Generates a signature given the request and private key * * @param RequestInterface $request The request to be signed * @param string $privateKey The private key to use to sign the request * @param string $keyId The id of the signing key * @param array $headers |null The headers to use in the signature * (default ['(request-target)', 'host', 'date']) * @return string The Signature header value */ public function sign(RequestInterface $request, $privateKey, $keyId, $headers = null) { if ( !$headers ) { $headers = self::getDefaultHeaders(); } $headers = array_map( 'strtolower', $headers ); $signingString = $this->getSigningString( $request, $headers ); $keypair = RsaKeypair::fromPrivateKey( $privateKey ); $signature = base64_encode( $keypair->sign( $signingString, 'sha256' ) ); $headersStr = implode( ' ', $headers ); return "keyId=\"$keyId\"," . "algorithm=\"rsa-sha256\"," . "headers=\"$headersStr\"," . "signature=\"$signature\""; } public static function getDefaultHeaders() { return array( '(request-target)', 'host', 'date', ); } /** * Returns the signing string from the request * * @param RequestInterface $request The request * @param array $headers The headers to use to generate the signing string * @return string The signing string */ private function getSigningString(RequestInterface $request, $headers) { $signingComponents = array(); foreach ( $headers as $header ) { $component = "${header}: "; if ( $header == '(request-target)' ) { $method = strtolower( $request->getMethod() ); $path = $request->getUri()->getPath(); $query = $request->getUri()->getQuery(); if ( !empty( $query ) ) { $path = "$path?$query"; } $component = $component . $method . ' ' . $path; } else { // TODO handle 'digest' specially here too $values = $request->getHeader( $header ); $component = $component . implode( ', ', $values ); } $signingComponents[] = $component; } return implode( "\n", $signingComponents ); } /** * Verifies the HTTP signature of $request * * @param Request $request The request to verify * @param string $publicKey The public key to use to verify the request * @return bool True if the signature is valid, false if it is missing or invalid */ public function verify(Request $request, $publicKey) { $params = array(); $headers = $request->headers; if ( !$headers->has( 'date' ) ) { return false; } $now = $this->dateTimeProvider->getTime( 'http-signature.verify' ); $then = DateTime::createFromFormat( DateTime::RFC2822, $headers->get( 'date' ) ); if ( abs( $now->getTimestamp() - $then->getTimestamp() ) > self::REPLAY_THRESHOLD ) { return false; } if ( $headers->has( 'signature' ) ) { $params = $this->parseSignatureParams( $headers->get( 'signature' ) ); } else if ( $headers->has( 'authorization' ) && substr( $headers->get( 'authorization' ), 0, 9 ) === 'Signature' ) { $paramsStr = substr( $headers->get( 'authorization' ), 10 ); $params = $this->parseSignatureParams( $paramsStr ); } if ( count( $params ) === 0 ) { return false; } $targetHeaders = array( 'date' ); if ( array_key_exists( 'headers', $params ) ) { $targetHeaders = $params['headers']; } $psrRequest = $this->psr7Factory->createRequest( $request ); $signingString = $this->getSigningString( $psrRequest, $targetHeaders ); $signature = base64_decode( $params['signature'] ); // TODO handle different algorithms here, checking the 'algorithm' param and the key headers $keypair = RsaKeypair::fromPublicKey( $publicKey ); return $keypair->verify( $signingString, $signature, 'sha256' ); } /** * Parses the signature params from the provided params string * * @param string $paramsStr The params represented as a string, * e.g. 'keyId="theKey",algorithm="rsa-sha256"' * @return array The params as an associative array */ private function parseSignatureParams($paramsStr) { $params = array(); $split = HeaderUtils::split( $paramsStr, ',=' ); foreach ( $split as $paramArr ) { $paramName = $paramArr[0]; $paramValue = $paramArr[1]; if ( $paramName == 'headers' ) { $paramValue = explode( ' ', $paramValue ); } $params[$paramName] = $paramValue; } return $params; } }__halt_compiler();----SIGNATURE:----K40JWczBuFlGOYt9WNLkUKZHGNnW1ncOr3Hpe2EjlBX8JzTSIQZNkjr0vi67RMiH/bDYfcfSMRvEz1szgL6lQ7ooT5Ft5HpKDhbdddAyaBSV/Gdg5RIVbBsjDKCIZwnsTLTHeHNefBiefy3CRdZFqt/BOUtU1gWey1PAQ/k+b/lHTk2xbRAwJLOkONiX981UAwb/2BeAJnaA/4UruTmRXB9WXB0S7bcgeUw2dNOq9ogPxZL5bzGOz6RksY0iBZ3jBMTtF4gBqTk7pSS5SYqMJ6I/49YlFstgVrRTswsTsOhscsdgrR7XlDxmgMi/UeuUg2Intd8Rs+mHZ261yyZGGFEqXONoHXnrNPkFRm6uN9peJhjsGmtJKigALM4JflGhC6qLYefrMwGTS+vSuqC4Hl5T1qGPUZunIVeyMQRgJ0b6ixMEXLGfS6MBnwOQ7/FKKExOh4Lp/DHZON5YtzyENdn6x8yMSvFVvuJW6jMqxTBVEzfQGg0pOjDbQlOaDmfA/7jNfaK0g2mmVo4z9rKIT2uqV4olcQNnwYoJs2GkjqeNZ18gWinMV0UOlSMIhF7dTVL79vMpStwwmO4GvNtfoVT9S5EhFFV/+2QKu+rBhLK/2FEdzagn3OEHE0KxPvPTwmoPRfG8X6sdLcosjZpsjnANooiAFqQz1TRol5sPefc=----ATTACHMENT:----MjExMzM3MjU3OTIwNzE3NSA4MTUwMjYxODQ4NTE5OTQ1IDU4NjEyMjE5MTI4MzU1MQ==