33 $this->interfaces = array(
34 'MAC' =>
'\\fpoirotte\\Pssht\\MAC\\MACInterface',
35 'Compression' =>
'\\fpoirotte\\Pssht\\Compression\\CompressionInterface',
36 'Key' =>
'\\fpoirotte\\Pssht\\Key\\KeyInterface',
37 'KEX' =>
'\\fpoirotte\\Pssht\\KEX\\KEXInterface',
38 'Encryption' =>
'\\fpoirotte\\Pssht\\Encryption\\EncryptionInterface',
43 'Compression' => array(),
46 'Encryption' => array(),
49 $logging = \Plop\Plop::getInstance();
50 foreach (array_keys($this->algos) as $type) {
51 $it = new \RecursiveIteratorIterator(
52 new \RecursiveDirectoryIterator(
53 __DIR__ . DIRECTORY_SEPARATOR . $type,
54 \FilesystemIterator::UNIX_PATHS |
55 \FilesystemIterator::KEY_AS_PATHNAME |
56 \FilesystemIterator::CURRENT_AS_FILEINFO |
57 \FilesystemIterator::SKIP_DOTS
60 $dirLen = strlen(__DIR__ . DIRECTORY_SEPARATOR . $type);
61 foreach ($it as $entry) {
62 if (!$entry->isFile()) {
66 if (substr($entry->getBasename(), -4) !==
'.php') {
70 $name = (string) substr($entry->getPathname(), $dirLen, -4);
71 $name = str_replace(
'/',
'\\', $name);
73 if ($class === null) {
83 'Adding "%(algo)s" (from %(class)s) to supported %(type)s algorithms',
84 array(
'type' => $type,
'algo' => $algo,
'class' => $class)
86 $this->algos[$type][$algo] = $class;
88 uksort($this->algos[$type], array(
'self',
'sortAlgorithms'));
96 throw new \RuntimeException();
107 static $instance = null;
108 if ($instance === null) {
109 $instance =
new static();
131 $logging = \Plop\Plop::getInstance();
132 $w =
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890\\';
133 if (!is_string($name) || strspn($name, $w) !== strlen($name)) {
135 'Skipping %(type)s algorithm "%(name)s" (invalid class name)',
136 array(
'type' => $type,
'name' => $name)
142 $class =
"\\fpoirotte\\Pssht\\$type$name";
143 if (!class_exists($class)) {
144 if (!interface_exists($class)) {
146 'Skipping %(type)s algorithm "%(name)s" (class does not exist)',
147 array(
'type' => $type,
'name' => $name)
154 $reflector = new \ReflectionClass($class);
155 if ($reflector->isAbstract()) {
161 $iface =
'\\fpoirotte\\Pssht\\Algorithms\\AvailabilityInterface';
162 if ($reflector->implementsInterface($iface) && !$class::isAvailable()) {
164 'Skipping %(type)s algorithm "%(name)s" (not available)',
165 array(
'type' => $type,
'name' => $name)
171 $iface = $this->interfaces[$type];
172 if ($iface !== null && !$reflector->implementsInterface($iface)) {
174 'Skipping %(type)s algorithm "%(name)s" (invalid interface)',
175 array(
'type' => $type,
'name' => $name)
197 $logging = \Plop\Plop::getInstance();
198 $w =
'abcdefghijklmnopqrstuvwxyz' .
199 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' .
201 $name = $class::getName();
202 if (!is_string($name) || strspn($name, $w) !== strlen($name)) {
204 'Skipping algorithm "%(name)s" (invalid algorithm name)',
205 array(
'name' => $name)
229 public function register($type, $class)
231 if (is_object($class)) {
232 $class = get_class($class);
234 if (!is_string($class) || !class_exists($class)) {
235 throw new \InvalidArgumentException();
237 if (!is_string($type) || !isset($this->algos[$type])) {
238 throw new \InvalidArgumentException();
241 if ($name === null) {
242 throw new \InvalidArgumentException();
245 $this->algos[$type][$name] = $class;
246 uksort($this->algos[$type], array(
'self',
'sortAlgorithms'));
264 if (!is_string($type) || !isset($this->algos[$type])) {
265 throw new \InvalidArgumentException();
267 if (!is_string($name)) {
268 throw new \InvalidArgumentException();
270 unset($this->algos[$type][$name]);
291 if (!is_string($type) || !isset($this->algos[$type])) {
292 throw new \InvalidArgumentException();
294 if (isset($this->savedAlgos[$type][$name])) {
295 $this->algos[$type][$name] = $this->savedAlgos[$type][$name];
313 if (!is_string($type) || !isset($this->algos[$type])) {
314 throw new \InvalidArgumentException();
316 return array_keys($this->algos[$type]);
332 if (!is_string($type) || !isset($this->algos[$type])) {
333 throw new \InvalidArgumentException();
335 return $this->algos[$type];
358 if (!is_string($type) || !isset($this->algos[$type])) {
359 throw new \InvalidArgumentException();
361 if (!is_string($name)) {
362 throw new \InvalidArgumentException();
364 if (!isset($this->algos[$type][$name])) {
367 return $this->algos[$type][$name];
387 static $preferences = array(
389 'curve25519-sha256@libssh.org',
390 'ecdh-sha2-nistp256',
391 'ecdh-sha2-nistp384',
392 'ecdh-sha2-nistp521',
393 'diffie-hellman-group-exchange-sha256',
394 'diffie-hellman-group-exchange-sha1',
395 'diffie-hellman-group14-sha1',
396 'diffie-hellman-group1-sha1',
399 'ecdsa-sha2-nistp256-cert-v01@openssh.com',
400 'ecdsa-sha2-nistp384-cert-v01@openssh.com',
401 'ecdsa-sha2-nistp521-cert-v01@openssh.com',
402 'ecdsa-sha2-nistp256',
403 'ecdsa-sha2-nistp384',
404 'ecdsa-sha2-nistp521',
405 'ssh-ed25519-cert-v01@openssh.com',
406 'ssh-rsa-cert-v01@openssh.com',
407 'ssh-dss-cert-v01@openssh.com',
408 'ssh-rsa-cert-v00@openssh.com',
409 'ssh-dss-cert-v00@openssh.com',
418 'aes128-gcm@openssh.com',
419 'aes256-gcm@openssh.com',
420 'chacha20-poly1305@openssh.com',
430 'rijndael-cbc@lysator.liu.se',
433 'umac-64-etm@openssh.com',
434 'umac-128-etm@openssh.com',
435 'hmac-sha2-256-etm@openssh.com',
436 'hmac-sha2-512-etm@openssh.com',
437 'hmac-sha1-etm@openssh.com',
438 'umac-64@openssh.com',
439 'umac-128@openssh.com',
443 'hmac-md5-etm@openssh.com',
444 'hmac-ripemd160-etm@openssh.com',
445 'hmac-sha1-96-etm@openssh.com',
446 'hmac-md5-96-etm@openssh.com',
449 'hmac-ripemd160@openssh.com',
459 $iA = array_search($a, $preferences,
true);
460 $iB = array_search($b, $preferences,
true);
462 return ($iB ===
false ? 0 : 1);
$algos
Array with currently available algorithms.
$interfaces
Mapping between algorithm types and their corresponding interface.
getValidAlgorithm($class)
getValidClass($type, $name)
$savedAlgos
A backup of $algos when it was first populated.
__clone()
Prevent cloning of the singleton.
static sortAlgorithms($a, $b)