4f6950f50ec0762fa2f9f378739379b71f23ac11
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 1 month ago

1) # SPDX-FileCopyrightText: 2024 Marco Ricci <m@the13thletter.info>
2) #
3) # SPDX-License-Identifier: MIT
4) 
Marco Ricci Update documentation to use...

Marco Ricci authored 1 month ago

5) """Python port of the vault(1) password generation scheme"""
Marco Ricci Move `sequin` and `ssh_agen...

Marco Ricci authored 1 month ago

6) 
7) from __future__ import annotations
8) 
9) import base64
10) import collections
11) import hashlib
12) import math
13) import unicodedata
14) from collections.abc import Callable
15) from typing import TypeAlias
16) 
17) from typing_extensions import assert_type
18) 
19) from derivepassphrase import sequin, ssh_agent
20) 
21) __author__ = 'Marco Ricci <m@the13thletter.info>'
22) 
23) 
24) class AmbiguousByteRepresentationError(ValueError):
25)     """The object has an ambiguous byte representation."""
26) 
27)     def __init__(self) -> None:
28)         super().__init__('text string has ambiguous byte representation')
29) 
30) 
31) _CHARSETS = collections.OrderedDict([
32)     ('lower', b'abcdefghijklmnopqrstuvwxyz'),
33)     ('upper', b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
34)     ('alpha', b''),  # Placeholder.
35)     ('number', b'0123456789'),
36)     ('alphanum', b''),  # Placeholder.
37)     ('space', b' '),
38)     ('dash', b'-_'),
39)     ('symbol', b'!"#$%&\'()*+,./:;<=>?@[\\]^{|}~-_'),
40)     ('all', b''),  # Placeholder.
41) ])
42) _CHARSETS['alpha'] = _CHARSETS['lower'] + _CHARSETS['upper']
43) _CHARSETS['alphanum'] = _CHARSETS['alpha'] + _CHARSETS['number']
44) _CHARSETS['all'] = (
45)     _CHARSETS['alphanum'] + _CHARSETS['space'] + _CHARSETS['symbol']
46) )
47) 
48) 
49) class Vault:
50)     """A work-alike of James Coglan's vault.
51) 
52)     Store settings for generating (actually: deriving) passphrases for
53)     named services, with various constraints, given only a master
54)     passphrase.  Also, actually generate the passphrase.  The derivation
55)     is deterministic and non-secret; only the master passphrase need be
56)     kept secret.  The implementation is compatible with [vault][].
57) 
58)     [James Coglan explains the passphrase derivation algorithm in great
59)     detail][ALGORITHM] in his blog post on said topic: A principally
60)     infinite bit stream is obtained by running a key-derivation function
61)     on the master passphrase and the service name, then this bit stream
Marco Ricci Update documentation to use...

Marco Ricci authored 1 month ago

62)     is fed into a [Sequin][derivepassphrase.sequin.Sequin] to generate
63)     random numbers in the correct range, and finally these random
64)     numbers select passphrase characters until the desired length is
65)     reached.