penguin/utils

my env utils

commit 85c9c3bea37db984b6cccb75331ecba8ebfc6541

author斟酌 鵬兄 <tgckpg@gmail.com>
date2022-08-13T15:40:12Z
subjectAdded 16_keystore
commit 85c9c3bea37db984b6cccb75331ecba8ebfc6541
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2022-08-13T15:40:12Z

    Added 16_keystore
---
 bash/bashrc/sources/16_keystore | 230 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 230 insertions(+)

diff --git a/bash/bashrc/sources/16_keystore b/bash/bashrc/sources/16_keystore
new file mode 100644
index 0000000..f455aaf
--- /dev/null
+++ b/bash/bashrc/sources/16_keystore
@@ -0,0 +1,230 @@
+#!/bin/bash
+
+_SQLITE=$( which sqlite3 2>&1 )
+if [ $? -ne 0 ]; then
+    echo "sqlite3 is missing" >&2
+    return 1
+fi
+
+echo "test" | openssl enc -e -aes-256-cbc -pbkdf2 -k test 2>/dev/null > /dev/null
+if [ $? -ne 0 ]; then
+    echo "openssl does not exists nor support pbkdf2" >&2
+    return 1
+fi
+
+if [ -z `which xxd` ]; then
+	echo "xxd is required" >&2
+	return 1
+fi
+
+_AUTH_DB=$RBASH_HOME/keystore.db
+_AUTH_SECRET=
+_KSTORE_DEF_PROP=${_KSTORE_DEF_PROP:-val}
+
+if [ -f "$RBASH_HOME/keystore.secret" ]; then
+	_AUTH_SECRET=$( cat "$RBASH_HOME/keystore.secret" )
+fi
+
+function kstore {
+	case $1 in
+		add) shift; kstore-add "$@" ;;
+		del) shift; kstore-del "$@" ;;
+		get) shift; kstore-get "$@" ;;
+		list) shift; kstore-list "$@" ;;
+		query) shift; kstore-query "$@" ;;
+		update) shift; kstore-update "$@" ;;
+		search) shift; kstore-search $@ ;;
+		secret) shift; kstore-secret $@ ;;
+		*)
+			__func_head "add key value [prop, default: $_KSTORE_DEF_PROP]"
+			__func_help "update key value [prop, default: $_KSTORE_DEF_PROP]"
+			__func_help "get key [prop, default: $_KSTORE_DEF_PROP]"
+			__func_help "list"
+			__func_help "del key"
+			__func_help "search key"
+			__func_help "query SQL"
+			return 1
+			;;
+	esac
+	return $?
+}
+
+function kstore-secret {
+	case "$1" in
+		clear) shift; kstore-secret-clear "$@" ;;
+		config) shift; kstore-secret-config "$@" ;;
+		*)
+			__func_head "clear"
+			__func_help "config"
+			;;
+	esac
+}
+
+function kstore-init {
+	cat <<___SQL___ | $_SQLITE "$_AUTH_DB"
+CREATE TABLE IF NOT EXISTS store ( 
+	key TEXT UNIQUE NOT NULL
+	, prop TEXT NOT NULL
+	, data BLOB
+	, PRIMARY KEY( key ASC, prop ASC )
+);
+___SQL___
+	kstore secret config
+}
+
+function kstore-quote {
+	echo -n "$1" | sed -e "s/'/''/g"
+}
+
+function kstore-enc {
+	if [ -z "$_AUTH_SECRET" ]; then
+		echo "Secret key is not set yet" >&2
+		return 1
+	fi
+
+	openssl enc -e -aes-256-cbc -pbkdf2 -k "$_AUTH_SECRET" | xxd -p | tr -d "\n"
+}
+
+function kstore-dec {
+	if [ -z "$_AUTH_SECRET" ]; then
+		echo "Secret key is not set yet" >&2
+		return 1
+	fi
+
+	openssl enc -d -aes-256-cbc -pbkdf2 -k "$_AUTH_SECRET"
+}
+
+function kstore-secret-macos {
+	local _A
+	case $1 in
+		get)
+			_A=`security find-generic-password -a default -gs rbash-kstore 2>&1 | grep ^password | cut -c 11-`
+			if [ $? -ne 0 ]; then
+				return 1
+			fi
+			_AUTH_SECRET="${_A:1:-1}"
+			;;
+		set)
+			security add-generic-password -a default -s rbash-kstore -w "$_AUTH_SECRET"
+			;;
+		*)
+			echo "Unknown action: $1" >&2
+			return 1
+			;;
+	esac
+}
+
+function kstore-secret-windows {
+	# Not impelemented yet
+	if [ "$1" == "get" ]; then
+		return 1
+	fi
+	return 1
+}
+
+function kstore-secret-config {
+	local _CONFIRM
+	if [ -z "$_AUTH_SECRET" ]; then
+
+		kstore-secret-windows get || kstore-secret-macos get
+		if [ -n "$_AUTH_SECRET" ]; then
+			return 0
+		fi
+
+		read -sp "Enter passphrase: " _AUTH_SECRET
+		echo
+		if [ -z "$_AUTH_SECRET" ]; then
+			echo "Passphrase cannot be empty" >&2
+			return 1
+		fi
+
+		read -p "Save this password to OS's keystore? (y/n): " _CONFIRM
+		if [ "$_CONFIRM" != "y" ]; then
+			return 0
+		fi
+
+		case $OSTYPE in
+			darwin*) kstore-secret-macos "set" ;;
+		esac
+	fi
+}
+
+function kstore-secret-clear {
+	_AUTH_SECRET=
+	case $OSTYPE in
+		darwin*)
+			security delete-generic-password -a default -s rbash-kstore 2>&1 > /dev/null
+		;;
+	esac
+}
+
+function kstore-update {
+	kstore-init || return 1
+	local _key _val _prop
+	_key=`kstore-quote "$1"`
+	_val=`echo -n "$2" | kstore-enc`
+	_val=`kstore-quote "$_val"`
+	_prop=`kstore-quote "${3:-$_KSTORE_DEF_PROP}"`
+	_cond="key = '$_key' AND prop = '$_prop'"
+	$_SQLITE "$_AUTH_DB" "UPDATE store SET data = '$_val' WHERE $_cond;"
+}
+
+function kstore-add {
+	kstore-init || return 1
+	local _key _val _prop
+	_key=`kstore-quote "$1"`
+	_val=`echo -n "$2" | kstore-enc`
+	_val=`kstore-quote "$_val"`
+	_prop=`kstore-quote "${3:-$_KSTORE_DEF_PROP}"`
+    sqlite3 "$_AUTH_DB" \
+		"INSERT INTO store ( key, prop, data )
+			VALUES( '$_key', '$_prop', X'$_val' );"
+}
+
+function kstore-get {
+	kstore-init || return 1
+	local _key _prop _cond
+	_key=`kstore-quote "$1"`
+	_prop=`kstore-quote "${2:-$_KSTORE_DEF_PROP}"`
+	_cond="key = '$_key' AND prop = '$_prop'"
+
+	echo -n "`$_SQLITE -list "$_AUTH_DB" "SELECT ( data ) FROM store WHERE $_cond;"`" | kstore-dec
+}
+
+function kstore-del {
+	kstore-init || return 1
+
+	local _CONFIRM _key _prop _cond
+	_key=`kstore-quote "$1"`
+	_prop=`kstore-quote "${2:-$_KSTORE_DEF_PROP}"`
+	_cond="key = '$_key' AND prop = '$_prop'"
+
+    sqlite3 "$_AUTH_DB" "SELECT 1111 FROM store WHERE $_cond;" | grep -q 1111
+	if [ $? -eq 0 ]; then
+		sqlite3 "$_AUTH_DB" "SELECT * FROM store WHERE $_cond;"
+		echo
+		read -p "Delete this entry (yes/no)? " _CONFIRM
+		if [ "$_CONFIRM" == "yes" ]; then
+			sqlite3 "$_AUTH_DB" "DELETE FROM store WHERE $_cond;"
+			if [ $? -eq 0 ]; then
+				echo "deleted"
+			fi
+		else
+			echo "action canceled"
+		fi
+	else
+		echo "$1 not found"
+	fi
+}
+
+function kstore-search {
+	echo "Not implemented yet"
+}
+
+function kstore-list {
+	$_SQLITE -header -column "$_AUTH_DB" "SELECT key, prop, length( data ) FROM store;"
+}
+
+function kstore-query {
+	sqlite3 "$_AUTH_DB" "$@"
+}