Keys/PuTTY: better support RFC4716 keys

This commit is contained in:
terrafrost 2020-01-19 02:09:39 -06:00
parent 14c09f8527
commit 2b28c3814b
3 changed files with 53 additions and 9 deletions

View File

@ -186,7 +186,7 @@ abstract class OpenSSH
private static function checkType($candidate)
{
if (!in_array($candidate, static::$types)) {
throw new \RuntimeException('The key type is not equal to: ' . implode(',', static::$types));
throw new \RuntimeException("The key type ($candidate) is not equal to: " . implode(',', static::$types));
}
}

View File

@ -85,19 +85,42 @@ abstract class PuTTY
}
if (strpos($key, 'BEGIN SSH2 PUBLIC KEY') !== false) {
$data = preg_split('#[\r\n]+#', $key);
$data = array_splice($data, 2, -1);
$data = implode('', $data);
$lines = preg_split('#[\r\n]+#', $key);
switch (true) {
case $lines[0] != '---- BEGIN SSH2 PUBLIC KEY ----':
throw new \UnexpectedValueException('Key doesn\'t start with ---- BEGIN SSH2 PUBLIC KEY ----');
case $lines[count($lines) - 1] != '---- END SSH2 PUBLIC KEY ----':
throw new \UnexpectedValueException('Key doesn\'t end with ---- END SSH2 PUBLIC KEY ----');
}
$lines = array_splice($lines, 1, -1);
$lines = array_map(function ($line) {
return rtrim($line, "\r\n");
}, $lines);
$data = $current = '';
$values = [];
$in_value = false;
foreach ($lines as $line) {
switch (true) {
case preg_match('#^(.*?): (.*)#', $line, $match):
$in_value = $line[strlen($line) - 1] == '\\';
$current = strtolower($match[1]);
$values[$current] = $in_value ? substr($match[2], 0, -1) : $match[2];
break;
case $in_value:
$in_value = $line[strlen($line) - 1] == '\\';
$values[$current].= $in_value ? substr($line, 0, -1) : $line;
break;
default:
$data.= $line;
}
}
$components = call_user_func([static::PUBLIC_HANDLER, 'load'], $data);
if ($components === false) {
throw new \UnexpectedValueException('Unable to decode public key');
}
if (!preg_match('#Comment: "(.+)"#', $key, $matches)) {
throw new \UnexpectedValueException('Key is missing a comment');
}
$components['comment'] = str_replace(['\\\\', '\"'], ['\\', '"'], $matches[1]);
$components+= $values;
$components['comment'] = str_replace(['\\\\', '\"'], ['\\', '"'], $values['comment']);
return $components;
}

View File

@ -993,5 +993,26 @@ AAAAB3NzaC1yc2EAAAADAQABAAAAQQCo9+BpMRYQ/dL3DS2CyJxRF+j6ctbT3/Qp
$key = PublicKeyLoader::load($orig);
$this->assertSame($orig, $key->toString('PuTTY'));
$key = '---- BEGIN SSH2 PUBLIC KEY ----
Subject: me
Comment: 1024-bit rsa, created by me@example.com Mon Jan 15 \
08:31:24 2001
AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=
---- END SSH2 PUBLIC KEY ----';
$key = PublicKeyLoader::load($key);
$this->assertInstanceOf(PublicKey::class, $key);
$key = '---- BEGIN SSH2 PUBLIC KEY ----
Comment: "1024-bit RSA, converted from OpenSSH by me@example.com"
x-command: /home/me/bin/lock-in-guest.sh
AAAAB3NzaC1yc2EAAAABIwAAAIEA1on8gxCGJJWSRT4uOrR13mUaUk0hRf4RzxSZ1zRb
YYFw8pfGesIFoEuVth4HKyF8k1y4mRUnYHP1XNMNMJl1JcEArC2asV8sHf6zSPVffozZ
5TT4SfsUu/iKy9lUcCfXzwre4WWZSXXcPff+EHtWshahu3WzBdnGxm5Xoi89zcE=
---- END SSH2 PUBLIC KEY ----';
$key = PublicKeyLoader::load($key);
$this->assertInstanceOf(PublicKey::class, $key);
}
}