198 lines
5.3 KiB
PHP
198 lines
5.3 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* @package Joomla.Platform
|
||
|
* @subpackage Keychain
|
||
|
*
|
||
|
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved
|
||
|
* @license GNU General Public License version 2 or later; see LICENSE
|
||
|
*/
|
||
|
|
||
|
defined('JPATH_PLATFORM') or die;
|
||
|
|
||
|
/**
|
||
|
* Keychain Class
|
||
|
*
|
||
|
* @package Joomla.Platform
|
||
|
* @subpackage Keychain
|
||
|
* @since 12.3
|
||
|
*/
|
||
|
class JKeychain extends JRegistry
|
||
|
{
|
||
|
/**
|
||
|
* @var string Method to use for encryption.
|
||
|
* @since 12.3
|
||
|
*/
|
||
|
public $method = 'aes-128-cbc';
|
||
|
|
||
|
/**
|
||
|
* @var string Initialisation vector for encryption method.
|
||
|
* @since 12.3
|
||
|
*/
|
||
|
public $iv = "1234567890123456";
|
||
|
|
||
|
/**
|
||
|
* Create a passphrase file
|
||
|
*
|
||
|
* @param string $passphrase The passphrase to store in the passphrase file.
|
||
|
* @param string $passphraseFile Path to the passphrase file to create.
|
||
|
* @param string $privateKeyFile Path to the private key file to encrypt the passphrase file.
|
||
|
* @param string $privateKeyPassphrase The passphrase for the private key.
|
||
|
*
|
||
|
* @return boolean Result of writing the passphrase file to disk.
|
||
|
*
|
||
|
* @since 12.3
|
||
|
* @throws RuntimeException
|
||
|
*/
|
||
|
public function createPassphraseFile($passphrase, $passphraseFile, $privateKeyFile, $privateKeyPassphrase)
|
||
|
{
|
||
|
$privateKey = openssl_get_privatekey(file_get_contents($privateKeyFile), $privateKeyPassphrase);
|
||
|
|
||
|
if (!$privateKey)
|
||
|
{
|
||
|
throw new RuntimeException("Failed to load private key.");
|
||
|
}
|
||
|
|
||
|
$crypted = '';
|
||
|
|
||
|
if (!openssl_private_encrypt($passphrase, $crypted, $privateKey))
|
||
|
{
|
||
|
throw new RuntimeException("Failed to encrypt data using private key.");
|
||
|
}
|
||
|
|
||
|
return file_put_contents($passphraseFile, $crypted);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Delete a registry value (very simple method)
|
||
|
*
|
||
|
* @param string $path Registry Path (e.g. joomla.content.showauthor)
|
||
|
*
|
||
|
* @return mixed Value of old value or boolean false if operation failed
|
||
|
*
|
||
|
* @since 12.3
|
||
|
*/
|
||
|
public function deleteValue($path)
|
||
|
{
|
||
|
$result = null;
|
||
|
|
||
|
// Explode the registry path into an array
|
||
|
$nodes = explode('.', $path);
|
||
|
|
||
|
if ($nodes)
|
||
|
{
|
||
|
// Initialize the current node to be the registry root.
|
||
|
$node = $this->data;
|
||
|
|
||
|
// Traverse the registry to find the correct node for the result.
|
||
|
for ($i = 0, $n = count($nodes) - 1; $i < $n; $i++)
|
||
|
{
|
||
|
if (!isset($node->$nodes[$i]) && ($i != $n))
|
||
|
{
|
||
|
$node->$nodes[$i] = new stdClass;
|
||
|
}
|
||
|
$node = $node->$nodes[$i];
|
||
|
}
|
||
|
|
||
|
// Get the old value if exists so we can return it
|
||
|
$result = $node->$nodes[$i];
|
||
|
unset($node->$nodes[$i]);
|
||
|
}
|
||
|
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Load a keychain file into this object.
|
||
|
*
|
||
|
* @param string $keychainFile Path to the keychain file.
|
||
|
* @param string $passphraseFile The path to the passphrase file to decript the keychain.
|
||
|
* @param string $publicKeyFile The file containing the public key to decrypt the passphrase file.
|
||
|
*
|
||
|
* @return boolean Result of loading the object.
|
||
|
*
|
||
|
* @since 12.3
|
||
|
* @throws RuntimeException
|
||
|
*/
|
||
|
public function loadKeychain($keychainFile, $passphraseFile, $publicKeyFile)
|
||
|
{
|
||
|
if (!file_exists($keychainFile))
|
||
|
{
|
||
|
throw new RuntimeException('Attempting to load non-existent keychain file');
|
||
|
}
|
||
|
$passphrase = $this->getPassphraseFromFile($passphraseFile, $publicKeyFile);
|
||
|
|
||
|
$cleartext = openssl_decrypt(file_get_contents($keychainFile), $this->method, $passphrase, true, $this->iv);
|
||
|
|
||
|
if ($cleartext === false)
|
||
|
{
|
||
|
throw new RuntimeException("Failed to decrypt keychain file");
|
||
|
}
|
||
|
|
||
|
return $this->loadObject(json_decode($cleartext));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Save this keychain to a file.
|
||
|
*
|
||
|
* @param string $keychainFile The path to the keychain file.
|
||
|
* @param string $passphraseFile The path to the passphrase file to encrypt the keychain.
|
||
|
* @param string $publicKeyFile The file containing the public key to decrypt the passphrase file.
|
||
|
*
|
||
|
* @return boolean Result of storing the file.
|
||
|
*
|
||
|
* @since 12.3
|
||
|
* @throws RuntimeException
|
||
|
*/
|
||
|
public function saveKeychain($keychainFile, $passphraseFile, $publicKeyFile)
|
||
|
{
|
||
|
$passphrase = $this->getPassphraseFromFile($passphraseFile, $publicKeyFile);
|
||
|
$data = $this->toString('JSON');
|
||
|
|
||
|
$encrypted = @openssl_encrypt($data, $this->method, $passphrase, true, $this->iv);
|
||
|
|
||
|
if ($encrypted === false)
|
||
|
{
|
||
|
throw new RuntimeException('Unable to encrypt keychain');
|
||
|
}
|
||
|
|
||
|
return file_put_contents($keychainFile, $encrypted);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the passphrase for this keychain
|
||
|
*
|
||
|
* @param string $passphraseFile The file containing the passphrase to encrypt and decrypt.
|
||
|
* @param string $publicKeyFile The file containing the public key to decrypt the passphrase file.
|
||
|
*
|
||
|
* @return string The passphrase in from passphraseFile
|
||
|
*
|
||
|
* @since 12.3
|
||
|
* @throws RuntimeException
|
||
|
*/
|
||
|
protected function getPassphraseFromFile($passphraseFile, $publicKeyFile)
|
||
|
{
|
||
|
if (!file_exists($publicKeyFile))
|
||
|
{
|
||
|
throw new RuntimeException('Missing public key file');
|
||
|
}
|
||
|
$publicKey = openssl_get_publickey(file_get_contents($publicKeyFile));
|
||
|
|
||
|
if (!$publicKey)
|
||
|
{
|
||
|
throw new RuntimeException("Failed to load public key.");
|
||
|
}
|
||
|
|
||
|
if (!file_exists($passphraseFile))
|
||
|
{
|
||
|
throw new RuntimeException('Missing passphrase file');
|
||
|
}
|
||
|
$passphrase = '';
|
||
|
|
||
|
if (!openssl_public_decrypt(file_get_contents($passphraseFile), $passphrase, $publicKey))
|
||
|
{
|
||
|
throw new RuntimeException('Failed to decrypt passphrase file');
|
||
|
}
|
||
|
return $passphrase;
|
||
|
}
|
||
|
}
|