def _fromString_PUBLIC_LSH(cls, data): """ Return a public key corresponding to this LSH public key string. The LSH public key string format is:: <s-expression: ('public-key', (<key type>, (<name, <value>)+))> The names for a RSA (key type 'rsa-pkcs1-sha1') key are: n, e. The names for a DSA (key type 'dsa') key are: y, g, p, q. @type data: L{bytes} @param data: The key data. @return: A new key. @rtype: L{twisted.conch.ssh.keys.Key} @raises BadKeyError: if the key type is unknown """ sexp = sexpy.parse(decodebytes(data[1:-1])) assert sexp[0] == b'public-key' kd = {} for name, data in sexp[1][1:]: kd[name] = common.getMP(common.NS(data))[0] if sexp[1][0] == b'dsa': return cls._fromDSAComponents( y=kd[b'y'], g=kd[b'g'], p=kd[b'p'], q=kd[b'q']) elif sexp[1][0] == b'rsa-pkcs1-sha1': return cls._fromRSAComponents(n=kd[b'n'], e=kd[b'e']) else: raise BadKeyError('unknown lsh key type %s' % (sexp[1][0],))
def _fromString_PUBLIC_OPENSSH(cls, data): """ Return a public key object corresponding to this OpenSSH public key string. The format of an OpenSSH public key string is:: <key type> <base64-encoded public key blob> @type data: L{bytes} @param data: The key data. @return: A new key. @rtype: L{twisted.conch.ssh.keys.Key} @raises BadKeyError: if the blob type is unknown. """ blob = decodebytes(data.split()[1]) return cls._fromString_BLOB(blob)
def _fromString_PUBLIC_OPENSSH(cls, data): """ Return a public key object corresponding to this OpenSSH public key string. The format of an OpenSSH public key string is:: <key type> <base64-encoded public key blob> @type data: L{bytes} @param data: The key data. @return: A new key. @rtype: L{twisted.conch.ssh.keys.Key} @raises BadKeyError: if the blob type is unknown. """ # ECDSA keys don't need base64 decoding which is required # for RSA or DSA key. if data.startswith(b'ecdsa-sha2'): return cls(load_ssh_public_key(data, default_backend())) blob = decodebytes(data.split()[1]) return cls._fromString_BLOB(blob)
def isInKnownHosts(host, pubKey, options): """ Checks to see if host is in the known_hosts file for the user. @return: 0 if it isn't, 1 if it is and is the same, 2 if it's changed. @rtype: L{int} """ keyType = common.getNS(pubKey)[0] retVal = 0 if not options['known-hosts'] and not os.path.exists( os.path.expanduser('~/.ssh/')): print('Creating ~/.ssh directory...') os.mkdir(os.path.expanduser('~/.ssh')) kh_file = options['known-hosts'] or _KNOWN_HOSTS try: known_hosts = open(os.path.expanduser(kh_file), 'rb') except IOError: return 0 with known_hosts: for line in known_hosts.readlines(): split = line.split() if len(split) < 3: continue hosts, hostKeyType, encodedKey = split[:3] if host not in hosts.split(b','): # incorrect host continue if hostKeyType != keyType: # incorrect type of key continue try: decodedKey = decodebytes(encodedKey) except: continue if decodedKey == pubKey: return 1 else: retVal = 2 return retVal
def isInKnownHosts(host, pubKey, options): """ Checks to see if host is in the known_hosts file for the user. @return: 0 if it isn't, 1 if it is and is the same, 2 if it's changed. @rtype: L{int} """ keyType = common.getNS(pubKey)[0] retVal = 0 if not options['known-hosts'] and not os.path.exists(os.path.expanduser('~/.ssh/')): print('Creating ~/.ssh directory...') os.mkdir(os.path.expanduser('~/.ssh')) kh_file = options['known-hosts'] or _KNOWN_HOSTS try: known_hosts = open(os.path.expanduser(kh_file), 'rb') except IOError: return 0 with known_hosts: for line in known_hosts.readlines(): split = line.split() if len(split) < 3: continue hosts, hostKeyType, encodedKey = split[:3] if host not in hosts.split(b','): # incorrect host continue if hostKeyType != keyType: # incorrect type of key continue try: decodedKey = decodebytes(encodedKey) except: continue if decodedKey == pubKey: return 1 else: retVal = 2 return retVal
GmdB9k3YzMHe1ldMxEB7zNw5aOnxjhoYLtiHeoEcOk2XOyvnE+VfhIWwWAdOiKRTEZlmiz kvhGbq0DCe2EPMXirjqWACI5nDioQX1oEMonR8N3AEO5v9SfBqS2Q9R6OBr6lf04RvwpHZ 0UGu8AAACAAhRpxGMIWEyaEh8YnjiazQTNEpklRZqeBGo1gotJggNmVaIQNIClGlLyCi35 9efEUuQcZ9SXxM59P+hecc/GU/GHakW5YWE4dP2GgdgMQWC7S6WFIXePGGXqNQDdWxlX8u mhenvQqa1PnKrFRhDrJw8Z7GjdHxflsxCEmXPoLN8AAAAVANXaBstzNR3EK6zSl8Q/Vt11 pdEtAAAAAAE= -----END OPENSSH PRIVATE KEY-----\ """ publicDSA_lsh = decodebytes(b"""\ e0tERXdPbkIxWW14cFl5MXJaWGtvTXpwa2MyRW9NVHB3TVRJNU9nQ1NrRHJGUkVWUTBDS1FEUngv aVFBTXBhUFM3eFdKaFJWVENMaHhScFdhU0MrN0lkeURKS3N2bkxMQ0RUUDVaeHc5MzVyQU1pNVZG MmJiZWp3L1M0R1VXczdEem9LYmJoL2hydVBCdnNoYmhQSmRIMVZWSXI2TFB6Sm1GU2V1cWsvZlli WEdTbXJhMDFtWjZWVnU0QlFBYUtzUG9YdGkyZElKSGxOUGtzZld1U2tvTVRweE1qRTZBUFFSaVpN MW9VbndKTFQ2OFZJWGlkaHpJU2RKS1NneE9tY3hNams2QUpJQzQ4UnlRQk82aFZuVTZuK3hHWjRM dTR3QnBuUWZaTjJNekIzdFpYVE1SQWU4emNPV2pwOFk0YUdDN1loM3FCSERwTmx6c3I1eFBsWDRT RnNGZ0hUb2lrVXhHWlpvczVMNFJtNnRBd250aER6RjRxNDZsZ0FpT1p3NHFFRjlhQkRLSjBmRGR3 QkR1Yi9Vbndha3RrUFVlamdhK3BYOU9FYjhLUjJkRkJydktTZ3hPbmt4TWpnNkFoUnB4R01JV0V5 YUVoOFluamlhelFUTkVwa2xSWnFlQkdvMWdvdEpnZ05tVmFJUU5JQ2xHbEx5Q2kzNTllZkVVdVFj WjlTWHhNNTlQK2hlY2MvR1UvR0hha1c1WVdFNGRQMkdnZGdNUVdDN1M2V0ZJWGVQR0dYcU5RRGRX eGxYOHVtaGVudlFxYTFQbktyRlJoRHJKdzhaN0dqZEh4ZmxzeENFbVhQb0xOOHBLU2s9fQ== """) privateDSA_lsh = decodebytes(b"""\ KDExOnByaXZhdGUta2V5KDM6ZHNhKDE6cDEyOToAkpA6xURFUNAikA0cf4kADKWj0u8ViYUVUwi4 cUaVmkgvuyHcgySrL5yywg0z+WccPd+awDIuVRdm23o8P0uBlFrOw86Cm24f4a7jwb7IW4TyXR9V VSK+iz8yZhUnrqpP32G1xkpq2tNZmelVbuAUAGirD6F7YtnSCR5TT5LH1rkpKDE6cTIxOgD0EYmT NaFJ8CS0+vFSF4nYcyEnSSkoMTpnMTI5OgCSAuPEckATuoVZ1Op/sRmeC7uMAaZ0H2TdjMwd7WV0 zEQHvM3Dlo6fGOGhgu2Id6gRw6TZc7K+cT5V+EhbBYB06IpFMRmWaLOS+EZurQMJ7YQ8xeKuOpYA IjmcOKhBfWgQyidHw3cAQ7m/1J8GpLZD1Ho4GvqV/ThG/CkdnRQa7ykoMTp5MTI4OgIUacRjCFhM mhIfGJ44ms0EzRKZJUWangRqNYKLSYIDZlWiEDSApRpS8got+fXnxFLkHGfUl8TOfT/oXnHPxlPx
zB3tZXTMRAe8zcOWjp8Y4aGC7Yh3qBHDpNlzsr5xPlX4SFsFgHToikUxGZZos5L4 Rm6tAwnthDzF4q46lgAiOZw4qEF9aBDKJ0fDdwBDub/UnwaktkPUejga+pX9OEb8 KR2dFBrvAoGAAhRpxGMIWEyaEh8YnjiazQTNEpklRZqeBGo1gotJggNmVaIQNICl GlLyCi359efEUuQcZ9SXxM59P+hecc/GU/GHakW5YWE4dP2GgdgMQWC7S6WFIXeP GGXqNQDdWxlX8umhenvQqa1PnKrFRhDrJw8Z7GjdHxflsxCEmXPoLN8CFQDV2gbL czUdxCus0pfEP1bddaXRLQ== -----END DSA PRIVATE KEY-----\ """ publicDSA_lsh = decodebytes(b"""\ e0tERXdPbkIxWW14cFl5MXJaWGtvTXpwa2MyRW9NVHB3TVRJNU9nQ1NrRHJGUkVWUTBDS1FEUngv aVFBTXBhUFM3eFdKaFJWVENMaHhScFdhU0MrN0lkeURKS3N2bkxMQ0RUUDVaeHc5MzVyQU1pNVZG MmJiZWp3L1M0R1VXczdEem9LYmJoL2hydVBCdnNoYmhQSmRIMVZWSXI2TFB6Sm1GU2V1cWsvZlli WEdTbXJhMDFtWjZWVnU0QlFBYUtzUG9YdGkyZElKSGxOUGtzZld1U2tvTVRweE1qRTZBUFFSaVpN MW9VbndKTFQ2OFZJWGlkaHpJU2RKS1NneE9tY3hNams2QUpJQzQ4UnlRQk82aFZuVTZuK3hHWjRM dTR3QnBuUWZaTjJNekIzdFpYVE1SQWU4emNPV2pwOFk0YUdDN1loM3FCSERwTmx6c3I1eFBsWDRT RnNGZ0hUb2lrVXhHWlpvczVMNFJtNnRBd250aER6RjRxNDZsZ0FpT1p3NHFFRjlhQkRLSjBmRGR3 QkR1Yi9Vbndha3RrUFVlamdhK3BYOU9FYjhLUjJkRkJydktTZ3hPbmt4TWpnNkFoUnB4R01JV0V5 YUVoOFluamlhelFUTkVwa2xSWnFlQkdvMWdvdEpnZ05tVmFJUU5JQ2xHbEx5Q2kzNTllZkVVdVFj WjlTWHhNNTlQK2hlY2MvR1UvR0hha1c1WVdFNGRQMkdnZGdNUVdDN1M2V0ZJWGVQR0dYcU5RRGRX eGxYOHVtaGVudlFxYTFQbktyRlJoRHJKdzhaN0dqZEh4ZmxzeENFbVhQb0xOOHBLU2s9fQ== """) privateDSA_lsh = decodebytes(b"""\ KDExOnByaXZhdGUta2V5KDM6ZHNhKDE6cDEyOToAkpA6xURFUNAikA0cf4kADKWj0u8ViYUVUwi4 cUaVmkgvuyHcgySrL5yywg0z+WccPd+awDIuVRdm23o8P0uBlFrOw86Cm24f4a7jwb7IW4TyXR9V VSK+iz8yZhUnrqpP32G1xkpq2tNZmelVbuAUAGirD6F7YtnSCR5TT5LH1rkpKDE6cTIxOgD0EYmT NaFJ8CS0+vFSF4nYcyEnSSkoMTpnMTI5OgCSAuPEckATuoVZ1Op/sRmeC7uMAaZ0H2TdjMwd7WV0 zEQHvM3Dlo6fGOGhgu2Id6gRw6TZc7K+cT5V+EhbBYB06IpFMRmWaLOS+EZurQMJ7YQ8xeKuOpYA IjmcOKhBfWgQyidHw3cAQ7m/1J8GpLZD1Ho4GvqV/ThG/CkdnRQa7ykoMTp5MTI4OgIUacRjCFhM mhIfGJ44ms0EzRKZJUWangRqNYKLSYIDZlWiEDSApRpS8got+fXnxFLkHGfUl8TOfT/oXnHPxlPx
def _fromString_PRIVATE_OPENSSH(cls, data, passphrase): """ Return a private key object corresponding to this OpenSSH private key string. If the key is encrypted, passphrase MUST be provided. Providing a passphrase for an unencrypted key is an error. The format of an OpenSSH private key string is:: -----BEGIN <key type> PRIVATE KEY----- [Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,<initialization value>] <base64-encoded ASN.1 structure> ------END <key type> PRIVATE KEY------ The ASN.1 structure of a RSA key is:: (0, n, e, d, p, q) The ASN.1 structure of a DSA key is:: (0, p, q, g, y, x) The ASN.1 structure of a ECDSA key is:: (ECParameters, OID, NULL) @type data: L{bytes} @param data: The key data. @type passphrase: L{bytes} or L{None} @param passphrase: The passphrase the key is encrypted with, or L{None} if it is not encrypted. @return: A new key. @rtype: L{twisted.conch.ssh.keys.Key} @raises BadKeyError: if * a passphrase is provided for an unencrypted key * the ASN.1 encoding is incorrect @raises EncryptedKeyError: if * a passphrase is not provided for an encrypted key """ lines = data.strip().splitlines() kind = lines[0][11:-17] if lines[1].startswith(b'Proc-Type: 4,ENCRYPTED'): if not passphrase: raise EncryptedKeyError('Passphrase must be provided ' 'for an encrypted key') # Determine cipher and initialization vector try: _, cipherIVInfo = lines[2].split(b' ', 1) cipher, ivdata = cipherIVInfo.rstrip().split(b',', 1) except ValueError: raise BadKeyError('invalid DEK-info %r' % (lines[2],)) if cipher in (b'AES-128-CBC', b'AES-256-CBC'): algorithmClass = algorithms.AES keySize = int(int(cipher.split(b'-')[1])/8) if len(ivdata) != 32: raise BadKeyError('AES encrypted key with a bad IV') elif cipher == b'DES-EDE3-CBC': algorithmClass = algorithms.TripleDES keySize = 24 if len(ivdata) != 16: raise BadKeyError('DES encrypted key with a bad IV') else: raise BadKeyError('unknown encryption type %r' % (cipher,)) # Extract keyData for decoding iv = bytes(bytearray([int(ivdata[i:i + 2], 16) for i in range(0, len(ivdata), 2)])) ba = md5(passphrase + iv[:8]).digest() bb = md5(ba + passphrase + iv[:8]).digest() decKey = (ba + bb)[:keySize] b64Data = decodebytes(b''.join(lines[3:-1])) decryptor = Cipher( algorithmClass(decKey), modes.CBC(iv), backend=default_backend() ).decryptor() keyData = decryptor.update(b64Data) + decryptor.finalize() removeLen = ord(keyData[-1:]) keyData = keyData[:-removeLen] else: b64Data = b''.join(lines[1:-1]) keyData = decodebytes(b64Data) try: decodedKey = berDecoder.decode(keyData)[0] except PyAsn1Error as e: raise BadKeyError( 'Failed to decode key (Bad Passphrase?): %s' % (e,)) if kind == b'EC': return cls( load_pem_private_key(data, passphrase, default_backend())) if kind == b'RSA': if len(decodedKey) == 2: # Alternate RSA key decodedKey = decodedKey[0] if len(decodedKey) < 6: raise BadKeyError('RSA key failed to decode properly') n, e, d, p, q, dmp1, dmq1, iqmp = [ long(value) for value in decodedKey[1:9] ] if p > q: # Make p smaller than q p, q = q, p return cls( rsa.RSAPrivateNumbers( p=p, q=q, d=d, dmp1=dmp1, dmq1=dmq1, iqmp=iqmp, public_numbers=rsa.RSAPublicNumbers(e=e, n=n), ).private_key(default_backend()) ) elif kind == b'DSA': p, q, g, y, x = [long(value) for value in decodedKey[1: 6]] if len(decodedKey) < 6: raise BadKeyError('DSA key failed to decode properly') return cls( dsa.DSAPrivateNumbers( x=x, public_numbers=dsa.DSAPublicNumbers( y=y, parameter_numbers=dsa.DSAParameterNumbers( p=p, q=q, g=g ) ) ).private_key(backend=default_backend()) ) else: raise BadKeyError("unknown key type %s" % (kind,))
def _fromString_PRIVATE_OPENSSH(cls, data, passphrase): """ Return a private key object corresponding to this OpenSSH private key string. If the key is encrypted, passphrase MUST be provided. Providing a passphrase for an unencrypted key is an error. The format of an OpenSSH private key string is:: -----BEGIN <key type> PRIVATE KEY----- [Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,<initialization value>] <base64-encoded ASN.1 structure> ------END <key type> PRIVATE KEY------ The ASN.1 structure of a RSA key is:: (0, n, e, d, p, q) The ASN.1 structure of a DSA key is:: (0, p, q, g, y, x) @type data: L{bytes} @param data: The key data. @type passphrase: L{bytes} or L{None} @param passphrase: The passphrase the key is encrypted with, or L{None} if it is not encrypted. @return: A new key. @rtype: L{twisted.conch.ssh.keys.Key} @raises BadKeyError: if * a passphrase is provided for an unencrypted key * the ASN.1 encoding is incorrect @raises EncryptedKeyError: if * a passphrase is not provided for an encrypted key """ lines = data.strip().split(b'\n') kind = lines[0][11:14] if lines[1].startswith(b'Proc-Type: 4,ENCRYPTED'): if not passphrase: raise EncryptedKeyError('Passphrase must be provided ' 'for an encrypted key') # Determine cipher and initialization vector try: _, cipherIVInfo = lines[2].split(b' ', 1) cipher, ivdata = cipherIVInfo.rstrip().split(b',', 1) except ValueError: raise BadKeyError('invalid DEK-info %r' % (lines[2],)) if cipher == b'AES-128-CBC': algorithmClass = algorithms.AES keySize = 16 if len(ivdata) != 32: raise BadKeyError('AES encrypted key with a bad IV') elif cipher == b'DES-EDE3-CBC': algorithmClass = algorithms.TripleDES keySize = 24 if len(ivdata) != 16: raise BadKeyError('DES encrypted key with a bad IV') else: raise BadKeyError('unknown encryption type %r' % (cipher,)) # Extract keyData for decoding iv = bytes(bytearray([int(ivdata[i:i + 2], 16) for i in range(0, len(ivdata), 2)])) ba = md5(passphrase + iv[:8]).digest() bb = md5(ba + passphrase + iv[:8]).digest() decKey = (ba + bb)[:keySize] b64Data = decodebytes(b''.join(lines[3:-1])) decryptor = Cipher( algorithmClass(decKey), modes.CBC(iv), backend=default_backend() ).decryptor() keyData = decryptor.update(b64Data) + decryptor.finalize() removeLen = ord(keyData[-1:]) keyData = keyData[:-removeLen] else: b64Data = b''.join(lines[1:-1]) keyData = decodebytes(b64Data) try: decodedKey = berDecoder.decode(keyData)[0] except PyAsn1Error as e: raise BadKeyError( 'Failed to decode key (Bad Passphrase?): %s' % (e,)) if kind == b'RSA': if len(decodedKey) == 2: # Alternate RSA key decodedKey = decodedKey[0] if len(decodedKey) < 6: raise BadKeyError('RSA key failed to decode properly') n, e, d, p, q, dmp1, dmq1, iqmp = [ long(value) for value in decodedKey[1:9] ] if p > q: # Make p smaller than q p, q = q, p return cls( rsa.RSAPrivateNumbers( p=p, q=q, d=d, dmp1=dmp1, dmq1=dmq1, iqmp=iqmp, public_numbers=rsa.RSAPublicNumbers(e=e, n=n), ).private_key(default_backend()) ) elif kind == b'DSA': p, q, g, y, x = [long(value) for value in decodedKey[1: 6]] if len(decodedKey) < 6: raise BadKeyError('DSA key failed to decode properly') return cls( dsa.DSAPrivateNumbers( x=x, public_numbers=dsa.DSAPublicNumbers( y=y, parameter_numbers=dsa.DSAParameterNumbers( p=p, q=q, g=g ) ) ).private_key(backend=default_backend()) ) else: raise BadKeyError("unknown key type %s" % (kind,))