| 
							
							
							
						 |  |  | @@ -1,348 +0,0 @@ | 
		
	
		
			
				|  |  |  |  | <?php | 
		
	
		
			
				|  |  |  |  | /* | 
		
	
		
			
				|  |  |  |  |  * Copyright (c) 2014 David Gwynne <david@gwynne.id.au> | 
		
	
		
			
				|  |  |  |  |  * | 
		
	
		
			
				|  |  |  |  |  * Permission to use, copy, modify, and distribute this software for any | 
		
	
		
			
				|  |  |  |  |  * purpose with or without fee is hereby granted, provided that the above | 
		
	
		
			
				|  |  |  |  |  * copyright notice and this permission notice appear in all copies. | 
		
	
		
			
				|  |  |  |  |  * | 
		
	
		
			
				|  |  |  |  |  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 
		
	
		
			
				|  |  |  |  |  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 
		
	
		
			
				|  |  |  |  |  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 
		
	
		
			
				|  |  |  |  |  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 
		
	
		
			
				|  |  |  |  |  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 
		
	
		
			
				|  |  |  |  |  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 
		
	
		
			
				|  |  |  |  |  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 
		
	
		
			
				|  |  |  |  |  */ | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | class HttpSignatureError extends Exception { }; | 
		
	
		
			
				|  |  |  |  | class ExpiredRequestError extends HttpSignatureError { }; | 
		
	
		
			
				|  |  |  |  | class InvalidHeaderError extends HttpSignatureError { }; | 
		
	
		
			
				|  |  |  |  | class InvalidParamsError extends HttpSignatureError { }; | 
		
	
		
			
				|  |  |  |  | class MissingHeaderError extends HttpSignatureError { }; | 
		
	
		
			
				|  |  |  |  | class InvalidAlgorithmError extends HttpSignatureError { }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | class HTTPSignature { | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	static function parse(array $headers, array $options = array()) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		if (!array_key_exists('signature', $headers)) { | 
		
	
		
			
				|  |  |  |  | 			throw new MissingHeaderError('no signature header in the request'); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		$auth = 'Signature '.$headers['signature']; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (!array_key_exists('headers', $options)) { | 
		
	
		
			
				|  |  |  |  | 			$options['headers'] = array(isset($headers['x-date']) ? 'x-date' : 'date'); | 
		
	
		
			
				|  |  |  |  | 		} else { | 
		
	
		
			
				|  |  |  |  | 			if (!is_array($options['headers'])) { | 
		
	
		
			
				|  |  |  |  | 				throw new Exception('headers option is not an array'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			if (sizeof(array_filter($options['headers'], function ($a) { return (!is_string($a)); }))) { | 
		
	
		
			
				|  |  |  |  | 				throw new Exception('headers option is not an array of strings'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (!array_key_exists('clockSkew', $options)) { | 
		
	
		
			
				|  |  |  |  | 			$options['clockSkew'] = 300; | 
		
	
		
			
				|  |  |  |  | 		} elseif (!is_numeric($options['clockSkew'])) { | 
		
	
		
			
				|  |  |  |  | 			throw new Exception('clockSkew option is not numeric'); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (array_key_exists('algorithms', $options)) { | 
		
	
		
			
				|  |  |  |  | 			if (!is_array($options['algorithms'])) { | 
		
	
		
			
				|  |  |  |  | 				throw new Exception('algorithms option is not an array'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			if (sizeof(array_filter($options['algorithms'], function ($a) { return (!is_string($a)); }))) { | 
		
	
		
			
				|  |  |  |  | 				throw new Exception('algorithms option is not an array of strings'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		$headers['request-line'] = array_key_exists('requestLine', $options) ? | 
		
	
		
			
				|  |  |  |  | 		    $options['requestLine'] : | 
		
	
		
			
				|  |  |  |  | 		    sprintf("%s %s %s", $_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'], $_SERVER['SERVER_PROTOCOL']); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		foreach ($options['headers'] as $header) { | 
		
	
		
			
				|  |  |  |  | 			if (!array_key_exists($header, $headers)) { | 
		
	
		
			
				|  |  |  |  | 				throw new MissingHeaderError("$header was not in the request"); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		$states = array( | 
		
	
		
			
				|  |  |  |  | 			'start' => 0, | 
		
	
		
			
				|  |  |  |  | 			'scheme' => 1, | 
		
	
		
			
				|  |  |  |  | 			'space' => 2, | 
		
	
		
			
				|  |  |  |  | 			'param' => 3, | 
		
	
		
			
				|  |  |  |  | 			'quote' => 4, | 
		
	
		
			
				|  |  |  |  | 			'value' => 5, | 
		
	
		
			
				|  |  |  |  | 			'comma' => 6 | 
		
	
		
			
				|  |  |  |  | 		); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		$scheme = ''; | 
		
	
		
			
				|  |  |  |  | 		$params = array(); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		$param = ''; | 
		
	
		
			
				|  |  |  |  | 		$value = ''; | 
		
	
		
			
				|  |  |  |  | 		$state = $states['start']; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		for ($i = 0; $i < strlen($auth); $i++) { | 
		
	
		
			
				|  |  |  |  | 			$ch = $auth[$i]; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			switch ($state) { | 
		
	
		
			
				|  |  |  |  | 			case $states['start']: | 
		
	
		
			
				|  |  |  |  | 				if (ctype_space($ch)) { | 
		
	
		
			
				|  |  |  |  | 					break; | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				$state = $states['scheme']; | 
		
	
		
			
				|  |  |  |  | 				/* FALLTHROUGH */ | 
		
	
		
			
				|  |  |  |  | 			case $states['scheme']: | 
		
	
		
			
				|  |  |  |  | 				if (ctype_space($ch)) { | 
		
	
		
			
				|  |  |  |  | 					$state = $states['space']; | 
		
	
		
			
				|  |  |  |  | 				} else { | 
		
	
		
			
				|  |  |  |  | 					$scheme .= $ch; | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			case $states['space']; | 
		
	
		
			
				|  |  |  |  | 				if (ctype_space($ch)) { | 
		
	
		
			
				|  |  |  |  | 					continue; | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				$state = $states['param']; | 
		
	
		
			
				|  |  |  |  | 				/* FALLTHROUGH */ | 
		
	
		
			
				|  |  |  |  | 			case $states['param']: | 
		
	
		
			
				|  |  |  |  | 				if ($ch === '=') { | 
		
	
		
			
				|  |  |  |  | 					if ($param === '') { | 
		
	
		
			
				|  |  |  |  | 						throw new InvalidHeaderError('bad param name'); | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 					if (array_key_exists($param, $params)) { | 
		
	
		
			
				|  |  |  |  | 						throw new InvalidHeaderError('param specified again'); | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 					$state = $states['quote']; | 
		
	
		
			
				|  |  |  |  | 					break; | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 				if (!ctype_alpha($ch)) { | 
		
	
		
			
				|  |  |  |  | 					throw new InvalidHeaderError('bad param format'); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				$param .= $ch; | 
		
	
		
			
				|  |  |  |  | 				break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			case $states['quote']; | 
		
	
		
			
				|  |  |  |  | 				if ($ch !== '"') { | 
		
	
		
			
				|  |  |  |  | 					throw new InvalidHeaderError('bad param format'); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 				$state = $states['value']; | 
		
	
		
			
				|  |  |  |  | 				break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			case $states['value']: | 
		
	
		
			
				|  |  |  |  | 				if ($ch === '"') { | 
		
	
		
			
				|  |  |  |  | 					$params[$param] = $value; | 
		
	
		
			
				|  |  |  |  | 					$param = ''; | 
		
	
		
			
				|  |  |  |  | 					$value = ''; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 					$state = $states['comma']; | 
		
	
		
			
				|  |  |  |  | 					break; | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				$value .= $ch; | 
		
	
		
			
				|  |  |  |  | 				break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			case $states['comma']: | 
		
	
		
			
				|  |  |  |  | 				if ($ch !== ',') { | 
		
	
		
			
				|  |  |  |  | 					throw new InvalidHeaderError('bad param format'); | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 				$state = $states['param']; | 
		
	
		
			
				|  |  |  |  | 				break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			default: | 
		
	
		
			
				|  |  |  |  | 				throw new Error('invalid state'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if ($state !== $states['comma']) { | 
		
	
		
			
				|  |  |  |  | 			throw new InvalidHeaderError("bad param format"); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if ($scheme !== 'Signature') { | 
		
	
		
			
				|  |  |  |  | 			throw new InvalidHeaderError('scheme was not "Signature"'); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		$required = array('keyId', 'algorithm', 'signature'); | 
		
	
		
			
				|  |  |  |  | 		foreach ($required as $param) { | 
		
	
		
			
				|  |  |  |  | 			if (!array_key_exists($param, $params)) { | 
		
	
		
			
				|  |  |  |  | 				throw new InvalidHeaderError("$param was not specified"); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (array_key_exists('headers', $params)) { | 
		
	
		
			
				|  |  |  |  | 			$params['headers'] = explode(' ', $params['headers']); | 
		
	
		
			
				|  |  |  |  | 		} else { | 
		
	
		
			
				|  |  |  |  | 			$params['headers'] = array(isset($headers['x-date']) ? 'x-date' : 'date'); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		foreach ($options['headers'] as $header) { | 
		
	
		
			
				|  |  |  |  | 			if (!in_array($header, $params['headers'])) { | 
		
	
		
			
				|  |  |  |  | 				throw new MissingHeaderError("$header was not a signed header"); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (isset($options['algorithms']) && !in_array($params['algorithm'], $options['algorithms'])) { | 
		
	
		
			
				|  |  |  |  | 			throw new InvalidParamsError($params['algorithm'] . " is not a supported algorithm"); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		$date = null; | 
		
	
		
			
				|  |  |  |  | 		if (isset($headers['date'])) { | 
		
	
		
			
				|  |  |  |  | 			$date = strtotime($headers['date']); | 
		
	
		
			
				|  |  |  |  | 		} elseif (isset($headers['x-date'])) { | 
		
	
		
			
				|  |  |  |  | 			$date = strtotime($headers['x-date']); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		if (!is_null($date)) { | 
		
	
		
			
				|  |  |  |  | 			if ($date === FALSE) { | 
		
	
		
			
				|  |  |  |  | 				throw new InvalidHeaderError('unable to parse date header'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			$skew = abs(time() - $date); | 
		
	
		
			
				|  |  |  |  | 			if ($skew > $options['clockSkew']) { | 
		
	
		
			
				|  |  |  |  | 				throw new ExpiredRequestError(sprintf("clock skew of %ds was greater than %ds", $skew, $options['clockSkew'])); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		$sign = array(); | 
		
	
		
			
				|  |  |  |  | 		foreach ($params['headers'] as $header) { | 
		
	
		
			
				|  |  |  |  | 			$sign[] = $header === 'request-line' ? $headers['request-line'] : sprintf("%s: %s", $header, $headers[$header]); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		return (array('scheme' => $scheme, 'params' => $params, 'signingString' => implode("\n", $sign))); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	static function verify(array $res, $key, $keytype) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		if (!is_string($key)) { | 
		
	
		
			
				|  |  |  |  | 			throw new Exception('key is not a string'); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		$alg = explode('-', $res['params']['algorithm'], 2); | 
		
	
		
			
				|  |  |  |  | 		if (sizeof($alg) != 2) { | 
		
	
		
			
				|  |  |  |  | 			throw new InvalidAlgorithmError("unsupported algorithm"); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		if ($alg[0] != $keytype) { | 
		
	
		
			
				|  |  |  |  | 			throw new InvalidAlgorithmError("algorithm type doesn't match key type"); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		switch ($alg[0]) { | 
		
	
		
			
				|  |  |  |  | 		case 'rsa': | 
		
	
		
			
				|  |  |  |  | 			$map = array('sha1' => OPENSSL_ALGO_SHA1, 'sha256' => OPENSSL_ALGO_SHA256, 'sha512' => OPENSSL_ALGO_SHA512); | 
		
	
		
			
				|  |  |  |  | 			if (!array_key_exists($alg[1], $map)) { | 
		
	
		
			
				|  |  |  |  | 				throw new InvalidAlgorithmError('unsupported algorithm'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			$pkey = openssl_get_publickey($key); | 
		
	
		
			
				|  |  |  |  | 			if ($pkey === FALSE) { | 
		
	
		
			
				|  |  |  |  | 				throw new Exception('key could not be parsed'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			$rv = openssl_verify($res['signingString'], base64_decode($res['params']['signature']), $pkey, $map[$alg[1]]); | 
		
	
		
			
				|  |  |  |  | 			openssl_free_key($pkey); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			switch ($rv) { | 
		
	
		
			
				|  |  |  |  | 			case 0: | 
		
	
		
			
				|  |  |  |  | 				return (FALSE); | 
		
	
		
			
				|  |  |  |  | 			case 1: | 
		
	
		
			
				|  |  |  |  | 				return (TRUE); | 
		
	
		
			
				|  |  |  |  | 			default: | 
		
	
		
			
				|  |  |  |  | 				throw new Exception('key could not be verified'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		case 'hmac': | 
		
	
		
			
				|  |  |  |  | 			return (hash_hmac($alg[1], $res['signingString'], $key, true) === base64_decode($res['params']['signature'])); | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  | 		default: | 
		
	
		
			
				|  |  |  |  | 			throw new InvalidAlgorithmError("unsupported algorithm"); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	static function sign(&$headers = array(), array $options = array()) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		if (is_null($headers)) { | 
		
	
		
			
				|  |  |  |  | 			$headers = array(); | 
		
	
		
			
				|  |  |  |  | 		} elseif (!is_array($headers)) { | 
		
	
		
			
				|  |  |  |  | 			throw new Exception('headers are not an array'); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (!array_key_exists('keyId', $options)) { | 
		
	
		
			
				|  |  |  |  | 			throw new Exception('keyId option is missing'); | 
		
	
		
			
				|  |  |  |  | 		} elseif (!is_string($options['keyId'])) { | 
		
	
		
			
				|  |  |  |  | 			throw new Exception('keyId option is not a string'); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		if (!array_key_exists('key', $options)) { | 
		
	
		
			
				|  |  |  |  | 			throw new Exception('key option is missing'); | 
		
	
		
			
				|  |  |  |  | 		} elseif (!is_string($options['key'])) { | 
		
	
		
			
				|  |  |  |  | 			throw new Exception('key option is not a string'); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (!array_key_exists('headers', $options)) { | 
		
	
		
			
				|  |  |  |  | 			$options['headers'] = array('date'); | 
		
	
		
			
				|  |  |  |  | 		} else { | 
		
	
		
			
				|  |  |  |  | 			if (!is_array($options['headers'])) { | 
		
	
		
			
				|  |  |  |  | 				throw new Exception('headers option is not an array'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			if (sizeof(array_filter($options['headers'], function ($a) { return (!is_string($a)); }))) { | 
		
	
		
			
				|  |  |  |  | 				throw new Exception('headers option is not an array of strings'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (!array_key_exists('algorithm', $options)) { | 
		
	
		
			
				|  |  |  |  | 			$options['algorithm'] = 'rsa-sha256'; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (!array_key_exists('date', $headers)) { | 
		
	
		
			
				|  |  |  |  | 			$headers['date'] = date(DATE_RFC1123); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		$headers['request-line'] = array_key_exists('requestLine', $options) ? | 
		
	
		
			
				|  |  |  |  | 		    $options['requestLine'] : | 
		
	
		
			
				|  |  |  |  | 		    sprintf("%s %s %s", $_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'], $_SERVER['SERVER_PROTOCOL']); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		$sign = array(); | 
		
	
		
			
				|  |  |  |  | 		foreach ($options['headers'] as $header) { | 
		
	
		
			
				|  |  |  |  | 			if (!array_key_exists($header, $headers)) { | 
		
	
		
			
				|  |  |  |  | 				throw new MissingHeaderError("$header was not in the request"); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			$sign[] = $header === 'request-line' ? $headers['request-line'] : sprintf("%s: %s", $header, $headers[$header]); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		$data = join("\n", $sign); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		$alg = explode('-', $options['algorithm'], 2); | 
		
	
		
			
				|  |  |  |  | 		if (sizeof($alg) != 2) { | 
		
	
		
			
				|  |  |  |  | 			throw new InvalidAlgorithmError("unsupported algorithm"); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		switch ($alg[0]) { | 
		
	
		
			
				|  |  |  |  | 		case 'rsa': | 
		
	
		
			
				|  |  |  |  | 			$map = array('sha1' => OPENSSL_ALGO_SHA1, 'sha256' => OPENSSL_ALGO_SHA256, 'sha512' => OPENSSL_ALGO_SHA512); | 
		
	
		
			
				|  |  |  |  | 			if (!array_key_exists($alg[1], $map)) { | 
		
	
		
			
				|  |  |  |  | 				throw new InvalidAlgorithmError('unsupported algorithm'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			$key = openssl_get_privatekey($options['key']); | 
		
	
		
			
				|  |  |  |  | 			if ($key === FALSE) { | 
		
	
		
			
				|  |  |  |  | 				error_log(openssl_error_string()); | 
		
	
		
			
				|  |  |  |  | 				throw new Exception('key option could not be parsed'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			if (openssl_sign($data, $signature, $key, $map[$alg[1]]) === FALSE) { | 
		
	
		
			
				|  |  |  |  | 				throw new Exception('unable to sign'); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		case 'hmac': | 
		
	
		
			
				|  |  |  |  | 			$signature = hash_hmac($alg[1], $data, $options['key'], true); | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  | 		default: | 
		
	
		
			
				|  |  |  |  | 			throw new InvalidAlgorithmError("unsupported algorithm"); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		unset($headers['request-line']); | 
		
	
		
			
				|  |  |  |  | 		$headers['authorization'] = sprintf('Signature keyId="%s",algorithm="%s",headers="%s",signature="%s"', | 
		
	
		
			
				|  |  |  |  | 		    $options['keyId'], $options['algorithm'], implode(' ', $options['headers']), | 
		
	
		
			
				|  |  |  |  | 		    base64_encode($signature)); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } |