|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* @link http://www.yiiframework.com/
|
|
|
|
* @copyright Copyright (c) 2008 Yii Software LLC
|
|
|
|
* @license http://www.yiiframework.com/license/
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace yii\authclient\signature;
|
|
|
|
|
|
|
|
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}).
|
|
|
|
*
|
|
|
|
* @property string $privateCertificate Private key certificate content.
|
|
|
|
* @property string $publicCertificate Public key certificate content.
|
|
|
|
*
|
|
|
|
* @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);
|
|
|
|
}
|
|
|
|
}
|