| | import gradio |
| |
|
| | import gpm.pipeline |
| |
|
| | |
| |
|
| | STYLE = '''.gradio-container button.primary:active { box-shadow: inset 0 0 0 256px rgba(255, 255, 255, 0.16); }''' |
| | TITLE = '''Generative Password Manager''' |
| | INTRO = '''This is a POC, do **not** use it to manage your secrets.\nStateless password manager: you don't need to save passwords, they can all be derived from a single master key.\nAlways use the same format for a given target / ID: for example the password generated for "Github" and "github.com" are different.''' |
| |
|
| | |
| |
|
| | |
| | CHARS = 0 |
| | WORDS = 1 |
| |
|
| | |
| | DIGITS = 1 |
| | LOWERS = 2 |
| | UPPERS = 4 |
| | SPACES = 8 |
| | SYMBOLS = 16 |
| |
|
| | |
| |
|
| | def create_intro_block(intro: str) -> dict: |
| | __intro = gradio.Markdown(intro, line_breaks=True) |
| | return {'intro_block': __intro} |
| |
|
| | |
| |
|
| | def create_master_block() -> dict: |
| | __key = gradio.Textbox(label='Key', type='text', value='', placeholder='Your master key. It should be hard to guess as it conditions all the passwords generated.', lines=1, max_lines=1, scale=1, interactive=True) |
| | return { |
| | 'key_block': __key,} |
| |
|
| | |
| |
|
| | def create_vocabulary_block() -> dict: |
| | __level = gradio.Radio(label='Level', type='value', value=CHARS, choices=[('Character', CHARS), ('Word', WORDS)], interactive=True) |
| | __vocabulary = gradio.CheckboxGroup(label='Vocabulary', type='value', value=[DIGITS, LOWERS, UPPERS], choices=[('Digits', DIGITS), ('Lowercase', LOWERS), ('Uppercase', UPPERS), ('Spaces', SPACES), ('Symbols', SYMBOLS)], interactive=True) |
| | return { |
| | 'level_block': __level, |
| | 'vocabulary_block': __vocabulary,} |
| |
|
| | |
| |
|
| | def create_sampling_block() -> dict: |
| | __length = gradio.Slider(label='Length', value=8, minimum=1, maximum=32, step=1, scale=1, interactive=True) |
| | __nonce = gradio.Number(label='Nonce', value=1, minimum=0, maximum=2 ** 32, step=1, scale=1, interactive=True) |
| | return { |
| | 'length_block': __length, |
| | 'nonce_block': __nonce,} |
| |
|
| | |
| |
|
| | def create_inputs_block() -> dict: |
| | __target = gradio.Textbox(label='Target', type='text', value='', placeholder='The login target (URL, IP, name, etc), like "Hugging Face" or "https://github.com".', lines=1, max_lines=1, scale=1, interactive=True) |
| | __identifier = gradio.Textbox(label='Identifier', type='text', value='', placeholder='The login ID (username, email, etc), like "John Doe" or "john.doe@example.com".', lines=1, max_lines=1, scale=1, interactive=True) |
| | return { |
| | 'target_block': __target, |
| | 'identifier_block': __identifier,} |
| |
|
| | |
| |
|
| | def create_outputs_block() -> dict: |
| | __password = gradio.Textbox(label='Password', type='text', value='', placeholder='The generated password. Provided a master key, the manager will always generate the same password for a (target, login) pair.', lines=1, max_lines=1, scale=1, interactive=False) |
| | return { |
| | 'password_block': __password,} |
| |
|
| | |
| |
|
| | def create_actions_block() -> dict: |
| | __process = gradio.Button('Generate', variant='primary', size='lg', scale=1, interactive=True) |
| | return {'process_block': __process,} |
| |
|
| | |
| |
|
| | def create_state() -> dict: |
| | return {} |
| |
|
| | |
| |
|
| | def create_layout(intro: str=INTRO) -> dict: |
| | __fields = {} |
| | __fields.update(create_intro_block(intro=intro)) |
| | with gradio.Tabs(): |
| | with gradio.Tab('Manager') as __main_tab: |
| | __fields.update({'main_tab': __main_tab}) |
| | with gradio.Row(equal_height=True): |
| | __fields.update(create_master_block()) |
| | with gradio.Row(equal_height=True): |
| | __fields.update(create_inputs_block()) |
| | with gradio.Row(equal_height=True): |
| | __fields.update(create_outputs_block()) |
| | with gradio.Row(equal_height=True): |
| | __fields.update(create_actions_block()) |
| | with gradio.Tab('Settings') as __settings_tab: |
| | __fields.update({'settings_tab': __settings_tab}) |
| | with gradio.Row(equal_height=True): |
| | __fields.update(create_vocabulary_block()) |
| | with gradio.Row(equal_height=True): |
| | __fields.update(create_sampling_block()) |
| | return __fields |
| |
|
| | |
| |
|
| | def generate_password( |
| | master_key: str, |
| | login_target: str, |
| | login_id: str, |
| | password_length: int, |
| | password_nonce: int, |
| | password_level: int, |
| | password_alphabet: list, |
| | ) -> str: |
| | return gpm.pipeline.process( |
| | master_key=master_key, |
| | login_target=login_target, |
| | login_id=login_id, |
| | password_length=password_length, |
| | password_nonce=password_nonce, |
| | include_lowers=(LOWERS in password_alphabet), |
| | include_uppers=(UPPERS in password_alphabet), |
| | include_digits=(DIGITS in password_alphabet), |
| | include_symbols=(SYMBOLS in password_alphabet), |
| | include_spaces=(SPACES in password_alphabet), |
| | include_words=(password_level == WORDS), |
| | input_vocabulary=[chr(__i) for __i in range(128)], |
| | model_context_dim=8, |
| | model_embedding_dim=128) |
| |
|
| | |
| |
|
| | def create_app(title: str=TITLE, intro: str=INTRO) -> gradio.Blocks: |
| | __fields = {} |
| | with gradio.Blocks(title=title) as __app: |
| | |
| | |
| | __fields.update(create_layout(intro=intro)) |
| | |
| | __fields.update(create_state()) |
| | |
| | __fields['process_block'].click( |
| | fn=generate_password, |
| | inputs=[__fields[__k] for __k in ['key_block', 'target_block', 'identifier_block', 'length_block', 'nonce_block', 'level_block', 'vocabulary_block']], |
| | outputs=__fields['password_block'], |
| | queue=False, |
| | show_progress='full') |
| | |
| | return __app |
| |
|
| | |
| |
|
| | if __name__ == '__main__': |
| | __app = create_app() |
| | __app.launch(theme=gradio.themes.Soft(), css=STYLE, share=True, debug=False) |
| |
|