RsaSha1.php 4.65 KB
Newer Older
1 2 3 4 5 6 7
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

8
namespace yii\authclient\signature;
9 10 11 12 13 14 15 16 17

use yii\base\InvalidConfigException;
use yii\base\NotSupportedException;

/**
 * RsaSha1 represents 'RSA-SHA1' signature method.
 *
 * Note: This class require PHP "OpenSSL" extension({@link http://php.net/manual/en/book.openssl.php}).
 *
Qiang Xue committed
18 19
 * @property string $privateCertificate Private key certificate content.
 * @property string $publicCertificate Public key certificate content.
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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
 *
 * @author Paul Klimov <klimov.paul@gmail.com>
 * @since 2.0
 */
class RsaSha1 extends BaseMethod
{
	/**
	 * @var string OpenSSL private key certificate content.
	 * This value can be fetched from file specified by {@link privateCertificateFile}.
	 */
	protected $_privateCertificate;
	/**
	 * @var string OpenSSL public key certificate content.
	 * This value can be fetched from file specified by {@link publicCertificateFile}.
	 */
	protected $_publicCertificate;
	/**
	 * @var string path to the file, which holds private key certificate.
	 */
	public $privateCertificateFile = '';
	/**
	 * @var string path to the file, which holds public key certificate.
	 */
	public $publicCertificateFile = '';

	/**
	 * @inheritdoc
	 */
	public function init()
	{
		if (!function_exists('openssl_sign')) {
			throw new NotSupportedException('PHP "OpenSSL" extension is required.');
		}
	}

	/**
	 * @param string $publicCertificate public key certificate content.
	 */
	public function setPublicCertificate($publicCertificate)
	{
		$this->_publicCertificate = $publicCertificate;
	}

	/**
	 * @return string public key certificate content.
	 */
	public function getPublicCertificate()
	{
		if ($this->_publicCertificate === null) {
			$this->_publicCertificate = $this->initPublicCertificate();
		}
		return $this->_publicCertificate;
	}

	/**
	 * @param string $privateCertificate private key certificate content.
	 */
	public function setPrivateCertificate($privateCertificate)
	{
		$this->_privateCertificate = $privateCertificate;
	}

	/**
	 * @return string private key certificate content.
	 */
	public function getPrivateCertificate()
	{
		if ($this->_privateCertificate === null) {
			$this->_privateCertificate = $this->initPrivateCertificate();
		}
		return $this->_privateCertificate;
	}

	/**
	 * @inheritdoc
	 */
	public function getName()
	{
		return 'RSA-SHA1';
	}

	/**
	 * Creates initial value for {@link publicCertificate}.
	 * This method will attempt to fetch the certificate value from {@link publicCertificateFile} file.
	 * @throws InvalidConfigException on failure.
	 * @return string public certificate content.
	 */
	protected function initPublicCertificate()
	{
		if (!empty($this->publicCertificateFile)) {
			if (!file_exists($this->publicCertificateFile)) {
				throw new InvalidConfigException("Public certificate file '{$this->publicCertificateFile}' does not exist!");
			}
			return file_get_contents($this->publicCertificateFile);
		} else {
			return '';
		}
	}

	/**
	 * Creates initial value for {@link privateCertificate}.
	 * This method will attempt to fetch the certificate value from {@link privateCertificateFile} file.
	 * @throws InvalidConfigException on failure.
	 * @return string private certificate content.
	 */
	protected function initPrivateCertificate()
	{
		if (!empty($this->privateCertificateFile)) {
			if (!file_exists($this->privateCertificateFile)) {
				throw new InvalidConfigException("Private certificate file '{$this->privateCertificateFile}' does not exist!");
			}
			return file_get_contents($this->privateCertificateFile);
		} else {
			return '';
		}
	}

	/**
	 * @inheritdoc
	 */
	public function generateSignature($baseString, $key)
	{
		$privateCertificateContent = $this->getPrivateCertificate();
		// Pull the private key ID from the certificate
		$privateKeyId = openssl_pkey_get_private($privateCertificateContent);
		// Sign using the key
		openssl_sign($baseString, $signature, $privateKeyId);
		// Release the key resource
		openssl_free_key($privateKeyId);
		return base64_encode($signature);
	}

	/**
	 * @inheritdoc
	 */
	public function verify($signature, $baseString, $key)
	{
		$decodedSignature = base64_decode($signature);
		// Fetch the public key cert based on the request
		$publicCertificate = $this->getPublicCertificate();
		// Pull the public key ID from the certificate
		$publicKeyId = openssl_pkey_get_public($publicCertificate);
		// Check the computed signature against the one passed in the query
		$verificationResult = openssl_verify($baseString, $decodedSignature, $publicKeyId);
		// Release the key resource
		openssl_free_key($publicKeyId);
		return ($verificationResult == 1);
	}
}