Exemple #1
0
 def BCRYPT_saltless(self, i, data, salt=''):
     start_time = time.time()
     bcrypt.kdf(
         password=data.encode('utf-16'),
         salt=salt.encode('utf-16'),
         desired_key_bytes=32,
         rounds=100)
     end_time = time.time()
     print("BCRYPT:", end_time - start_time, "s")
     self.slow_time_saltless[i].append(end_time - start_time)
Exemple #2
0
def login():  
    if current_user.is_authenticated:
        return redirect(url_for('main.home'))
    loginForm = LoginForm()
    if loginForm.validate_on_submit():
        user = User.query.filter_by(username=loginForm.username.data).first()
        kdf = bcrypt.kdf(password=loginForm.password.data.encode(), salt=b'CR7BalonDeOro', desired_key_bytes=64, rounds=50)
        if user and bcrypt.checkpw(base64.b64encode(kdf[:32]), user.password):
            if user.confirmed:
                if checkUserDevice(user, request):
                    login_user(user, remember=loginForm.remember.data)
                    next_page = request.args.get('next')
                    if next_page:
                        flash(f'Welcome to Social Medium {user.username}', 'success')
                        current_app.logger.info('[IP: %s] [Message: El usuario %s se ha logeado]',request.remote_addr, user.username)
                        session['Pk'] = kdf[32:]
                        return redirect(next_page)
                    else:
                        flash(f'Welcome to Social Medium {user.username}', 'success')
                        current_app.logger.info('[IP: %s] [Message: El usuario %s se ha logeado]',request.remote_addr, user.username)
                        session['Pk'] = kdf[32:]
                        return redirect(url_for('main.home'))
                else:
                    session['username'] = user.username
                    current_app.logger.info('[IP: %s] Intento de inicio de sesion desde un nuevo dispisitivo, pasamos a token de verifiacion con el usurio %s]', request.remote_addr,loginForm.username.data)
                    return redirect(url_for('users.token',  remember=loginForm.remember.data))
            else:
                flash('Please verify your account via email', 'warning')
                current_app.logger.info('[IP: %s] Intento de inicio de sesion sin cuenta validad por el usuario %s]', request.remote_addr,loginForm.username.data)
        else:
            flash('Login Unsuccessful. Please try again', 'warning')
            current_app.logger.warning('[IP: %s] [Message: Inicio de sesión fallido mediante el usuario %s]', request.remote_addr, loginForm.username.data)
    return render_template('login.html', title='Login', form=loginForm)
Exemple #3
0
def reset_token(token):
    if current_user.is_authenticated:
        flash('You are already logged in, no need to reset the password', 'info')
        return redirect(url_for('main.home'))
    user = User.verify_reset_token(token)
    if user is None:
        current_app.logger.warning('[IP: %s] [Message: Token caducado o incorrecto para el reseteo de contraseña %s]', request.remote_addr)
        flash('That is an invalid or expired token', 'danger')
        return redirect(url_for('users.reset_request'))
    passwordResetform = ResetPasswordForm()
    if passwordResetform.validate_on_submit():
        kdf = bcrypt.kdf(password=passwordResetform.password.data.encode(), salt=b'CR7BalonDeOro', desired_key_bytes=64, rounds=50)
        salt_Pk = bcrypt.gensalt(rounds=12)
        hashed_password = bcrypt.hashpw(base64.b64encode(kdf[:32]), salt_Pk)
        ciphered_Uk, iv_Uk = generate_keys(kdf[32:])
        user.password = hashed_password
        user.ciphered_Uk = ciphered_Uk
        user.salt_Pk = salt_Pk
        user.iv_Uk = iv_Uk
        Post.query.filter(Post.post_type == '1').filter_by(author=user).delete()
        current_app.logger.info('[User: %s] [Message: Ha eliminado sus posts personales y renovado todas las llaves de cifrado %s]', user.username)
        db.session.commit()
        current_app.logger.info('[User: %s] [Message: Ha actualizado su contraseña %s]', user.username)
        flash('Password Updated!', 'success')
        return redirect(url_for('users.login'))
    return render_template('reset_token.html', title='Reset Password', form=passwordResetform)
Exemple #4
0
def new_user():

    while True:
        try:
            details = misc.user()

            # create encryption key from master password
            global_var['salt'] = bcrypt.gensalt()
            global_var['key'] = bcrypt.kdf(details[1].encode(),
                                           global_var['salt'], 16, 100)
            details[1] = bcrypt.hashpw(details[1].encode('utf8'),
                                       global_var['salt'])

            new = Base.User(name=details[0],
                            key=global_var['salt'],
                            master_pass=details[1])
            global_var['session'].add(new)
            global_var['session'].commit()

            # get user_id
            for id, in global_var['session'].query(
                    Base.User.id).filter(Base.User.name == details[0]):
                global_var['user_id'] = int(id)

            print('\n $ Welcome ' + details[0] + '\n')
            break
        except (exc.IntegrityError, sqlite3.IntegrityError):
            global_var['session'].rollback()
            global_var['session'] = Session()
            print(' $ Username already exists! Please Enter again')
Exemple #5
0
    def read_data(self, escrowed_data, sign_key, layer_count=None):
        self.log.info('reading data from %d escrowed bytes', len(escrowed_data))

        # TODO: check that we're logged in

        post_data = {
            'escrow_data': escrowed_data,
            'sign_key': serial.dumps(sign_key)
        }
        if layer_count is not None:
            post_data['layer_count'] = layer_count

        self.log.debug('requesting read_data')
        r = requests.post(
            self.url + 'data', params=self.get_auth_params(), data=post_data)
        boxed_data = r.content
        self.log.debug('got %d byte response from read_data', len(boxed_data))

        self.log.debug('unboxing response')
        key = bcrypt.kdf(
            self.password.encode('utf-8'),
            self.challenge,
            SecretBox.KEY_SIZE, ITERATIONS
        )
        box = SecretBox(key)
        data = box.decrypt(boxed_data)
        self.log.debug('unboxed response, got %d bytes', len(data))

        return data
