diff --git a/README.md b/README.md index 65b38d4..a625d91 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,40 @@ — Lars Wirzenius (Linux kernel developer) +## Warm-Up +- how to start a repo from scratch? + - `git init` local method + - on an online forge (GitHub, GitLab, …): `git clone` +- how to revert mistakes? + - before commit: + - `git restore ` [discard changes in the working directory] __changes files__ + - `git restore --staged ` [unstage changes ➔ opposite of `git add `, does not modify the working directory] + - after commit: + - `git revert ` [creates a new commit, modifies the working directory] + - `git reset ` [only reset the HEAD pointer, does not modify the working directory] __rewrites history__ ➔ can not be used if you have already pushed to some remote + - `git reset --hard ` [reset HEAD and modify working directory] __rewrites history__ and __changes files__ ➔ can not be used if you have already pushed to some remote +- how to *move* the whole working directory to a specific point in history? + - `git checkout ` ➔ `DETACHED HEAD` problem, __changes__ __files__ + - interaction with branches: `git branch ` + `git switch ` +- how to copy a file from a different branch: + - `git checkout ` ➔ the file is staged automatically + - `git restore --source= `, `git push `, `git fetch `, `git merge ` +- git-forge: forks, branches and PRs: notice the difference between `fork` and `clone`!!! +- strategies for keeping your fork up-to-date: your `main`, origin's and upstream's `main`, short-lived and long-lived topic branches +- a more thorough and detailed explanation can be found on the [SciPy Contributor's Guide](https://docs.scipy.org/doc/scipy/dev/gitwash/gitwash.html). This guide can be adapted to your own needs, see [gitwash](https://github.com/matthew-brett/gitwash). +- GitHub and GitLab are just options (git≠GitHub): there are many git-forges out there, both installable on premises (e.g. [forgejo](https://forgejo.org/)) ) or as an online service for free and open source software (e.g. [codeberg](https://codeberg.org/) + + diff --git a/auth.py b/auth.py new file mode 100644 index 0000000..5408393 --- /dev/null +++ b/auth.py @@ -0,0 +1,88 @@ +import getpass +import json +import pathlib +import random +import string +import sys + +# name of the file where we store the pw database +PWDB_FLNAME = pathlib.Path('pwdb.json') + +# list of valid characters for salt (only ASCII letters + digits + punctuation) +CHARS = string.ascii_letters + string.digits + string.punctuation + +# length of salt +SALT_LENGTH = 5 + +def get_credentials(): + # get input from terminal + username = input('Enter your username: ') + # get password using the appropriate module, so that typed characters are not + # echoed to the terminal + password = getpass.getpass('Enter your password: ') + return (username, password) + +def authenticate(username, pass_text, pwdb): + # get the salt from the database + salt = pwdb[username][1] + # calculate hash and compare with stored hash + return pwhash(pass_text, salt) == pwdb[username][0] + +def add_user(username, pwdb): + # do not try to add a username twice + if username in pwdb: + raise Exception(f'Username already exists [{username}]!') + else: + password = getpass.getpass(f'Enter password for {username}: ') + salt = get_salt() + pwdb[username] = (pwhash(password,salt), salt) + return pwdb + +def read_pwdb(pwdb_path): + if not pwdb_path.exists(): + pwdb = {} + else: + with open(pwdb_path, 'rt') as pwdb_file: + pwdb = json.load(pwdb_file) + return pwdb + +def write_pwdb(pwdb, pwdb_path): + with open(pwdb_path, 'wt') as pwdb_file: + json.dump(pwdb, pwdb_file) + +def pwhash(pass_text, salt): + # simple additive hash -> very insecure! + hash_ = 0 + full_pass_text = pass_text + salt + for idx, char in enumerate(full_pass_text): + # use idx as a multiplier, so that shuffling the characters returns a + # different hash + hash_ += (idx+1)*ord(char) + return hash_ + +def get_salt(): + salt_chars = random.choices(CHARS, k=SALT_LENGTH) + return ''.join(salt_chars) + +def main(pwdb_path): + # load the password database from file + pwdb = read_pwdb(pwdb_path) + + # if we are passed an argument, we want to add a new user + if len(sys.argv) > 1: + pwdb = add_user(sys.argv[1], pwdb) + write_pwdb(pwdb, pwdb_path) + return + + # ask for credentials + username, password = get_credentials() + if username not in pwdb or not authenticate(username, password, pwdb): + print('Wrong username or password!') + else: + print('Successfully authenticated!') + + return + +if __name__ == '__main__': + main(PWDB_FLNAME) + diff --git a/minimal_auth.py b/minimal_auth.py new file mode 100644 index 0000000..67064e5 --- /dev/null +++ b/minimal_auth.py @@ -0,0 +1,42 @@ +import json +import sys + +def get_credentials(): + username = input('Enter your username: ') + password = input('Enter your password: ') + return (username, password) + +def authenticate(username, password, pwdb): + return password == pwdb[username] + +def add_user(username, pwdb): + pwdb[username] = input(f'Enter password for {username}: ') + return pwdb + +def read_pwdb(pwdb_path): + try: + pwdb_file = open(pwdb_path, 'rt') + pwdb = json.load(pwdb_file) + except Exception: + pwdb = {} + return pwdb + +def write_pwdb(pwdb, pwdb_path): + pwdb_file = open(pwdb_path, 'wt') + json.dump(pwdb, pwdb_file) + +pwdb_path = 'pwdb.json' +pwdb = read_pwdb(pwdb_path) + +if len(sys.argv) > 1: + pwdb = add_user(sys.argv[1], pwdb) + write_pwdb(pwdb, pwdb_path) +else: + username, password = get_credentials() + if username not in pwdb: + print('Wrong username!') + else: + if authenticate(username, password, pwdb): + print('Successfully authenticated!') + else: + print('Wrong password!')