commit: 6ecd112962c6a86e5c92ee990b8086071f5ecb61
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Sun, 24 May 2020 15:43:24 +0200
Initial Commit
Diffstat:
A | COPYING | 13 | +++++++++++++ |
A | README | 19 | +++++++++++++++++++ |
A | pass2secret | 43 | +++++++++++++++++++++++++++++++++++++++++++ |
A | secret | 106 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
4 files changed, 181 insertions(+), 0 deletions(-)
diff --git a/COPYING b/COPYING
@@ -0,0 +1,13 @@
+Copyright (c) 2020, Haelwenn (lanodan) Monnier <contact+secret@hacktivis.me>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/README b/README
@@ -0,0 +1,19 @@
+## Secret
+
+- No audit done
+- No warranty is given
+- Tagged release when it's frozen enough
+- ISC Licensed
+
+This is a replacment to pass(1), the Unix password manager. It is backed by
+reop(1) instead of GnuPG(1).
+
+## Dependencies
+- POSIX Shell
+- reop (and so libsodium) <https://flak.tedunangst.com/post/reop>
+- dmenu (optionnal) <https://tools.suckless.org/dmenu/>
+- oathtool (optionnal) <http://www.nongnu.org/oath-toolkit/>
+
+## Tested platforms
+- System: GNU/Linux (gentoo)
+- Shell: mksh
diff --git a/pass2secret b/pass2secret
@@ -0,0 +1,43 @@
+#!/bin/sh
+# pass2secret: Converts pass(1) storage to secret(1) storage
+# Copyright 2020 Haelwenn (lanodan) Monnier <contact+secret@hacktivis.me>
+# SPDX-License-Identifier: ISC
+OLDPWD="$PWD"
+workdir="$HOME/.secret-storage/"
+PASSWORD_STORE_DIR="${PASSWORD_STORE_DIR:-$HOME/.password-store}"
+export SECRET_FILE="/dev/shm/pass2secret"
+
+set -e
+
+touch "$SECRET_FILE"
+chmod 700 "$SECRET_FILE"
+
+echo -n "Passphrase: "
+read passphrase
+echo
+
+# Create needed directories
+cd "$workdir"
+(cd "$PASSWORD_STORE_DIR" && find -type d | grep -v ./.git) | xargs mkdir -p
+
+# Convert each entry
+(
+ cd "$PASSWORD_STORE_DIR"
+ find -type f -name '*.gpg' | sed -e 's;\.gpg$;;' -e 's;^./;;'
+) | while read entry
+do
+ ( pass "$entry" && echo ) > "$SECRET_FILE"
+ if [[ ! -f "$workdir/$entry" ]]; then secret write "$entry" <<<"$passphrase"; fi
+ if [[ ! -f "$workdir/$entry.oath" ]] && grep "^otpauth" "$SECRET_FILE"; then
+ grep "^otpauth" "$SECRET_FILE" | sed \
+ -e 's;^otpauth://totp/totp-secret?secret=q;;' \
+ -e 's;^;--base32 ;' \
+ | secret write "${entry}.oath" <<<"$passphrase"
+ fi
+ else
+ echo "following entry exists, ignoring: $workdir/$entry"
+ fi
+done
+
+shred -u "$secret_file"
+cd "$OLDPWD"
diff --git a/secret b/secret
@@ -0,0 +1,106 @@
+#!/bin/sh
+# secret: Replacement to pass(1) based on reop(1)
+# Copyright 2020 Haelwenn (lanodan) Monnier <contact+secret@hacktivis.me>
+# SPDX-License-Identifier: ISC
+workdir="$HOME/.secret-storage"
+
+set -e
+
+secret_list() {
+ ( cd "$workdir" && find . -type f -name '*.reop' "$@" | sed -e 's;^./;;' -e 's;.reop$;;') | sort | column
+}
+
+secret_list_oath() {
+ secret_list -name '*.oath.reop' "$@"
+}
+
+tree() {
+ secret_list "$@" | tree --fromfile
+}
+
+secret_read() {
+ entry="$*"
+ target="${SECRET_FILE:--}"
+
+ reop -D -m "$target" -x "${workdir}/${entry}.reop"
+}
+
+secret_write() {
+ entry="$*"
+ target="${SECRET_FILE:--}"
+
+ reop -E -m "$target" -x "${workdir}/${entry}.reop"
+
+ if test -f "${workdir}/.git/HEAD"
+ then
+ git add "${workdir}/${entry}.reop"
+ git commit -m "${entry}: encrypt auto-update"
+ if [ "$(git remote show -n)" != "" ]; then git push; fi
+ else
+ echo "No git repository in ‘$workdir’, consider creating one"
+ fi
+}
+
+secret_read_oath() {
+ secret_read "$@" | read -r secret
+ oathtool --totp --base32 "$secret"
+}
+
+secret_dmenu() {
+ echo | dmenu -nb '#000' -nf '#000' -p "Passphrase: "
+}
+
+secret_dmenu_oath() {
+ entry="$(secret_find -name '*.oath.reop' | dmenu -i)"
+ oathtool $(secret_menu | secret_read "$entry") | xclip -i -selection clipboard
+}
+
+secret_dmenu_read() {
+ entry="$(secret_find | dmenu -i)"
+ secret_menu | secret_read "$entry" | xclip -i -selection clipboard
+}
+
+secret_usage() {
+ cat <<-EOF
+secret [command] [command-arguments...]
+ Replacement to pass(1) based on reop(1)
+
+secret ls [arguments...]
+ List the entries. Passes arguments to find(1), ls(1)-style output.
+secret tree [arguments...]
+ Same as ‘secret ls’ but outputs via tree(1).
+secret read <entry>
+ Read a secret entry.
+secret write <entry>
+ Write a secret entry.
+secret dmenu
+ dmenu on entries, dmenu for a passphrase, read secret, pipe to xclip(1).
+
+secret ls-oath [arguments...]
+ Same as ‘secret ls’ but limited to oath entries(‘*.oath.reop’).
+secret read-oath <entry>
+ Same as ‘secret read’ but entry content passed to oathtool(1) as arguments.
+secret dmenu-oath
+ Same as ‘secret dmenu’ but ‘secret read-oath’ instead of ‘secret read’.
+EOF
+
+ exit 1
+}
+
+command="$1"
+[ "$1" = "" ] && secret_usage "$@"
+shift || secret_usage "$@"
+
+case "$command" in
+ ls) secret_list "$@" ;;
+ tree) secret_tree "$@" ;;
+ read) secret_read "$@" ;;
+ write) secret_write "$@" ;;
+ dmenu) secret_dmenu_read "$@" ;;
+
+ ls-oath) secret_list_oath "$@" ;;
+ read-oath) secret_read_oath "$@" ;;
+ dmenu-oath) secret_dmenu_oath "$@" ;;
+
+ *) secret_usage "$@" ;;
+esac