def generate_partial_password(password,
                              min_parts_required,
                              work_factor,
                              salt_length=16):
    """Construct a shared secret using a password"""
    plen = len(password)
    salts = []
    keys = []
    ivs = []
    for i in range(plen):
        salts.append(os.urandom(salt_length))
        keys.append(
            bcrypt.kdf(password=password[i].encode('utf-8'),
                       salt=salts[i],
                       desired_key_bytes=32,
                       rounds=work_factor))
        ivs.append(os.urandom(16))
    secret, shares = shamir.make_random_shares(minimum=min_parts_required,
                                               shares=plen)
    encrypted = []
    for (x, y), key, iv in zip(shares, keys, ivs):
        backend = default_backend()
        cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
        encryptor = cipher.encryptor()
        ct = encryptor.update(y.to_bytes(
            32, byteorder="little")) + encryptor.finalize()
        encrypted.append(ct)
    output = []
    for salt, iv, ct in zip(salts, ivs, encrypted):
        output.append({'salt': salt, 'iv': iv, 'ct': ct[:16]})
    secret = base64.urlsafe_b64encode(secret.to_bytes(16, "little"))
    print(secret)
    hashed_secret = bcrypt.hashpw(secret, bcrypt.gensalt())
    return output, hashed_secret
Exemple #7
0
def existing_user():
    while True:
        # get input and verify
        # if verified user then initialze global vasiables
        details = misc.user()
        result = global_var['session'].query(
            Base.User).filter(Base.User.name == details[0])
        temp = None
        for row in result:
            global_var['user_id'] = int(row.id)
            global_var['salt'] = row.key
            temp = row.master_pass
        if global_var['user_id'] == None:
            print('Username does not exist please create a new account')
            new_user()
            return
        else:
            t = details[1]
            details[1] = bcrypt.hashpw(details[1].encode('utf8'),
                                       global_var['salt'])
            if (not temp == details[1]):
                print('Invalid password')
            else:
                global_var['key'] = bcrypt.kdf(t.encode(), global_var['salt'],
                                               16, 100)
                t = None
                os.system('cls' if os.name == 'nt' else 'clear')
                print('\n $ Welcome ' + details[0] + '\n')
                break
Exemple #8
0
def get_masterkey(password, factor):
	binary_password = password.encode()
	print('Generating master key... It may take some minutes.')
	master_key = bcrypt.hashpw(binary_password, bcrypt.gensalt(factor))
	master_key = bcrypt.kdf(password = binary_password, salt = b'sealed', desired_key_bytes = 32, rounds = factor)
	print('Master key generated.')
	return master_key
Exemple #9
0
def register():
    if current_user.is_authenticated:
        return redirect(url_for('main.home'))
    registerForm = RegistrationForm()
    if registerForm.validate_on_submit():
        kdf = bcrypt.kdf(password=registerForm.password.data.encode(), salt=b'CR7BalonDeOro', desired_key_bytes=64, rounds=50)
        salt_Pk = bcrypt.gensalt(rounds=12)
        hashed_password = bcrypt.hashpw(base64.b64encode(kdf[:32]), salt_Pk)
        ciphered_Uk, iv_Uk = generate_keys(kdf[32:])
        user = User(username = registerForm.username.data,
                    email = registerForm.email.data,
                    password = hashed_password,
                    ciphered_Uk = ciphered_Uk,
                    salt_Pk = salt_Pk,
                    iv_Uk = iv_Uk)
        db.session.add(user)
        db.session.commit()
        current_app.logger.info('[IP: %s] [Message: El usuario %s se ha registrado]',request.remote_addr, user.username)
        createDevice(user, request)
        current_app.logger.info('[User: %s] [Message: Ha añadido correctamente un dispositivo de confianza]', user.username)
        send_confirmation_email(user)
        current_app.logger.info('[User: %s] [Message: Ha recibido el correo de confirmacion]', user.username)
        flash(f'Your new account has been created! Please verify it within 30 minutes.', 'info')
        # redirect to the two-factor auth page, passing username in session
        session['username'] = user.username
        return redirect(url_for('users.two_factor_setup'))
    return render_template('register.html', title='Register', form=registerForm)
Exemple #10
0
def generate_from_raw(comment, password, raw_pub, raw_priv):
    """ADVANCED: Given a raw Ed25519 key pair raw_pub and raw_priv,
    create a Signify keypair.

    See generate() for documentation.
    """

    assert isinstance(raw_pub, bytes)
    assert isinstance(raw_priv, bytes)

    if comment is None:
        comment = "signify"

    keynum = os.urandom(8)

    # private key
    kdfrounds = 42
    salt = os.urandom(16)

    if password is None:
        kdfrounds = 0
        xorkey = b"\x00" * 64
    else:
        xorkey = bcrypt.kdf(password, salt, 64, kdfrounds)
    protected_key = xorbuf(xorkey, raw_priv)
    checksum = hashlib.sha512(raw_priv).digest()[0:8]

    priv_blob = b"Ed" + b"BK" + struct.pack("!L", kdfrounds) + salt + checksum + keynum + protected_key
    priv = _Materialized.write_message("%s secret key" % (comment,), priv_blob)

    # public key
    pub_blob = b"Ed" + keynum + raw_pub
    pub = _Materialized.write_message("%s public key" % (comment,), pub_blob)

    return PublicKey.from_bytes(pub), SecretKey.from_bytes(priv)
Exemple #11
0
    def _authenticate_user(self, password):
        """
        Authenticate a user who is trying to log in.

        @param `submitted_credentials` (JSON): Expected keys:
        `email_address_or_username`, `password`.

        @return (bool): (JSON) if user was successfully authenticated,
        `NoneType` otherwise.

        """
        account_info = users_db.read(self.identifier_key_val_pair)

        if account_info is None:
            return None

        calculated_hash = bcrypt.kdf(
            password=password.encode("utf-8"), rounds=pbkdf_rounds,
            salt=account_info["salt"], desired_key_bytes=desired_key_bytes
        )

        if calculated_hash == account_info["hash"]:
            return account_info
        else:
            return None
Exemple #12
0
def test_kdf(rounds, password, salt, expected):
    derived = bcrypt.kdf(password,
                         salt,
                         len(expected),
                         rounds,
                         ignore_few_rounds=True)
    assert derived == expected
def get_key_from_pass(password, hashed_password):
	#extract the salt and convert from hex to bytes
	salt = bytes.fromhex(hashed_password[:58])
	
	#run password and salt through bcrypt KDF for 100 rounds to produce a 32 byte key, encoded as base64
	key = base64.urlsafe_b64encode(bcrypt.kdf(password.encode('utf-8'), salt, 32, 100))
	return key
Exemple #14
0
    def __init__(self,
                 password,
                 credential_id,
                 salt=None,
                 strip_whitespace=True):
        """
        :param password: string, password as plaintext
        :param credential_id: unique id of credential in the authentication backend databas
        :param salt: string or None, NDNv1H1 salt to be used for pre-hashing
                      (if None, one will be generated. If non-default salt
                      parameters are requested, use generate_salt() directly)
        :param strip_whitespace: boolean, Remove all whitespace from input

        :type password: string_types
        :type credential_id: string_types | bson.ObjectId
        :type salt: None | string_types
        :type strip_whitespace: bool
        """
        if salt is None:
            salt = self.generate_salt()
        if not salt.startswith('$NDNv1H1$'):
            raise ValueError('Invalid salt (not NDNv1H1)')
        self.salt = salt
        if isinstance(credential_id, bson.ObjectId):
            # backwards compatibility
            credential_id = str(credential_id)
        if not isinstance(credential_id, string_types):
            raise ValueError(
                'Non-string credential id: {!r}'.format(credential_id))
        self.credential_id = credential_id
        salt, key_length, rounds, = self._decode_parameters(salt)

        cid_str = str(self.credential_id)
        if strip_whitespace:
            password = ''.join(password.split())
        if six.PY2:
            # Allow passwords containing non-ascii characters, while
            # keeping backward-capability by converting to byte string.
            # UTF-8 is the encoding used for POST-requests, for more info see the
            # section handling-form-submissions-in-view-callables-unicode-and-character-set-issues
            # at http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/views.html
            if isinstance(password, unicode):
                password = password.encode('UTF-8')
            T1 = "{!s}{!s}{!s}{!s}".format(len(cid_str), cid_str,
                                           len(password), password)
        else:
            password = bytes(password, 'utf-8')
            T1 = "{!s}{!s}{!s}".format(len(cid_str), cid_str, len(password))
            T1 = bytes(T1, 'utf-8') + password

        # password = '******' (T1 as hex:'3434373131323070617373776f7264c3a5c3a4c3b6d185d18dd0b6')
        # should give res == '80e6759a26bb9d439bc77d52'
        res = bcrypt.kdf(T1, salt, key_length, rounds)
        if six.PY2:
            res = res.encode('hex')
        else:
            res = res.hex()
        self.hash = res
        VCCSFactor.__init__(self)
Exemple #15
0
 def encrypt(cls, plain_text, method='normal'):
     plain_text = str(plain_text).encode('utf-8')
     if method is 'kdf':
         return bcrypt.kdf(password=plain_text,
                           salt=cls.gensalt(12),
                           desired_key_bytes=32,
                           rounds=100)
     return bcrypt.hashpw(plain_text, cls.gensalt(12))
Exemple #16
0
    def hash(self, p):
        #Defining example salt value
        salt = b"1234"
        
        hv = bcrypt.kdf(p, salt, 64, 100)
        cipher = binascii.hexlify(hv)

        return cipher
Exemple #17
0
def decrypt(password, salt, iv, enc_data):
    key = bcrypt.kdf(password, salt, 24, KDF_ROUNDS)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    raw_pad = cipher.decrypt(enc_data)

    raw = raw_pad[0:-raw_pad[-1]]

    return raw
Exemple #18
0
    def hashValues(value, salt):
        #Encoding salt from string to binary
        hashVal = bcrypt.kdf(value, salt, 64, 100)

        #Generating hex value from binary hash
        key = binascii.hexlify(hashVal)

        #Returning decoded hex value
        return key.decode('ascii')
Exemple #19
0
def create_secret_box(password, username):
    key = bcrypt.kdf(
        password.encode('utf-8'),
        username,                # this is the salt
        KEYLEN, ITERATIONS
    )
    
    nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)
    return nacl.secret.SecretBox(key), nonce
Exemple #20
0
def create_secret_box(password, username):
    key = bcrypt.kdf(
        password.encode('utf-8'),
        username,  # this is the salt
        KEYLEN,
        ITERATIONS)

    nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)
    return nacl.secret.SecretBox(key), nonce
Exemple #21
0
def encrypt(password, salt, iv, raw_data):
    key = bcrypt.kdf(password, salt, 24, KDF_ROUNDS)
    length = 16 - (len(raw_data) % 16)
    raw_data += bytes([length]) * length

    cipher = AES.new(key, AES.MODE_CBC, iv)
    enc_data = cipher.encrypt(raw_data)

    return enc_data
Exemple #22
0
def build_psk(macid):
    mac_str = build_mac(macid)
    bc = bcrypt.kdf(mac_str.encode(), salt=PREFIX.encode(), desired_key_bytes=45, rounds=100)
    bc_b64 = binascii.b2a_base64(bc, newline=False)
    bc_b64 = bc_b64.replace(b'/', b'')
    bc_b64 = bc_b64.replace(b'+', b'')
    if len(bc_b64) > 61:
        bc_b64 = bc_b64[:61]
    return bc_b64.decode()
Exemple #23
0
def _decrypt_key(
    encrypted: bytes,
    passphrase: bytes = None,
    ciphername: bytes = b"none",
    kdfname: bytes = b"none",
    kdf_metadata: bytes = b"",
) -> bytes:

    if ciphername == b"none":
        return encrypted

    if not passphrase:
        raise WrongPassphrase("Passphrase needed for decryption")

    if kdfname == b"none":
        raise InvalidKeyFile("Encrypted SSH key without KDF function name")

    if kdfname != b"bcrypt":
        raise InvalidKeyFile(
            f"Unsupported private key encryption KDF {kdfname!r}")

    Suite = collections.namedtuple(
        "Suite", ("algorithm", "mode", "key_bytes", "block_bytes", "iv_bytes"))
    suites: typing.Dict[bytes, Suite] = {
        b"aes256-ctr": Suite(cipher_algos.AES, cipher_modes.CTR, 32, 16, 16),
        b"aes192-ctr": Suite(cipher_algos.AES, cipher_modes.CTR, 24, 16, 16),
        b"aes128-ctr": Suite(cipher_algos.AES, cipher_modes.CTR, 16, 16, 16),
    }

    if ciphername not in suites:
        raise NotImplementedError(
            f"Unsupported private key encryption cipher {ciphername!r}")

    suite = suites[ciphername]

    kdf_stream = io.BytesIO(kdf_metadata)
    salt = _sshbuf_get_cstring(kdf_stream)
    (rounds, ) = _read_struct(kdf_stream, ">I")

    # ignore_few_rounds prevents a warning when called with <50 rounds
    bcrypt_result = bcrypt.kdf(passphrase,
                               salt,
                               suite.key_bytes + suite.iv_bytes,
                               rounds,
                               ignore_few_rounds=True)
    key = bcrypt_result[:suite.key_bytes]
    iv = bcrypt_result[suite.key_bytes:]

    cipher = Cipher(algorithm=suite.algorithm(key),
                    mode=suite.mode(iv),
                    backend=default_backend())
    decryptor = cipher.decryptor()
    decrypted = decryptor.update(encrypted) + decryptor.finalize()

    return decrypted
 def unprotect(self, password):
     if self.secret_key is None:
         import bcrypt
         mask = bcrypt.kdf(password, self.salt, len(self.enckey),
                           self.kdfrounds)
         result = bytes_xor(self.enckey, mask)
         if self.checksum != hashlib.sha512(
                 result).digest()[:len(self.checksum)]:
             raise BadPassword()
         self.secret_key = result
         self.public_key = result[-PK_BYTES:]
Exemple #25
0
def get_password(kdf_rounds: int, character_set: Sequence[str], length: int, increment: int, site_name: str, master_password: str) -> str:
	set_size = len(character_set)
	mask = get_mask(set_size)
	nonce = increment.to_bytes(8, 'little')

	key = bcrypt.kdf(master_password.encode('utf-8'), site_name.encode('utf-8'), 32, kdf_rounds)

	byte_stream = get_stream(key, nonce)
	character_stream = (character_set[b & mask] for b in byte_stream if b & mask < set_size)

	return ''.join(itertools.islice(character_stream, length))
 def generate_hash(password, salt, desired_key_bytes=32, rounds=100):
     password = password.encode()
     '''
     We are utlizing bcrypt pbkdf function to hash our passwords. In this
     function we are doing so, and then returning the hash.
     '''
     hash = bcrypt.kdf(password=password,
                       salt=salt,
                       desired_key_bytes=desired_key_bytes,
                       rounds=rounds)
     return hash
def decrypt_aes256ctr(salt_iv: str, psw: str, enc: str) -> bytes:
    warnings.filterwarnings("ignore")
    data = kdf(password=psw,
               salt=salt_iv,
               desired_key_bytes=32 + 16,
               rounds=10)
    key, iv = data[:32], data[32:]
    iv = int.from_bytes(iv, "big")
    counter = pyaes.Counter(iv)
    aes = pyaes.AESModeOfOperationCTR(key, counter)
    return aes.decrypt(enc)
Exemple #28
0
def CryptoBcrypt():

         TimeEstimation()
         start = timer()
         
         global digest
         digest = bcrypt.kdf( keyx, saltx, args.size, args.iter)
         
         end = timer()
         timex = (end - start)
         print("\n" + str(timex) + " seconds elapsed\n")
         print( "Key was : " + keyx +"\n")
         print( "salt was : " + saltx + "\n")
Exemple #29
0
    def unprotect(self, password):
        if self.secret_key is None:
            if self.ciphername == b'none' and self.kdfname == b'none':
                blob = self.protected_privatekey
            elif self.ciphername == b'aes256-ctr' and self.kdfname == b'bcrypt':
                if not password: raise BadPassword()
                import bcrypt
                from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
                from cryptography.hazmat.backends import default_backend
                (salt, kdfoptions) = parse_str(self.kdfoptions)
                (rounds, kdfoptions) = parse_int(kdfoptions)
                parse_end(kdfoptions)
                key_and_iv = bcrypt.kdf(password, salt, 32 + 16, rounds)
                c = Cipher(algorithms.AES(key_and_iv[:32]),
                           modes.CTR(key_and_iv[32:]),
                           backend=default_backend())
                d = c.decryptor()
                blob = d.update(self.protected_privatekey) + d.finalize()
            else:
                raise SyntaxError('Unsupported ciphername/kdfname')

            ## Oddly, this only partially lines up with the spec at
            ## https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?annotate=1.1
            ##
            ## Specifically, contra spec, after the checkints, we seem to have
            ## the public key again followed by the private key bytes and then
            ## a comment string.
            ##
            ## The code (sshkey.c) does this:
            ##  - retrieve a key type string
            ##  - dispatch on it
            ##  - for ed25519, read a string with the PK, then a string with the SK
            ##  - checks the sizes to ensure they are correct for ed25519
            ##
            ## This is what the PROTOCOL.key documentation says to do. It's
            ## not what actually needs to be done.
            ##
            ## [ (checkint1 :: bits 32) (= checkint1 :: bits 32) ## must be the same
            ##   (keys :: (ssh:repeat 1 (ssh:repeat 2 (ssh:string))))
            ##   (= 'padding-ok :: (ssh:padding)) ]
            ##
            (checkint1, blob) = parse_int(blob)
            (checkint2, blob) = parse_int(blob)
            if checkint1 != checkint2: raise BadPassword()
            (keytype, blob) = parse_str(blob)
            if keytype != b'ssh-ed25519': raise SyntaxError()
            (pkbytes, blob) = parse_str(blob)
            if pkbytes != self.public_key: raise BadPassword()
            (self.secret_key, blob) = parse_str(blob)
            (comment, blob) = parse_str(blob)
            self.comment = comment.decode('utf-8')
Exemple #30
0
	def derive_key():
		"""Gets a key for encryption and decryption"""

		password = getpass.getpass('Enter your password: '******'utf-8'), bytes.fromhex(hash)):
			salt = bytes.fromhex(hash[:58]) #bcrypt first 58 is salt
			password = password.encode('utf-8')
			key = bcrypt.kdf(password, salt, bcrypt_keylen, bcrypt_kdf_rounds)
			return key
		else:
			print('Invalid Password\n')
			sys.exit()
