Пример #1
0
def _get_dss_key_from_string(dsskeystr=None, password=None):
    from paramiko.dsskey import DSSKey, SSHException, BER, BERException, randpool, util
    from paramiko.pkey import base64, PasswordRequiredException

    class MyDSSKey(DSSKey):
        def __init__(self): pass

    self = MyDSSKey()

    tag = 'DSA'
    lines = dsskeystr.split('\n')
    # adapted from PKey._read_private_key_file()
    while True:
        start = 0
        while (start < len(lines)) and (lines[start].strip() != '-----BEGIN ' + tag + ' PRIVATE KEY-----'):
            start += 1
        if start >= len(lines):
            raise SSHException('not a valid ' + tag + ' private key file')
        # parse any headers first
        headers = {}
        start += 1
        while start < len(lines):
            l = lines[start].split(': ')
            if len(l) == 1:
                break
            headers[l[0].lower()] = l[1].strip()
            start += 1
        # find end
        end = start
        while (lines[end].strip() != '-----END ' + tag + ' PRIVATE KEY-----') and (end < len(lines)):
            end += 1
        # if we trudged to the end of the file, just try to cope.
        try:
            data = base64.decodestring(''.join(lines[start:end]))
        except base64.binascii.Error, e:
            raise SSHException('base64 decoding error: ' + str(e))
        if not headers.has_key('proc-type'):
            # unencryped: done
            break
        # encrypted keyfile: will need a password
        if headers['proc-type'] != '4,ENCRYPTED':
            raise SSHException('Unknown private key structure "%s"' % headers['proc-type'])
        try:
            encryption_type, saltstr = headers['dek-info'].split(',')
        except:
            raise SSHException('Can\'t parse DEK-info in private key file')
        if not self._CIPHER_TABLE.has_key(encryption_type):
            raise SSHException('Unknown private key cipher "%s"' % encryption_type)
        # if no password was passed in, raise an exception pointing out that we need one
        if password is None:
            raise PasswordRequiredException('Private key file is encrypted')
        cipher = self._CIPHER_TABLE[encryption_type]['cipher']
        keysize = self._CIPHER_TABLE[encryption_type]['keysize']
        mode = self._CIPHER_TABLE[encryption_type]['mode']
        salt = util.unhexify(saltstr)
        key = util.generate_key_bytes(MD5, salt, password, keysize)
        data = cipher.new(key, mode, salt).decrypt(data)    
        break
Пример #2
0
def _get_dss_key_as_string(dsskey=None, password=None):
    
    # patching paramiko to get a string instead of a file
    self = dsskey
    from paramiko.dsskey import SSHException, BER, BERException, randpool, util
    from paramiko.pkey import base64

    # adapted from DSSKey.write_private_key_file()
    if self.x is None:
        raise SSHException('Not enough key information')
    keylist = [ 0, self.p, self.q, self.g, self.y, self.x ]
    try:
        b = BER()
        b.encode(keylist)
    except BERException:
        raise SSHException('Unable to create ber encoding of key')

    f = []

    # adapted from PKey._write_private_key_file()
    tag, data, password = '******', str(b), password
    
    f.append('-----BEGIN %s PRIVATE KEY-----\n' % tag)
    if password is not None:
        # since we only support one cipher here, use it
        cipher_name = self._CIPHER_TABLE.keys()[0]
        cipher = self._CIPHER_TABLE[cipher_name]['cipher']
        keysize = self._CIPHER_TABLE[cipher_name]['keysize']
        blocksize = self._CIPHER_TABLE[cipher_name]['blocksize']
        mode = self._CIPHER_TABLE[cipher_name]['mode']
        salt = randpool.get_bytes(8)
        key = util.generate_key_bytes(MD5, salt, password, keysize)
        if len(data) % blocksize != 0:
            n = blocksize - len(data) % blocksize
            #data += randpool.get_bytes(n)
            # that would make more sense ^, but it confuses openssh.
            data += '\0' * n
        data = cipher.new(key, mode, salt).encrypt(data)
        f.append('Proc-Type: 4,ENCRYPTED\n')
        f.append('DEK-Info: %s,%s\n' % (cipher_name, util.hexify(salt)))
        f.append('\n')
    s = base64.encodestring(data)
    # re-wrap to 64-char lines
    s = ''.join(s.split('\n'))
    s = '\n'.join([s[i : i+64] for i in range(0, len(s), 64)])
    f.append(s)
    f.append('\n')
    f.append('-----END %s PRIVATE KEY-----\n' % tag)

    return ''.join(f)