fix(keyringctl): avoid simplified uid collisions using a hash
Add a postfix hash of the raw uid data to the filenames to avoid collisions with the simplified uid.
This commit is contained in:
parent
4821087b2b
commit
0ceb6c743e
@ -38,7 +38,7 @@ from .util import contains_fingerprint
|
|||||||
from .util import filter_fingerprints_by_trust
|
from .util import filter_fingerprints_by_trust
|
||||||
from .util import get_cert_paths
|
from .util import get_cert_paths
|
||||||
from .util import get_fingerprint_from_partial
|
from .util import get_fingerprint_from_partial
|
||||||
from .util import simplify_ascii
|
from .util import simplify_uid
|
||||||
from .util import transform_fd_to_tmpfile
|
from .util import transform_fd_to_tmpfile
|
||||||
|
|
||||||
PACKET_FILENAME_DATETIME_FORMAT: str = "%Y-%m-%d_%H-%M-%S"
|
PACKET_FILENAME_DATETIME_FORMAT: str = "%Y-%m-%d_%H-%M-%S"
|
||||||
@ -353,7 +353,7 @@ def convert_certificate(
|
|||||||
elif packet.name.endswith("--UserID"):
|
elif packet.name.endswith("--UserID"):
|
||||||
current_packet_mode = "uid"
|
current_packet_mode = "uid"
|
||||||
current_packet_fingerprint = None
|
current_packet_fingerprint = None
|
||||||
current_packet_uid = Uid(simplify_ascii(packet_dump_field(packet, "Value")))
|
current_packet_uid = Uid(packet_dump_field(packet, "Value"))
|
||||||
|
|
||||||
if current_packet_uid in uids:
|
if current_packet_uid in uids:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
@ -549,7 +549,8 @@ def persist_uids(
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
for uid, uid_packet in uids.items():
|
for uid, uid_packet in uids.items():
|
||||||
output_file = key_dir / "uid" / uid / f"{uid}.asc"
|
simplified_uid = simplify_uid(uid)
|
||||||
|
output_file = key_dir / "uid" / simplified_uid / f"{simplified_uid}.asc"
|
||||||
output_file.parent.mkdir(parents=True, exist_ok=True)
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
debug(f"Writing file {output_file} from {uid_packet}")
|
debug(f"Writing file {output_file} from {uid_packet}")
|
||||||
packet_join(packets=[uid_packet], output=output_file, force=True)
|
packet_join(packets=[uid_packet], output=output_file, force=True)
|
||||||
@ -703,7 +704,7 @@ def persist_uid_certifications(
|
|||||||
|
|
||||||
for uid, uid_certifications in certifications.items():
|
for uid, uid_certifications in certifications.items():
|
||||||
for issuer, issuer_certifications in uid_certifications.items():
|
for issuer, issuer_certifications in uid_certifications.items():
|
||||||
certification_dir = key_dir / "uid" / uid / "certification"
|
certification_dir = key_dir / "uid" / simplify_uid(uid) / "certification"
|
||||||
certification_dir.mkdir(parents=True, exist_ok=True)
|
certification_dir.mkdir(parents=True, exist_ok=True)
|
||||||
certification = latest_certification(issuer_certifications)
|
certification = latest_certification(issuer_certifications)
|
||||||
output_file = certification_dir / f"{issuer}.asc"
|
output_file = certification_dir / f"{issuer}.asc"
|
||||||
@ -728,7 +729,7 @@ def persist_uid_revocations(
|
|||||||
|
|
||||||
for uid, uid_revocations in revocations.items():
|
for uid, uid_revocations in revocations.items():
|
||||||
for issuer, issuer_revocations in uid_revocations.items():
|
for issuer, issuer_revocations in uid_revocations.items():
|
||||||
revocation_dir = key_dir / "uid" / uid / "revocation"
|
revocation_dir = key_dir / "uid" / simplify_uid(uid) / "revocation"
|
||||||
revocation_dir.mkdir(parents=True, exist_ok=True)
|
revocation_dir.mkdir(parents=True, exist_ok=True)
|
||||||
revocation = latest_certification(issuer_revocations)
|
revocation = latest_certification(issuer_revocations)
|
||||||
output_file = revocation_dir / f"{issuer}.asc"
|
output_file = revocation_dir / f"{issuer}.asc"
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
from collections.abc import Iterator
|
from collections.abc import Iterator
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
from hashlib import sha256
|
||||||
from os import chdir
|
from os import chdir
|
||||||
from os import environ
|
from os import environ
|
||||||
from os import getcwd
|
from os import getcwd
|
||||||
@ -28,6 +29,7 @@ from typing import Union
|
|||||||
|
|
||||||
from libkeyringctl.types import Fingerprint
|
from libkeyringctl.types import Fingerprint
|
||||||
from libkeyringctl.types import Trust
|
from libkeyringctl.types import Trust
|
||||||
|
from libkeyringctl.types import Uid
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
@ -312,3 +314,20 @@ def simplify_ascii(_str: str) -> str:
|
|||||||
_str = "".join([ascii_mapping_lookup.get(char) or char for char in _str])
|
_str = "".join([ascii_mapping_lookup.get(char) or char for char in _str])
|
||||||
_str = sub("[^" + escape(simple_printable) + "]", "_", _str)
|
_str = sub("[^" + escape(simple_printable) + "]", "_", _str)
|
||||||
return _str
|
return _str
|
||||||
|
|
||||||
|
|
||||||
|
def simplify_uid(uid: Uid, hash_postfix: bool = True) -> str:
|
||||||
|
"""Simplify a uid to contain more filesystem and printable friendly characters with an optional
|
||||||
|
collision resistant hash postfix.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
uid: Uid to simplify (e.g. 'Foobar McFooface <foobar@foo.face>')
|
||||||
|
hash_postfix: Whether to add a hash of the uid as postfix
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Simplified str representation of uid
|
||||||
|
"""
|
||||||
|
_hash = "" if not hash_postfix else f"_{sha256(uid.encode()).hexdigest()[:8]}"
|
||||||
|
return f"{simplify_ascii(_str=uid)}{_hash}"
|
||||||
|
@ -18,7 +18,7 @@ from libkeyringctl.types import Fingerprint
|
|||||||
from libkeyringctl.types import Uid
|
from libkeyringctl.types import Uid
|
||||||
from libkeyringctl.util import get_cert_paths
|
from libkeyringctl.util import get_cert_paths
|
||||||
from libkeyringctl.util import get_fingerprint_from_partial
|
from libkeyringctl.util import get_fingerprint_from_partial
|
||||||
from libkeyringctl.util import simplify_ascii
|
from libkeyringctl.util import simplify_uid
|
||||||
from libkeyringctl.util import system
|
from libkeyringctl.util import system
|
||||||
|
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ def verify_integrity(certificate: Path, all_fingerprints: Set[Fingerprint]) -> N
|
|||||||
|
|
||||||
assert_packet_kind(path=uid_path, expected="User")
|
assert_packet_kind(path=uid_path, expected="User")
|
||||||
|
|
||||||
uid_value = Uid(simplify_ascii(packet_dump_field(packet=uid_path, field="Value")))
|
uid_value = simplify_uid(Uid(packet_dump_field(packet=uid_path, field="Value")))
|
||||||
if uid_value != uid.name:
|
if uid_value != uid.name:
|
||||||
raise Exception(f"Unexpected uid in file {str(uid_path)}: {uid_value}")
|
raise Exception(f"Unexpected uid in file {str(uid_path)}: {uid_value}")
|
||||||
elif not uid_path.is_dir():
|
elif not uid_path.is_dir():
|
||||||
|
@ -34,7 +34,7 @@ from libkeyringctl.types import Fingerprint
|
|||||||
from libkeyringctl.types import Uid
|
from libkeyringctl.types import Uid
|
||||||
from libkeyringctl.types import Username
|
from libkeyringctl.types import Username
|
||||||
from libkeyringctl.util import cwd
|
from libkeyringctl.util import cwd
|
||||||
from libkeyringctl.util import simplify_ascii
|
from libkeyringctl.util import simplify_uid
|
||||||
from libkeyringctl.util import system
|
from libkeyringctl.util import system
|
||||||
|
|
||||||
test_keys: Dict[Username, List[Path]] = defaultdict(list)
|
test_keys: Dict[Username, List[Path]] = defaultdict(list)
|
||||||
@ -133,7 +133,7 @@ def create_uid_certification(
|
|||||||
certificate: Path = test_certificates[certified][0]
|
certificate: Path = test_certificates[certified][0]
|
||||||
fingerprint: Fingerprint = Fingerprint(test_keyring_certificates[certified][0].name)
|
fingerprint: Fingerprint = Fingerprint(test_keyring_certificates[certified][0].name)
|
||||||
issuer_fingerprint: Fingerprint = Fingerprint(test_keyring_certificates[issuer][0].name)
|
issuer_fingerprint: Fingerprint = Fingerprint(test_keyring_certificates[issuer][0].name)
|
||||||
simplified_uid = Uid(simplify_ascii(uid))
|
simplified_uid = simplify_uid(Uid(uid))
|
||||||
|
|
||||||
output: Path = (
|
output: Path = (
|
||||||
working_dir
|
working_dir
|
||||||
|
Loading…
Reference in New Issue
Block a user