Skip to content

Commit

Permalink
something went wrong with my pushes...
Browse files Browse the repository at this point in the history
  • Loading branch information
nginsburg committed Apr 6, 2020
1 parent ee93a22 commit 0dde0cc
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 16 deletions.
39 changes: 24 additions & 15 deletions libpkpass/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,22 @@
import os
import hashlib
import shutil
from subprocess import Popen, PIPE, STDOUT
from subprocess import Popen, PIPE, STDOUT, DEVNULL
from cryptography.fernet import Fernet, InvalidToken
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from libpkpass.util import color_prepare
from libpkpass.errors import EncryptionError, DecryptionError, SignatureCreationError, X509CertificateError

##############################################################################
def handle_python_strings(string):
"""handles py2/3 incompatiblities"""
##############################################################################
if not isinstance(string, bytes):
string = string.encode("ASCII")
return string

##############################################################################
def pk_encrypt_string(plaintext_string, identity):
""" Encrypt and return a base 64 encoded string for the provided identity"""
Expand All @@ -29,9 +37,9 @@ def pk_encrypt_string(plaintext_string, identity):
ciphertext_derived_key = stdout

fern = Fernet(plaintext_derived_key)
encrypted_string = fern.encrypt(plaintext_string.encode("ASCII"))
encrypted_string = fern.encrypt(handle_python_strings(plaintext_string))

return (encrypted_string, base64.urlsafe_b64encode(ciphertext_derived_key))
return (encrypted_string, base64.urlsafe_b64encode(handle_python_strings(ciphertext_derived_key)))

##############################################################################
def print_card_info(card_slot, identity, verbosity, color, theme_map):
Expand All @@ -41,7 +49,7 @@ def print_card_info(card_slot, identity, verbosity, color, theme_map):
command = ['pkcs11-tool', '-L']
proc = Popen(command, stdout=PIPE, stdin=PIPE, stderr=STDOUT)
stdout, _ = proc.communicate()
out_list = stdout.split(b'Slot')
out_list = handle_python_strings(stdout).split(b'Slot')
if verbosity > 1:
print_all_slots(stdout, color, theme_map)
for out in out_list[1:]:
Expand All @@ -58,13 +66,14 @@ def print_all_slots(slot_info, color, theme_map):
##############################################################################
columns = int(shutil.get_terminal_size().columns) // 4
print(color_prepare("#" * columns, "debug", color, theme_map))
print(slot_info.decode("ASCII").strip())
print(handle_python_strings(slot_info).decode("ASCII").strip())
print(color_prepare("#" * columns, "debug", color, theme_map))

##############################################################################
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)
Expand All @@ -81,9 +90,7 @@ def pk_decrypt_string(ciphertext_string, ciphertext_derived_key, identity, passp
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)
proc = Popen(command, stdout=PIPE, stdin=PIPE, stderr=DEVNULL)
stdout, _ = proc.communicate(input=passphrase.encode('ASCII'))
os.unlink(fname.name)
try:
Expand All @@ -96,7 +103,7 @@ def pk_decrypt_string(ciphertext_string, ciphertext_derived_key, identity, passp

fern = Fernet(plaintext_derived_key)

plaintext_string = fern.decrypt(ciphertext_string)
plaintext_string = fern.decrypt(handle_python_strings(ciphertext_string))
return plaintext_string.decode("ASCII")

##############################################################################
Expand All @@ -108,7 +115,7 @@ def pk_sign_string(string, identity, passphrase, card_slot=None):
command = ['openssl', 'rsautl', '-sign', '-inkey', identity['key_path']]
proc = Popen(command, stdout=PIPE, stdin=PIPE, stderr=STDOUT)
stdout, _ = proc.communicate(input=stringhash.encode('ASCII'))
signature = base64.urlsafe_b64encode(stdout)
signature = base64.urlsafe_b64encode(handle_python_strings(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 signature text
Expand All @@ -125,7 +132,7 @@ def pk_sign_string(string, identity, passphrase, card_slot=None):
out.close()

with open(out.name, 'rb') as sigfile:
signature = base64.urlsafe_b64encode(sigfile.read())
signature = base64.urlsafe_b64encode(handle_python_strings(sigfile.read()))

os.unlink(fname.name)
os.unlink(out.name)
Expand All @@ -142,7 +149,7 @@ def pk_verify_signature(string, signature, identity):
stringhash = hashlib.sha256(string.encode("ASCII")).hexdigest()
command = ['openssl', 'rsautl', '-inkey', identity['certificate_path'], '-certin', '-verify']
proc = Popen(command, stdout=PIPE, stdin=PIPE, stderr=STDOUT)
stdout, _ = proc.communicate(input=base64.urlsafe_b64decode(signature))
stdout, _ = proc.communicate(input=base64.urlsafe_b64decode(handle_python_strings(signature)))

return stdout.decode("ASCII") == stringhash

Expand Down Expand Up @@ -216,15 +223,16 @@ def sk_encrypt_string(plaintext_string, key):
##############################################################################
fern = Fernet(hash_password(key))
encrypted_string = fern.encrypt(plaintext_string.encode('ASCII'))
return base64.urlsafe_b64encode(encrypted_string)
return base64.urlsafe_b64encode(handle_python_strings(encrypted_string))

##############################################################################
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(ciphertext_string))
plaintext_string = fern.decrypt(base64.urlsafe_b64decode(handle_python_strings(ciphertext_string)))
return plaintext_string.decode("ASCII")
except InvalidToken:
# handle some legacy stuff from NCCS
Expand All @@ -238,6 +246,7 @@ def sk_decrypt_string(ciphertext_string, key):
def hash_password(password):
"""Hash people's password"""
##############################################################################
password = handle_python_strings("%s" % password)
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=b"salt",
iterations=100000, backend=default_backend())
return base64.urlsafe_b64encode(kdf.derive(password))
return base64.urlsafe_b64encode(handle_python_strings(kdf.derive(password)))
2 changes: 1 addition & 1 deletion libpkpass/password.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def verify_entry(self, uid=None, iddb=None):
identitydb = iddb.iddb
recipient_entry = self.recipients[uid].copy()
distributor = recipient_entry['distributor']
iddb.verify_identity(distributor)
iddb.verify_identity(distributor, [])
signature = recipient_entry.pop('signature')
message = self._create_signable_string(recipient_entry)
sig_ok = crypto.pk_verify_signature(
Expand Down

0 comments on commit 0dde0cc

Please sign in to comment.