Implement key stripping

This commit is contained in:
David Duque 2020-12-06 02:27:04 +00:00
parent 7f2c43219e
commit 15ac7988f3
No known key found for this signature in database
GPG key ID: 2F327738A3C0AE3A
2 changed files with 35 additions and 4 deletions

View file

@ -56,7 +56,7 @@ def fork_context(f, context = default_context):
with tempfile.TemporaryDirectory() as tmpdir: with tempfile.TemporaryDirectory() as tmpdir:
shutil.copytree(context.home_dir, f"{tmpdir}/gnupg") shutil.copytree(context.home_dir, f"{tmpdir}/gnupg")
kwargs["context"] = gpg.Context(armor=context.armor, home_dir=f"{tmpdir}/gnupg") kwargs["context"] = gpg.Context(armor=context.armor, home_dir=f"{tmpdir}/gnupg")
f(*args, **kwargs) return f(*args, **kwargs)
return wrapped return wrapped

View file

@ -1,6 +1,6 @@
#!/usr/local/lib/mailinabox/env/bin/python #!/usr/local/lib/mailinabox/env/bin/python
# WDK (Web Key Directory) Manager: Facilitates discovery of keys by third-parties # WDK (Web Key Directory) Manager: Facilitates discovery of keys by third-parties
# Current relevant documents: https://tools.ietf.org/id/draft-koch-openpgp-webkey-service-10.html # Current relevant documents: https://tools.ietf.org/id/draft-koch-openpgp-webkey-service-11.html
import pgp, utils import pgp, utils
from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hashes
@ -29,8 +29,39 @@ def zbase32(digest):
@pgp.fork_context @pgp.fork_context
# Strips and exports a key so that only the provided UID index(es) remain. # Strips and exports a key so that only the provided UID index(es) remain.
def key_stripped(key, uid_index, context = None): # This is to comply with the following requirement, set forth in section 5 of the draft:
pass #
# The mail provider MUST make sure to publish a key in a way
# that only the mail address belonging to the requested user
# is part of the User ID packets included in the returned key.
# Other User ID packets and their associated binding signatures
# MUST be removed before publication.
def strip_and_export(fpr, except_uid_indexes, context):
context.armor = False # We need to disable armor output for this key
k = pgp.get_key(fpr, context)
if k is None:
return None
for i in except_uid_indexes:
if i > len(k.uids):
raise ValueError(f"UID index {i} out of bounds")
switch = [(f"uid {i+1}" if i + 1 not in except_uid_indexes else "") for i in range(len(k.uids))] + ["deluid", "save"]
stage = [-1] # Horrible hack: Because it's a reference (aka pointer), we can pass these around
def interaction(request, prompt):
print(f"{request}/{prompt}")
if request in ["GOT_IT", "KEY_CONSIDERED", ""]:
return 0
elif request == "GET_BOOL":
# No way to confirm interactively, so we just say yes
return "y" # Yeah, I'd also rather just return True but that doesn't work
elif request == "GET_LINE" and prompt == "keyedit.prompt":
stage[0] += 1
return switch[stage[0]]
else:
raise Exception("No idea of what to do!")
context.interact(k, interaction)
return pgp.export_key(fpr, context)
def set_wkd_published(fingerprint, publish): def set_wkd_published(fingerprint, publish):
if pgp.get_key(fingerprint) is None: if pgp.get_key(fingerprint) is None: