def decrypt_entry(self, identity=None, passphrase=None, card_slot=None): #################################################################### """Decrypt this password entry for a particular identity (usually the user)""" #################################################################### try: recipient_entry = self.recipients[identity["name"]] except KeyError as err: raise NotARecipientError( f"Identity '{identity}' is not on the recipient list for password '{self.metadata['name']}'" ) from err try: # support old yaml format return pk_decrypt_string( recipient_entry["encrypted_secret"], recipient_entry["derived_key"], identity, passphrase, card_slot, ) except KeyError: try: # support rsa if "key" in identity and identity["key"]: for _, value in recipient_entry["encrypted_secrets"].items(): return pk_decrypt_string( value["encrypted_secret"], value["derived_key"], identity, passphrase, ) else: cert_key = get_card_fingerprint(card_slot=card_slot) return pk_decrypt_string( recipient_entry["encrypted_secrets"][cert_key][ "encrypted_secret" ], recipient_entry["encrypted_secrets"][cert_key]["derived_key"], identity, passphrase, card_slot, ) except DecryptionError as err: msg = create_error_message(recipient_entry["timestamp"], card_slot) raise DecryptionError( f"Error decrypting password named '{self.metadata['name']}'. {msg}" ) from err except KeyError as err: raise DecryptionError( f"Error decrypting password named '{self.metadata['name']}'. Appropriate private key not found" ) from err except DecryptionError as err: msg = create_error_message(recipient_entry["timestamp"], card_slot) raise DecryptionError( f"Error decrypting password named '{self.metadata['name']}'. {msg}" ) from err
def decrypt_entry(self, identity=None, passphrase=None, card_slot=None): """ Decrypt this password entry for a particular identity (usually the user) """ ####################################################################### try: recipient_entry = self.recipients[identity['uid']] except KeyError: raise NotARecipientError( "Identity '%s' is not on the recipient list for password '%s'" % (identity['uid'], self.metadata['name'])) try: # support old yaml format return crypto.pk_decrypt_string( recipient_entry['encrypted_secret'], recipient_entry['derived_key'], identity, passphrase, card_slot) except KeyError: try: # support rsa if 'key_path' in identity.keys(): for _, value in recipient_entry['encrypted_secrets'].items(): return crypto.pk_decrypt_string( value['encrypted_secret'], value['derived_key'], identity, passphrase ) else: cert_key = crypto.get_card_fingerprint() return crypto.pk_decrypt_string( recipient_entry['encrypted_secrets'][cert_key]['encrypted_secret'], recipient_entry['encrypted_secrets'][cert_key]['derived_key'], identity, passphrase, card_slot) except DecryptionError: msg = create_error_message(recipient_entry['timestamp'], card_slot) raise DecryptionError( "Error decrypting password named '%s'. %s" % (self.metadata['name'], msg)) except KeyError: raise DecryptionError( "Error decrypting password named '%s'. Appropriate private key not found" % self.metadata['name']) except DecryptionError: msg = create_error_message(recipient_entry['timestamp'], card_slot) raise DecryptionError("Error decrypting password named '%s'. %s" % (self.metadata['name'], msg))
def pk_decrypt_string(ciphertext_string, ciphertext_derived_key, identity, passphrase, card_slot=None): #################################################################### """Decrypt a base64 encoded string for the provided identity""" #################################################################### ciphertext_derived_key = handle_python_strings(ciphertext_derived_key) if "key" in identity and identity["key"]: command = [ "openssl", "rsautl", "-inkey", identity["key"], "-decrypt", "-pkcs" ] with Popen(command, stdout=PIPE, stdin=PIPE, stderr=STDOUT) as proc: stdout, _ = proc.communicate( input=urlsafe_b64decode(ciphertext_derived_key)) returncode = proc.returncode plaintext_derived_key = stdout else: # We've got to use pkcs15-crypt for PIV cards, and it only supports pin on # command line (insecure) or via stdin. So, we have to put ciphertext into # a file for pkcs15-crypt to read. YUCK! with NamedTemporaryFile(delete=False) as fname: fname.write(urlsafe_b64decode(ciphertext_derived_key)) command = [ "pkcs15-crypt", "--decipher", "--raw", "--pkcs", "--input", fname.name, ] if card_slot is not None: command.extend(["--reader", str(card_slot)]) command.extend(["--pin", "-"]) with Popen(command, stdout=PIPE, stdin=PIPE, stderr=DEVNULL) as proc: stdout, _ = proc.communicate(input=passphrase.encode("UTF-8")) unlink(fname.name) try: plaintext_derived_key = stdout except IndexError as err: raise DecryptionError(stdout) from err returncode = proc.returncode if returncode != 0: raise DecryptionError(stdout) return (Fernet(plaintext_derived_key).decrypt( handle_python_strings(ciphertext_string)).decode("UTF-8"))
def pk_decrypt_string(ciphertext_string, ciphertext_derived_key, identity, passphrase, card_slot=None): """ Decrypt a base64 encoded string for the provided identity""" ############################################################################## ciphertext_derived_key = handle_python_strings(ciphertext_derived_key) if 'key_path' in identity: command = [ 'openssl', 'rsautl', '-inkey', identity['key_path'], '-decrypt', '-pkcs' ] proc = Popen(command, stdout=PIPE, stdin=PIPE, stderr=STDOUT) stdout, _ = proc.communicate( input=base64.urlsafe_b64decode(ciphertext_derived_key)) plaintext_derived_key = stdout else: # We've got to use pkcs15-crypt for PIV cards, and it only supports pin on # command line (insecure) or via stdin. So, we have to put ciphertext into # a file for pkcs15-crypt to read. YUCK! with tempfile.NamedTemporaryFile(delete=False) as fname: fname.write(base64.urlsafe_b64decode(ciphertext_derived_key)) command = [ 'pkcs15-crypt', '--decipher', '--raw', '--pkcs', '--input', fname.name ] if card_slot is not None: command.extend(['--reader', str(card_slot)]) command.extend(['--pin', '-']) #subprocess.DEVNULL doesn't exist in python2 so... with open(os.devnull, 'w') as devnull: proc = Popen(command, stdout=PIPE, stdin=PIPE, stderr=devnull) stdout, _ = proc.communicate(input=passphrase.encode('ASCII')) os.unlink(fname.name) try: plaintext_derived_key = stdout except IndexError: raise DecryptionError(stdout) if proc.returncode != 0: raise DecryptionError(stdout) fern = Fernet(plaintext_derived_key) plaintext_string = fern.decrypt(handle_python_strings(ciphertext_string)) return plaintext_string.decode("ASCII")
def sk_decrypt_string(ciphertext_string, key): """ Symmetrically Decrypt a base64 encoded string using the provided key""" ############################################################################## fern = Fernet(hash_password(key)) ciphertext_string = handle_python_strings(ciphertext_string) try: plaintext_string = fern.decrypt( base64.urlsafe_b64decode(handle_python_strings(ciphertext_string))) return plaintext_string.decode("ASCII") except InvalidToken: raise DecryptionError("Incorrect Password")
def sk_decrypt_string(ciphertext_string, key): #################################################################### """Symmetrically Decrypt a base64 encoded string using the provided key""" #################################################################### fern = Fernet(hash_password(key)) ciphertext_string = handle_python_strings(ciphertext_string) try: plaintext_string = fern.decrypt( urlsafe_b64decode(handle_python_strings(ciphertext_string))) return plaintext_string.decode("UTF-8") except InvalidToken: # handle some legacy stuff from NCCS try: plaintext_string = fern.decrypt(ciphertext_string) return plaintext_string.decode("UTF-8") except InvalidToken as err: raise DecryptionError("Incorrect Password") from err
def decrypt_entry(self, identity=None, passphrase=None, card_slot=None): """ Decrypt this password entry for a particular identity (usually the user) """ ####################################################################### try: recipient_entry = self.recipients[identity['uid']] except KeyError: raise NotARecipientError( "Identity '%s' is not on the recipient list for password '%s'" % (identity['uid'], self.metadata['name'])) try: return crypto.pk_decrypt_string( recipient_entry['encrypted_secret'], recipient_entry['derived_key'], identity, passphrase, card_slot) except DecryptionError: raise DecryptionError( "Error decrypting password named '%s'. Perhaps a bad pin/passphrase?" % self.metadata['name'])