mirror of https://github.com/huashengdun/webssh
Support openssh new format key
parent
3b649c0305
commit
ccb40d2bed
|
@ -0,0 +1,21 @@
|
|||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsQAAAAdzc2gtZH
|
||||
NzAAAAgQC5Y5rQ1EN+eWQUFv/9K/DLfPgjGC0mwyqvKsKyv6RLpKLc0vi0VDj8lY0WUcuG
|
||||
CzdYnhIOSa9aB0buGe10gIjU2vAxkhqv1yaR+Zuj3dLDHQk6jpAAgNHciKlQSf1zho/seL
|
||||
7nehYq/waXfU8/iJuXqywQgqpMLfaHOnIl/tPLGQAAABUArINMjWcrsmEgLmzf6k+sroko
|
||||
5GkAAACAMQsRQjOtQGQA8/XI7vOWnEMCVntwt1Xi4RsLH5+4GpUMUcm4CvqjfFfSF4CufH
|
||||
pjlywFhrAC2/ouQIpGJPGToWotk7dt5zWckGX5DscMiRVON7fxdpUMn16IO6DdUctXlWa9
|
||||
SY+NdfRESKoUCjgH5nlM8k7N2MwCK5phHHkoPu8AAACADgxrRWeNqX3gmZUM1qhrDO0mOH
|
||||
oHJFrBuvJCdQ6+S1GvjuBI0rNm225+gcaAhia9k/LGk8NwCbWG1FbpesuNaNFt/FxS9LVS
|
||||
qEaZoXtKuY+CUCn1BfBWF97/u0oMPwanXKIJEAhU81f5TXZM8Ui7OEIyTx1t9qgva+5/gF
|
||||
cL48kAAAHoLtDYCy7Q2AsAAAAHc3NoLWRzcwAAAIEAuWOa0NRDfnlkFBb//Svwy3z4Ixgt
|
||||
JsMqryrCsr+kS6Si3NL4tFQ4/JWNFlHLhgs3WJ4SDkmvWgdG7hntdICI1NrwMZIar9cmkf
|
||||
mbo93Swx0JOo6QAIDR3IipUEn9c4aP7Hi+53oWKv8Gl31PP4ibl6ssEIKqTC32hzpyJf7T
|
||||
yxkAAAAVAKyDTI1nK7JhIC5s3+pPrK6JKORpAAAAgDELEUIzrUBkAPP1yO7zlpxDAlZ7cL
|
||||
dV4uEbCx+fuBqVDFHJuAr6o3xX0heArnx6Y5csBYawAtv6LkCKRiTxk6FqLZO3bec1nJBl
|
||||
+Q7HDIkVTje38XaVDJ9eiDug3VHLV5VmvUmPjXX0REiqFAo4B+Z5TPJOzdjMAiuaYRx5KD
|
||||
7vAAAAgA4Ma0Vnjal94JmVDNaoawztJjh6ByRawbryQnUOvktRr47gSNKzZttufoHGgIYm
|
||||
vZPyxpPDcAm1htRW6XrLjWjRbfxcUvS1UqhGmaF7SrmPglAp9QXwVhfe/7tKDD8Gp1yiCR
|
||||
AIVPNX+U12TPFIuzhCMk8dbfaoL2vuf4BXC+PJAAAAFBVcac1iVzrWVnLglRZRenUhlKLr
|
||||
AAAADHNoZW5nQHNlcnZlcgECAwQFBgc=
|
||||
-----END OPENSSH PRIVATE KEY-----
|
|
@ -0,0 +1,39 @@
|
|||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
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
|
||||
PR/8/w==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
|
@ -196,6 +196,15 @@ class TestPrivateKey(unittest.TestCase):
|
|||
password = 'abc123'
|
||||
self._test_with_encrypted_key(fname, password, paramiko.Ed25519Key)
|
||||
|
||||
def test_get_pkey_obj_with_encrypted_new_rsa_key(self):
|
||||
fname = 'test_new_rsa_password.key'
|
||||
password = '123456'
|
||||
self._test_with_encrypted_key(fname, password, paramiko.RSAKey)
|
||||
|
||||
def test_get_pkey_obj_with_plain_new_dsa_key(self):
|
||||
pk = self.get_pk_obj('test_new_dsa.key')
|
||||
self.assertIsInstance(pk.get_pkey_obj(), paramiko.DSSKey)
|
||||
|
||||
def test_parse_name(self):
|
||||
key = u'-----BEGIN PRIVATE KEY-----'
|
||||
pk = PrivateKey(key)
|
||||
|
|
|
@ -118,6 +118,7 @@ class PrivateKey(object):
|
|||
self.password = password
|
||||
self.check_length()
|
||||
self.iostr = io.StringIO(privatekey)
|
||||
self.last_exception = None
|
||||
|
||||
def check_length(self):
|
||||
if len(self.privatekey) > self.max_length:
|
||||
|
@ -138,30 +139,49 @@ class PrivateKey(object):
|
|||
break
|
||||
return name, len(line_)
|
||||
|
||||
def get_specific_pkey(self, name, offset, password):
|
||||
self.iostr.seek(offset)
|
||||
logging.debug('Reset offset to {}.'.format(offset))
|
||||
|
||||
logging.debug('Try parsing it as {} type key'.format(name))
|
||||
pkeycls = getattr(paramiko, name+'Key')
|
||||
pkey = None
|
||||
|
||||
try:
|
||||
pkey = pkeycls.from_private_key(self.iostr, password=password)
|
||||
except paramiko.PasswordRequiredException:
|
||||
raise InvalidValueError('Need a passphrase to decrypt the key.')
|
||||
except (paramiko.SSHException, ValueError) as exc:
|
||||
self.last_exception = exc
|
||||
logging.debug(str(exc))
|
||||
|
||||
return pkey
|
||||
|
||||
def get_pkey_obj(self):
|
||||
logging.info('Parsing private key {!r}'.format(self.filename))
|
||||
name, length = self.parse_name(self.iostr, self.tag_to_name)
|
||||
if not name:
|
||||
raise InvalidValueError('Invalid key {}.'.format(self.filename))
|
||||
|
||||
offset = self.iostr.tell() - length
|
||||
self.iostr.seek(offset)
|
||||
logging.debug('Reset offset to {}.'.format(offset))
|
||||
|
||||
logging.info('Parsing {} key'.format(name))
|
||||
pkeycls = getattr(paramiko, name+'Key')
|
||||
password = to_bytes(self.password) if self.password else None
|
||||
pkey = self.get_specific_pkey(name, offset, password)
|
||||
|
||||
try:
|
||||
return pkeycls.from_private_key(self.iostr, password=password)
|
||||
except paramiko.PasswordRequiredException:
|
||||
raise InvalidValueError('Need a passphrase to decrypt the key.')
|
||||
except paramiko.SSHException as exc:
|
||||
logging.error(str(exc))
|
||||
msg = 'Invalid key'
|
||||
if self.password:
|
||||
msg += ' or wrong passphrase "{}" for decrypting it.'.format(
|
||||
self.password)
|
||||
raise InvalidValueError(msg)
|
||||
if pkey is None and name == 'Ed25519':
|
||||
for name in ['RSA', 'ECDSA', 'DSS']:
|
||||
pkey = self.get_specific_pkey(name, offset, password)
|
||||
if pkey:
|
||||
break
|
||||
|
||||
if pkey:
|
||||
return pkey
|
||||
|
||||
logging.error(str(self.last_exception))
|
||||
msg = 'Invalid key'
|
||||
if self.password:
|
||||
msg += ' or wrong passphrase "{}" for decrypting it.'.format(
|
||||
self.password)
|
||||
raise InvalidValueError(msg)
|
||||
|
||||
|
||||
class MixinHandler(object):
|
||||
|
|
Loading…
Reference in New Issue