1 <?php
2 /**
3 * @package Joomla.Platform
4 * @subpackage Keychain
5 *
6 * @copyright Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved
7 * @license GNU General Public License version 2 or later; see LICENSE
8 */
9
10 defined('JPATH_PLATFORM') or die;
11
12 /**
13 * Keychain Class
14 *
15 * @since 12.3
16 * @deprecated 4.0 Deprecated without replacement
17 */
18 class JKeychain extends \Joomla\Registry\Registry
19 {
20 /**
21 * @var string Method to use for encryption.
22 * @since 12.3
23 */
24 public $method = 'aes-128-cbc';
25
26 /**
27 * @var string Initialisation vector for encryption method.
28 * @since 12.3
29 */
30 public $iv = '1234567890123456';
31
32 /**
33 * Create a passphrase file
34 *
35 * @param string $passphrase The passphrase to store in the passphrase file.
36 * @param string $passphraseFile Path to the passphrase file to create.
37 * @param string $privateKeyFile Path to the private key file to encrypt the passphrase file.
38 * @param string $privateKeyPassphrase The passphrase for the private key.
39 *
40 * @return boolean Result of writing the passphrase file to disk.
41 *
42 * @since 12.3
43 * @throws RuntimeException
44 */
45 public function createPassphraseFile($passphrase, $passphraseFile, $privateKeyFile, $privateKeyPassphrase)
46 {
47 $privateKey = openssl_get_privatekey(file_get_contents($privateKeyFile), $privateKeyPassphrase);
48
49 if (!$privateKey)
50 {
51 throw new RuntimeException('Failed to load private key.');
52 }
53
54 $crypted = '';
55
56 if (!openssl_private_encrypt($passphrase, $crypted, $privateKey))
57 {
58 throw new RuntimeException('Failed to encrypt data using private key.');
59 }
60
61 return file_put_contents($passphraseFile, $crypted);
62 }
63
64 /**
65 * Delete a registry value (very simple method)
66 *
67 * @param string $path Registry Path (e.g. joomla.content.showauthor)
68 *
69 * @return mixed Value of old value or boolean false if operation failed
70 *
71 * @since 12.3
72 */
73 public function deleteValue($path)
74 {
75 $result = null;
76
77 // Explode the registry path into an array
78 $nodes = explode('.', $path);
79
80 if ($nodes)
81 {
82 // Initialize the current node to be the registry root.
83 $node = $this->data;
84
85 // Traverse the registry to find the correct node for the result.
86 for ($i = 0, $n = count($nodes) - 1; $i < $n; $i++)
87 {
88 if (!isset($node->{$nodes[$i]}) && ($i != $n))
89 {
90 $node->{$nodes[$i]} = new stdClass;
91 }
92
93 $node = $node->{$nodes[$i]};
94 }
95
96 // Get the old value if exists so we can return it
97 $result = $node->{$nodes[$i]};
98 unset($node->{$nodes[$i]});
99 }
100
101 return $result;
102 }
103
104 /**
105 * Load a keychain file into this object.
106 *
107 * @param string $keychainFile Path to the keychain file.
108 * @param string $passphraseFile The path to the passphrase file to decript the keychain.
109 * @param string $publicKeyFile The file containing the public key to decrypt the passphrase file.
110 *
111 * @return boolean Result of loading the object.
112 *
113 * @since 12.3
114 * @throws RuntimeException
115 */
116 public function loadKeychain($keychainFile, $passphraseFile, $publicKeyFile)
117 {
118 if (!file_exists($keychainFile))
119 {
120 throw new RuntimeException('Attempting to load non-existent keychain file');
121 }
122
123 $passphrase = $this->getPassphraseFromFile($passphraseFile, $publicKeyFile);
124
125 $cleartext = openssl_decrypt(file_get_contents($keychainFile), $this->method, $passphrase, true, $this->iv);
126
127 if ($cleartext === false)
128 {
129 throw new RuntimeException('Failed to decrypt keychain file');
130 }
131
132 return $this->loadObject(json_decode($cleartext));
133 }
134
135 /**
136 * Save this keychain to a file.
137 *
138 * @param string $keychainFile The path to the keychain file.
139 * @param string $passphraseFile The path to the passphrase file to encrypt the keychain.
140 * @param string $publicKeyFile The file containing the public key to decrypt the passphrase file.
141 *
142 * @return boolean Result of storing the file.
143 *
144 * @since 12.3
145 * @throws RuntimeException
146 */
147 public function saveKeychain($keychainFile, $passphraseFile, $publicKeyFile)
148 {
149 $passphrase = $this->getPassphraseFromFile($passphraseFile, $publicKeyFile);
150 $data = $this->toString('JSON');
151
152 $encrypted = @openssl_encrypt($data, $this->method, $passphrase, true, $this->iv);
153
154 if ($encrypted === false)
155 {
156 throw new RuntimeException('Unable to encrypt keychain');
157 }
158
159 return file_put_contents($keychainFile, $encrypted);
160 }
161
162 /**
163 * Get the passphrase for this keychain
164 *
165 * @param string $passphraseFile The file containing the passphrase to encrypt and decrypt.
166 * @param string $publicKeyFile The file containing the public key to decrypt the passphrase file.
167 *
168 * @return string The passphrase in from passphraseFile
169 *
170 * @since 12.3
171 * @throws RuntimeException
172 */
173 protected function getPassphraseFromFile($passphraseFile, $publicKeyFile)
174 {
175 if (!file_exists($publicKeyFile))
176 {
177 throw new RuntimeException('Missing public key file');
178 }
179
180 $publicKey = openssl_get_publickey(file_get_contents($publicKeyFile));
181
182 if (!$publicKey)
183 {
184 throw new RuntimeException('Failed to load public key.');
185 }
186
187 if (!file_exists($passphraseFile))
188 {
189 throw new RuntimeException('Missing passphrase file');
190 }
191
192 $passphrase = '';
193
194 if (!openssl_public_decrypt(file_get_contents($passphraseFile), $passphrase, $publicKey))
195 {
196 throw new RuntimeException('Failed to decrypt passphrase file');
197 }
198
199 return $passphrase;
200 }
201 }
202