Exemple #31
0
def mdp_crypt(main_password: str, password_to_crypt: str):
    """
    @param main_password: str -> the userpassword
    @param password_to_crypt: str -> to crypt
    @return: byte string
    """
    nonce = os.urandom(32)
    key = bcrypt.kdf(password=bytes(main_password, "utf8"),
                     salt=nonce,
                     desired_key_bytes=32,
                     rounds=100)
    ciph = Cipher(AES(key), CTR(nonce), default_backend())
    encryptor = ciph.encryptor()

    return encryptor.update(bytes(password_to_crypt,
                                  "utf8")).hex(), nonce.hex()
Exemple #32
0
def mdp_decrypt(main_password: str, pasword_to_decrypt: str,
                nonce: str) -> str:
    """
    @summary décrypte un mot de passe a partir du maitre et du nonce
    @param main_password: str
    @param pasword_to_decrypt: str
    @param nonce: str
    @return: bytes .decode("utf8") pour utf8
    """
    nonce = bytes.fromhex(nonce)
    main_password = bytes(main_password, 'utf8')
    key = bcrypt.kdf(password=main_password,
                     salt=nonce,
                     desired_key_bytes=32,
                     rounds=100)
    ciph = Cipher(AES(key), CTR(nonce), default_backend())
    decryptor = ciph.decryptor()

    return decryptor.update(bytes.fromhex(pasword_to_decrypt))
Exemple #33
0
    def unprotect(self, password):
        """Decrypt the SecretKey object and return an UnprotectedSecretKey
        that can be used for signing.

        Can throw KeyError if the password is incorrect.
        """

        if self._kdfrounds == 0:
            xorkey = b"\x00" * 64
        else:
            xorkey = bcrypt.kdf(password, self._salt, 64, self._kdfrounds)
        priv = xorbuf(self._seckey, xorkey)

        checksum_ref = hashlib.sha512(priv).digest()[0:8]
        if self._checksum != checksum_ref:
            raise KeyError("incorrect password")

        usk = UnprotectedSecretKey(self)
        usk._key = priv
        return usk
Exemple #34
0
    def _parse_signing_key_data(self, data, password):
        from paramiko.transport import Transport
        # We may eventually want this to be usable for other key types, as
        # OpenSSH moves to it, but for now this is just for Ed25519 keys.
        # This format is described here:
        # https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
        # The description isn't totally complete, and I had to refer to the
        # source for a full implementation.
        message = Message(data)
        if message.get_bytes(len(OPENSSH_AUTH_MAGIC)) != OPENSSH_AUTH_MAGIC:
            raise SSHException("Invalid key")

        ciphername = message.get_text()
        kdfname = message.get_text()
        kdfoptions = message.get_binary()
        num_keys = message.get_int()

        if kdfname == "none":
            # kdfname of "none" must have an empty kdfoptions, the ciphername
            # must be "none"
            if kdfoptions or ciphername != "none":
                raise SSHException("Invalid key")
        elif kdfname == "bcrypt":
            if not password:
                raise PasswordRequiredException(
                    "Private key file is encrypted"
                )
            kdf = Message(kdfoptions)
            bcrypt_salt = kdf.get_binary()
            bcrypt_rounds = kdf.get_int()
        else:
            raise SSHException("Invalid key")

        if ciphername != "none" and ciphername not in Transport._cipher_info:
            raise SSHException("Invalid key")

        public_keys = []
        for _ in range(num_keys):
            pubkey = Message(message.get_binary())
            if pubkey.get_text() != "ssh-ed25519":
                raise SSHException("Invalid key")
            public_keys.append(pubkey.get_binary())

        private_ciphertext = message.get_binary()
        if ciphername == "none":
            private_data = private_ciphertext
        else:
            cipher = Transport._cipher_info[ciphername]
            key = bcrypt.kdf(
                password=password,
                salt=bcrypt_salt,
                desired_key_bytes=cipher["key-size"] + cipher["block-size"],
                rounds=bcrypt_rounds,
                # We can't control how many rounds are on disk, so no sense
                # warning about it.
                ignore_few_rounds=True,
            )
            decryptor = Cipher(
                cipher["class"](key[:cipher["key-size"]]),
                cipher["mode"](key[cipher["key-size"]:]),
                backend=default_backend()
            ).decryptor()
            private_data = (
                decryptor.update(private_ciphertext) + decryptor.finalize()
            )

        message = Message(unpad(private_data))
        if message.get_int() != message.get_int():
            raise SSHException("Invalid key")

        signing_keys = []
        for i in range(num_keys):
            if message.get_text() != "ssh-ed25519":
                raise SSHException("Invalid key")
            # A copy of the public key, again, ignore.
            public = message.get_binary()
            key_data = message.get_binary()
            # The second half of the key data is yet another copy of the public
            # key...
            signing_key = nacl.signing.SigningKey(key_data[:32])
            # Verify that all the public keys are the same...
            assert (
                signing_key.verify_key.encode() == public == public_keys[i] ==
                key_data[32:]
            )
            signing_keys.append(signing_key)
            # Comment, ignore.
            message.get_binary()

        if len(signing_keys) != 1:
            raise SSHException("Invalid key")
        return signing_keys[0]
Exemple #35
0
def test_kdf(rounds, password, salt, expected):
    derived = bcrypt.kdf(password, salt, len(expected), rounds)
    assert derived == expected
