Browse Source

Added pass support for mouseless password management

tags/v0.1.1
Micah Halter 1 year ago
parent
commit
c83773f5a8
3 changed files with 142 additions and 4 deletions
  1. 1
    0
      README.md
  2. 3
    4
      i3/.config/i3/config
  3. 138
    0
      pass/.enpass2pass.py

+ 1
- 0
README.md View File

@@ -48,6 +48,7 @@ My dotfiles for my Linux rice, managed using stow.
- neofetch
- offlineimap
- oomox
- pass
- pdfpc
- py-wal
- R

+ 3
- 4
i3/.config/i3/config View File

@@ -362,8 +362,8 @@ bindsym $mod+Shift+Control+bracketleft exec --no-startup-id light -U 10
#bindsym $mod+Shift+bracketright
bindsym $mod+Shift+Control+bracketright exec --no-startup-id light -A 10

#bindsym $mod+backslash
#bindsym $mod+Shift+backslash
bindsym $mod+backslash exec --no-startup-id passmenu -i -nb '$dmenu-bg-color' -nf '$dmenu-text-color' -sb '$dmenu-text-color' -sf '$dmenu-bg-color' -fn 'System San Francisco Display-13'
bindsym $mod+Shift+backslash exec --no-startup-id networkmanager_dmenu -i -nb '$dmenu-bg-color' -nf '$dmenu-text-color' -sb '$dmenu-text-color' -sf '$dmenu-bg-color' -fn 'System San Francisco Display-13'
#bindsym $mod+Shift+Control+backslash

#bindsym $mod+semicolon
@@ -477,5 +477,4 @@ bindsym XF86MonBrightnessDown exec --no-startup-id light -U 10

bindsym XF86ScreenSaver exec --no-startup-id ~/.config/i3/scripts/lock/lock.sh

bindsym XF86Launch1 exec --no-startup-id networkmanager_dmenu -i -nb '$dmenu-bg-color' -nf '$dmenu-text-color' -sb '$dmenu-text-color' -sf '$dmenu-bg-color' -fn 'System San Francisco Display-13'
bindsym $mod+XF86Launch1 exec --no-startup-id ~/.config/polybar/launch.sh
bindsym XF86Launch1 exec --no-startup-id ~/.config/polybar/launch.sh

+ 138
- 0
pass/.enpass2pass.py View File

@@ -0,0 +1,138 @@
#!/usr/bin/env python
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This script based on the Enpassant
# script written by Steffen Zerbe.
#
# $Id: enpass2pass.py,v 1.1 2016/09/11 23:02:12 dhn Exp $

from subprocess import Popen, PIPE, check_output
from pysqlcipher import dbapi2 as sqlite
from Crypto.Cipher import AES
import hashlib
import binascii
import json


class enpass2pass:

def __init__(self, filename, gpg):
self.initDb(filename, gpg)
self.crypto = self.getCryptoParams()

def getpasswd(self, gpg):
passphrase = "/home/micah/.gnupg/passphrase"
return check_output(["gpg2", "--pinentry-mode", "loopback", "--passphrase-file", passphrase, "--quiet", "--batch", "-d", gpg]).strip()

# Sets up SQLite DB
def initDb(self, filename, gpg):
self.conn = sqlite.connect(filename)
self.c = self.conn.cursor()
self.c.row_factory = sqlite.Row
self.c.execute("PRAGMA key='" + self.getpasswd(gpg) + "'")
self.c.execute("PRAGMA kdf_iter = 24000")

def generateKey(self, key, salt):
# 2 Iterations of PBKDF2 SHA256
return hashlib.pbkdf2_hmac('sha256', key, salt, 2)

def getCryptoParams(self):
ret = {}
# Identity contains stuff to decrypt data columns
self.c.execute("SELECT * FROM Identity")
identity = self.c.fetchone()

# Info contains more parameters
info = identity["Info"]

# Get params from stream
i = 16 # First 16 bytes are for "mHashData", which is unused
ret["iv"] = ""
salt = ""
while i <= 31:
ret["iv"] += info[i]
i += 1
while i <= 47:
salt += info[i]
i += 1

ret["key"] = self.generateKey(identity["Hash"], salt)

return ret

def unpad(self, s):
return s[0:-ord(s[-1])]

def decrypt(self, enc, key, iv):
# PKCS5
cipher = AES.new(key, AES.MODE_CBC, iv)
return self.unpad(cipher.decrypt(enc))

def passImportEntry(self, path, data):
proc = Popen(['pass', 'insert', '--multiline', path],
stdin=PIPE, stdout=PIPE)
proc.communicate(data.encode('utf8'))
proc.wait()

def getCards(self):
self.c.execute("SELECT * FROM Cards")
cards = self.c.fetchall()
ret = []
for card in cards:
# Decrypted string
dec = self.decrypt(card["Data"], self.crypto[
"key"], self.crypto["iv"])
# Parsing as object
item = json.loads(dec)
ret.append(item)
return ret

def dumpCards(self):
cards = self.getCards()
for card in cards:
if card["fields"] != []:
templatetype = card['templatetype']
type_ = card["fields"][0]['type']

if templatetype == "login.default":
pwd = card['fields'][2]['value']
name = card['name']

if type_ == "username":
value = card['fields'][0]['value']
if value == "":
email = card['fields'][1]['value']
path = name + "/" + email
else:
username = card['fields'][0]['value']
path = name + "/" + username

path = "Login/" + path
data = pwd + "\n"
self.passImportEntry(path, data)
elif templatetype == "computer.wifi":
name = card['fields'][0]['value']
pwd = card['fields'][1]['value']

path = "Wifi/" + name
data = pwd + "\n"
self.passImportEntry(path, data)

if __name__ == "__main__":
import sys
if len(sys.argv) < 3:
print("\nusage: " + str(sys.argv[0]) + " walletx.db gpgfile\n")
sys.exit()
else:
en = enpass2pass(sys.argv[1], sys.argv[2])
en.dumpCards()

Loading…
Cancel
Save