Exemple #36
0
def _decode_openssh_private(data, passphrase):
    """Decode an OpenSSH format private key"""

    try:
        if not data.startswith(_OPENSSH_KEY_V1):
            raise KeyImportError('Unrecognized OpenSSH private key type')

        data = data[len(_OPENSSH_KEY_V1):]
        packet = SSHPacket(data)

        cipher_name = packet.get_string()
        kdf = packet.get_string()
        kdf_data = packet.get_string()
        nkeys = packet.get_uint32()
        _ = packet.get_string()                 # public_key
        key_data = packet.get_string()
        mac = packet.get_remaining_payload()

        if nkeys != 1:
            raise KeyImportError('Invalid OpenSSH private key')

        if cipher_name != b'none':
            if not _bcrypt_available: # pragma: no cover
                raise KeyEncryptionError('OpenSSH private key encryption '
                                         'requires bcrypt')

            if passphrase is None:
                raise KeyImportError('Passphrase must be specified to import '
                                     'encrypted private keys')

            try:
                key_size, iv_size, block_size, mode = \
                    get_encryption_params(cipher_name)
            except KeyError:
                raise KeyEncryptionError('Unknown cipher: %s' %
                                         cipher_name.decode('ascii')) from None

            if kdf != b'bcrypt':
                raise KeyEncryptionError('Unknown kdf: %s' %
                                         kdf.decode('ascii'))

            packet = SSHPacket(kdf_data)
            salt = packet.get_string()
            rounds = packet.get_uint32()
            packet.check_end()

            if isinstance(passphrase, str):
                passphrase = passphrase.encode('utf-8')

            try:
                # pylint: disable=no-member
                key = bcrypt.kdf(passphrase, salt, key_size + iv_size, rounds)
                # pylint: enable=no-member
            except ValueError:
                raise KeyEncryptionError('Invalid OpenSSH '
                                         'private key') from None

            cipher = get_cipher(cipher_name, key[:key_size], key[key_size:])

            if mode == 'chacha':
                key_data = cipher.verify_and_decrypt(b'', key_data,
                                                     UInt64(0), mac)
                mac = b''
            elif mode == 'gcm':
                key_data = cipher.verify_and_decrypt(b'', key_data, mac)
                mac = b''
            else:
                key_data = cipher.decrypt(key_data)

            if key_data is None:
                raise KeyEncryptionError('Incorrect passphrase')

            block_size = max(block_size, 8)
        else:
            block_size = 8

        if mac:
            raise KeyImportError('Invalid OpenSSH private key')

        packet = SSHPacket(key_data)

        check1 = packet.get_uint32()
        check2 = packet.get_uint32()
        if check1 != check2:
            if cipher_name != b'none':
                raise KeyEncryptionError('Incorrect passphrase') from None
            else:
                raise KeyImportError('Invalid OpenSSH private key')

        alg = packet.get_string()
        handler = _public_key_alg_map.get(alg)
        if not handler:
            raise KeyImportError('Unknown OpenSSH private key algorithm')

        key_params = handler.decode_ssh_private(packet)
        _ = packet.get_string()                             # comment
        pad = packet.get_remaining_payload()

        if len(pad) >= block_size or pad != bytes(range(1, len(pad) + 1)):
            raise KeyImportError('Invalid OpenSSH private key')

        return handler.make_private(*key_params)
    except PacketDecodeError:
        raise KeyImportError('Invalid OpenSSH private key')
Exemple #37
0
    def export_private_key(self, format_name, passphrase=None,
                           cipher_name='aes256-cbc', hash_name='sha256',
                           pbe_version=2, rounds=16):
        """Export a private key in the requested format

           This function returns this object's private key encoded in the
           requested format. If a passphrase is specified, the key will
           be exported in encrypted form.

           Available formats include:

               pkcs1-der, pkcs1-pem, pkcs8-der, pkcs8-pem, openssh

           Encryption is supported in pkcs1-pem, pkcs8-der, pkcs8-pem,
           and openssh formats. For pkcs1-pem, only the cipher can be
           specified. For pkcs8-der and pkcs-8, cipher,  hash and PBE
           version can be specified. For openssh, cipher and rounds
           can be specified.

           Available ciphers for pkcs1-pem are:

               aes128-cbc, aes192-cbc, aes256-cbc, des-cbc, des3-cbc

           Available ciphers for pkcs8-der and pkcs8-pem are:

               aes128-cbc, aes192-cbc, aes256-cbc, blowfish-cbc,
               cast128-cbc, des-cbc, des2-cbc, des3-cbc, rc4-40, rc4-128

           Available ciphers for openssh format include the following
           :ref:`encryption algorithms <EncryptionAlgs>`.

           Available hashes include:

               md5, sha1, sha256, sha384, sha512, sha512-224, sha512-256

           Available PBE versions include 1 for PBES1 and 2 for PBES2.

           Not all combinations of cipher, hash, and version are supported.

           The default cipher is aes256. In the pkcs8 formats, the default
           hash is sha256 and default version is PBES2. In openssh format,
           the default number of rounds is 16.

           :param string format_name:
               The format to export the key in.
           :param string passphrase: (optional)
               A passphrase to encrypt the private key with.
           :param string cipher_name: (optional)
               The cipher to use for private key encryption.
           :param string hash_name: (optional)
               The hash to use for private key encryption.
           :param integer pbe_version: (optional)
               The PBE version to use for private key encryption.
           :param integer rounds: (optional)
               The number of KDF rounds to apply to the passphrase.

        """

        if format_name in ('pkcs1-der', 'pkcs1-pem'):
            data = der_encode(self.encode_pkcs1_private())

            if passphrase is not None:
                if format_name == 'pkcs1-der':
                    raise KeyExportError('PKCS#1 DER format does not support '
                                         'private key encryption')

                alg, iv, data = pkcs1_encrypt(data, cipher_name, passphrase)
                headers = (b'Proc-Type: 4,ENCRYPTED\n' +
                           b'DEK-Info: ' + alg + b',' +
                           binascii.b2a_hex(iv).upper() + b'\n\n')
            else:
                headers = b''

            if format_name == 'pkcs1-pem':
                keytype = self.pem_name + b' PRIVATE KEY'
                data = (b'-----BEGIN ' + keytype + b'-----\n' +
                        headers + _wrap_base64(data) +
                        b'-----END ' + keytype + b'-----\n')

            return data
        elif format_name in ('pkcs8-der', 'pkcs8-pem'):
            alg_params, data = self.encode_pkcs8_private()

            data = der_encode((0, (self.pkcs8_oid, alg_params), data))

            if passphrase is not None:
                data = pkcs8_encrypt(data, cipher_name, hash_name,
                                     pbe_version, passphrase)

            if format_name == 'pkcs8-pem':
                if passphrase is not None:
                    keytype = b'ENCRYPTED PRIVATE KEY'
                else:
                    keytype = b'PRIVATE KEY'

                data = (b'-----BEGIN ' + keytype + b'-----\n' +
                        _wrap_base64(data) +
                        b'-----END ' + keytype + b'-----\n')

            return data
        elif format_name == 'openssh':
            check = os.urandom(4)
            nkeys = 1
            comment = b''

            keydata = String(self.algorithm) + self.encode_ssh_private()

            data = b''.join((check, check, keydata, String(comment)))

            if passphrase is not None:
                if not _bcrypt_available: # pragma: no cover
                    raise KeyExportError('OpenSSH private key encryption '
                                         'requires bcrypt')

                try:
                    alg = cipher_name.encode('ascii')
                    key_size, iv_size, block_size, mode = \
                        get_encryption_params(alg)
                except (KeyError, UnicodeEncodeError):
                    raise KeyEncryptionError('Unknown cipher: %s' %
                                             cipher_name) from None

                kdf = b'bcrypt'
                salt = os.urandom(_OPENSSH_SALT_LEN)
                kdf_data = b''.join((String(salt), UInt32(rounds)))

                if isinstance(passphrase, str):
                    passphrase = passphrase.encode('utf-8')

                # pylint: disable=no-member
                key = bcrypt.kdf(passphrase, salt, key_size + iv_size, rounds)
                # pylint: enable=no-member

                cipher = get_cipher(alg, key[:key_size], key[key_size:])
                block_size = max(block_size, 8)
            else:
                cipher = None
                alg = b'none'
                kdf = b'none'
                kdf_data = b''
                block_size = 8
                mac = b''

            pad = len(data) % block_size
            if pad: # pragma: no branch
                data = data + bytes(range(1, block_size + 1 - pad))

            if cipher:
                if mode == 'chacha':
                    data, mac = cipher.encrypt_and_sign(b'', data, UInt64(0))
                elif mode == 'gcm':
                    data, mac = cipher.encrypt_and_sign(b'', data)
                else:
                    data, mac = cipher.encrypt(data), b''

            data = b''.join((_OPENSSH_KEY_V1, String(alg), String(kdf),
                             String(kdf_data), UInt32(nkeys),
                             String(self.get_ssh_public_key()),
                             String(data), mac))

            return (b'-----BEGIN OPENSSH PRIVATE KEY-----\n' +
                    _wrap_base64(data, _OPENSSH_WRAP_LEN) +
                    b'-----END OPENSSH PRIVATE KEY-----\n')
        else:
            raise KeyExportError('Unknown export format')
Exemple #38
0
import sqlite3
import bcrypt
import hashlib
from Crypto.Cipher import AES
import codecs
import json
from password import encrypt, decrypt, toHex, fromHex

pwdatabase = 'passwords.db'
jsonfile = open('passwords.json', mode='w')

password = input('Enter password: '******'select * from master_pass').fetchone()

if bcrypt.checkpw(password, pwHash):
    print('Password is correct.')
    aes_key = bcrypt.kdf(password, salt, 16, 32)
    records = [list(i) for i in conn.execute('select * from passwords')]
    for i in range(len(records)):
        records[i][3] = decrypt(aes_key, records[i][3]).decode()
        records[i][4] = decrypt(aes_key, records[i][4]).decode()
    json.dump(records, jsonfile, indent=2)
else:
    print('Incorrect password.')

jsonfile.close()
conn.close()
Exemple #39
0
def test_kdf_str_password():
    with pytest.raises(TypeError):
        bcrypt.kdf(
            six.text_type("password"), b"$2b$04$cVWp4XaNU8a4v1uMRum2SO", 10, 10
        )
Exemple #40
0
	def test_00__test_vectors(self):
		for rounds, password, salt, expected in kdf_test_vectors:
			key = bcrypt.kdf(password, salt, len(expected), rounds)
			self.assertEqual(key, expected)
Exemple #41
0
def kdf(password, salt):
    '''Generate aes key from password and salt.'''
    return bcrypt.kdf(password, salt, 16, 32)
Exemple #42
0
def test_kdf_str_salt():
    with pytest.raises(TypeError):
        bcrypt.kdf(
            b"password", six.text_type("salt"), 10, 10
        )
Exemple #43
0
def test_invalid_params(password, salt, desired_key_bytes, rounds, error):
    with pytest.raises(error):
        bcrypt.kdf(password, salt, desired_key_bytes, rounds)
    def export_private_key(
        self, format_name, passphrase=None, cipher_name="aes256-cbc", hash_name="sha256", pbe_version=2, rounds=16
    ):
        """Export a private key in the requested format

           This function returns this object's private key encoded in the
           requested format. If a passphrase is specified, the key will
           be exported in encrypted form.

           Available formats include:

               pkcs1-der, pkcs1-pem, pkcs8-der, pkcs8-pem, openssh

           Encryption is supported in pkcs1-pem, pkcs8-der, pkcs8-pem,
           and openssh formats. For pkcs1-pem, only the cipher can be
           specified. For pkcs8-der and pkcs-8, cipher,  hash and PBE
           version can be specified. For openssh, cipher and rounds
           can be specified.

           Available ciphers for pkcs1-pem are:

               aes128-cbc, aes192-cbc, aes256-cbc, des-cbc, des3-cbc

           Available ciphers for pkcs8-der and pkcs8-pem are:

               aes128-cbc, aes192-cbc, aes256-cbc, blowfish-cbc,
               cast128-cbc, des-cbc, des2-cbc, des3-cbc, rc2-40-cbc,
               rc2-64-cbc, rc2-128-cbc, rc4-40, rc4-128

           Available ciphers for openssh format include the following
           :ref:`encryption algorithms <EncryptionAlgs>`.

           Available hashes include:

               md5, sha1, sha256, sha384, sha512, sha512-224, sha512-256

           Available PBE versions include 1 for PBES1 and 2 for PBES2.

           Not all combinations of cipher, hash, and version are supported.

           The default cipher is aes256. In the pkcs8 formats, the default
           hash is sha256 and default version is PBES2. In openssh format,
           the default number of rounds is 16.

           :param string format_name:
               The format to export the key in.
           :param string passphrase: (optional)
               A passphrase to encrypt the private key with.
           :param string cipher_name: (optional)
               The cipher to use for private key encryption.
           :param string hash_name: (optional)
               The hash to use for private key encryption.
           :param integer pbe_version: (optional)
               The PBE version to use for private key encryption.
           :param integer rounds: (optional)
               The number of KDF rounds to apply to the passphrase.

        """

        if format_name in ("pkcs1-der", "pkcs1-pem"):
            data = der_encode(self.encode_pkcs1_private())

            if passphrase is not None:
                if format_name == "pkcs1-der":
                    raise KeyExportError("PKCS#1 DER format does not support " "private key encryption")

                alg, iv, data = pkcs1_encrypt(data, cipher_name, passphrase)
                headers = (
                    b"Proc-Type: 4,ENCRYPTED\n" + b"DEK-Info: " + alg + b"," + binascii.b2a_hex(iv).upper() + b"\n\n"
                )
            else:
                headers = b""

            if format_name == "pkcs1-pem":
                keytype = self.pem_name + b" PRIVATE KEY"
                data = (
                    b"-----BEGIN "
                    + keytype
                    + b"-----\n"
                    + headers
                    + _wrap_base64(data)
                    + b"-----END "
                    + keytype
                    + b"-----\n"
                )

            return data
        elif format_name in ("pkcs8-der", "pkcs8-pem"):
            alg_params, data = self.encode_pkcs8_private()

            data = der_encode((0, (self.pkcs8_oid, alg_params), data))

            if passphrase is not None:
                data = pkcs8_encrypt(data, cipher_name, hash_name, pbe_version, passphrase)

            if format_name == "pkcs8-pem":
                if passphrase is not None:
                    keytype = b"ENCRYPTED PRIVATE KEY"
                else:
                    keytype = b"PRIVATE KEY"

                data = b"-----BEGIN " + keytype + b"-----\n" + _wrap_base64(data) + b"-----END " + keytype + b"-----\n"

            return data
        elif format_name == "openssh":
            check = urandom(4)
            nkeys = 1
            comment = b""

            data = b"".join((check, check, self.encode_ssh_private(), String(comment)))

            if passphrase is not None:
                if not _bcrypt_available:
                    raise KeyExportError("OpenSSH private key encryption " "requires bcrypt")

                try:
                    alg = cipher_name.encode("ascii")
                    key_size, iv_size, block_size, mode = get_encryption_params(alg)
                except (KeyError, UnicodeEncodeError):
                    raise KeyEncryptionError("Unknown cipher: %s" % cipher_name) from None

                kdf = b"bcrypt"
                salt = urandom(_OPENSSH_SALT_LEN)
                kdf_data = b"".join((String(salt), UInt32(rounds)))

                # pylint: disable=no-member
                key = bcrypt.kdf(passphrase.encode("utf-8"), salt, key_size + iv_size, rounds)
                # pylint: enable=no-member

                cipher = get_cipher(alg, key[:key_size], key[key_size:])
                block_size = max(block_size, 8)
            else:
                cipher = None
                alg = b"none"
                kdf = b"none"
                kdf_data = b""
                block_size = 8
                mac = b""

            pad = len(data) % block_size
            if pad:
                data = data + bytes(range(1, block_size + 1 - pad))

            if cipher:
                if mode == "chacha":
                    data, mac = cipher.encrypt_and_sign(b"", data, UInt64(0))
                elif mode == "gcm":
                    data, mac = cipher.encrypt_and_sign(b"", data)
                else:
                    data, mac = cipher.encrypt(data), b""

            data = b"".join(
                (
                    _OPENSSH_KEY_V1,
                    String(alg),
                    String(kdf),
                    String(kdf_data),
                    UInt32(nkeys),
                    String(self.encode_ssh_public()),
                    String(data),
                    mac,
                )
            )

            return (
                b"-----BEGIN OPENSSH PRIVATE KEY-----\n"
                + _wrap_base64(data, _OPENSSH_WRAP_LEN)
                + b"-----END OPENSSH PRIVATE KEY-----\n"
            )
        else:
            raise KeyExportError("Unknown export format")
def _decode_openssh_private(data, passphrase):
    """Decode an OpenSSH format private key"""

    try:
        if not data.startswith(_OPENSSH_KEY_V1):
            raise KeyImportError("Unrecognized OpenSSH private key type")

        data = data[len(_OPENSSH_KEY_V1) :]
        packet = SSHPacket(data)

        cipher_name = packet.get_string()
        kdf = packet.get_string()
        kdf_data = packet.get_string()
        nkeys = packet.get_uint32()
        _ = packet.get_string()  # public_key
        key_data = packet.get_string()
        mac = packet.get_remaining_payload()

        if nkeys != 1:
            raise KeyImportError("Invalid OpenSSH private key")

        if cipher_name != b"none":
            if not _bcrypt_available:
                raise KeyEncryptionError("OpenSSH private key encryption " "requires bcrypt")

            if passphrase is None:
                raise KeyEncryptionError("Passphrase must be specified to " "import encrypted private keys")

            try:
                key_size, iv_size, block_size, mode = get_encryption_params(cipher_name)
            except KeyError:
                raise KeyEncryptionError("Unknown cipher: %s" % cipher_name.decode("ascii")) from None

            if kdf != b"bcrypt":
                raise KeyEncryptionError("Unknown kdf: %s" % kdf.decode("ascii"))

            packet = SSHPacket(kdf_data)
            salt = packet.get_string()
            rounds = packet.get_uint32()
            packet.check_end()

            # pylint: disable=no-member
            key = bcrypt.kdf(passphrase.encode("utf-8"), salt, key_size + iv_size, rounds)
            # pylint: enable=no-member

            cipher = get_cipher(cipher_name, key[:key_size], key[key_size:])

            if mode == "chacha":
                key_data = cipher.verify_and_decrypt(b"", key_data, UInt64(0), mac)
                mac = b""
            elif mode == "gcm":
                key_data = cipher.verify_and_decrypt(b"", key_data, mac)
                mac = b""
            else:
                key_data = cipher.decrypt(key_data)

            if key_data is None:
                raise KeyEncryptionError("Incorrect passphrase") from None

            block_size = max(block_size, 8)
        else:
            block_size = 8

        if mac:
            raise KeyEncryptionError("Invalid OpenSSH private key")

        packet = SSHPacket(key_data)

        check1 = packet.get_uint32()
        check2 = packet.get_uint32()
        if check1 != check2:
            raise KeyImportError("Invalid OpenSSH private key")

        alg = packet.get_string()
        handler = _public_key_alg_map.get(alg)
        if not handler:
            raise KeyImportError("Unknown OpenSSH private key algorithm")

        key_params = handler.decode_ssh_private(packet)
        _ = packet.get_string()  # comment
        pad = packet.get_remaining_payload()

        if len(pad) >= block_size or pad != bytes(range(1, len(pad) + 1)):
            raise KeyImportError("Invalid OpenSSH private key")

        if not key_params:
            raise KeyImportError("Invalid %s private key" % handler.pem_name.decode("ascii"))

        return handler.make_private(*key_params)
    except DisconnectError:
        raise KeyImportError("Invalid OpenSSH private key")