def editPassword(self, item): row = self.passwordTable.row(item) group = self.pwMap.groups[self.selectedGroup] try: decrypted = self.cachedOrDecrypt(row) except CallException: return dialog = AddPasswordDialog() entry = group.entry(row) dialog.keyEdit.setText(s2q(entry[0])) dialog.pwEdit1.setText(s2q(decrypted)) dialog.pwEdit2.setText(s2q(decrypted)) if not dialog.exec_(): return item = QtGui.QTableWidgetItem(dialog.key()) pwItem = QtGui.QTableWidgetItem("*****") self.passwordTable.setItem(row, self.KEY_IDX, item) self.passwordTable.setItem(row, self.PASSWORD_IDX, pwItem) plainPw = q2s(dialog.pw1()) encPw = self.pwMap.encryptPassword(plainPw, self.selectedGroup) bkupPw = self.pwMap.backupKey.encryptPassword(plainPw) group.updateEntry(row, q2s(dialog.key()), encPw, bkupPw) self.cachePassword(row, plainPw) self.setModified(True)
def createPassword(self): """Slot to create key-value password entry. """ if self.selectedGroup is None: return group = self.pwMap.groups[self.selectedGroup] dialog = AddPasswordDialog() if not dialog.exec_(): return rowCount = self.passwordTable.rowCount() self.passwordTable.setRowCount(rowCount+1) item = QtGui.QTableWidgetItem(dialog.key()) pwItem = QtGui.QTableWidgetItem("*****") self.passwordTable.setItem(rowCount, self.KEY_IDX, item) self.passwordTable.setItem(rowCount, self.PASSWORD_IDX, pwItem) plainPw = q2s(dialog.pw1()) encPw = self.pwMap.encryptPassword(plainPw, self.selectedGroup) bkupPw = self.pwMap.backupKey.encryptPassword(plainPw) group.addEntry(q2s(dialog.key()), encPw, bkupPw) self.cachePassword(rowCount, plainPw) self.passwordTable.resizeRowsToContents() self.setModified(True)
def initializeStorage(trezor, pwMap, settings): """ Initialize new encrypted password file, ask for master passphrase. Initialize RSA keypair for backup, encrypt private RSA key using backup passphrase and Trezor's cipher-key-value system. Makes sure a session is created on Trezor so that the passphrase will be cached until disconnect. @param trezor: Trezor client @param pwMap: PasswordMap where to put encrypted backupKeys @param settings: Settings object to store password database location """ dialog = InitializeDialog() if not dialog.exec_(): sys.exit(4) masterPassphrase = q2s(dialog.pw1()) trezor.prefillPassphrase(masterPassphrase) backup = Backup(trezor) backup.generate() pwMap.backupKey = backup settings.dbFilename = q2s(dialog.pwFile()) settings.store()
def callback_PinMatrixRequest(self, msg): dialog = EnterPinDialog() if not dialog.exec_(): sys.exit(7) pin = q2s(dialog.pin()) return proto.PinMatrixAck(pin=pin)
def saveBackup(self): """ Uses backup key encrypted by Trezor to decrypt all passwords at once and export them. Export format is CSV: group, key, password """ dialog = QtGui.QFileDialog(self, "Select backup export file", "", "CVS files (*.csv)") dialog.setAcceptMode(QtGui.QFileDialog.AcceptSave) res = dialog.exec_() if not res: return fname = q2s(dialog.selectedFiles()[0]) backupKey = self.pwMap.backupKey try: privateKey = backupKey.unwrapPrivateKey() except CallException: return with file(fname, "w") as f: csv.register_dialect("escaped", doublequote=False, escapechar='\\') writer = csv.writer(f, dialect="escaped") sortedGroupNames = sorted(self.pwMap.groups.keys()) for groupName in sortedGroupNames: group = self.pwMap.groups[groupName] for entry in group.entries: key, _, bkupPw = entry password = backupKey.decryptPassword(bkupPw, privateKey) csvEntry = (groupName, key, password) writer.writerow(csvEntry)
def createGroup(self): """Slot to create a password group. """ dialog = AddGroupDialog(self.pwMap.groups) if not dialog.exec_(): return groupName = dialog.newGroupName() newItem = QtGui.QStandardItem(groupName) self.groupsModel.appendRow(newItem) self.pwMap.addGroup(q2s(groupName)) #make new item selected to save a few clicks itemIdx = self.groupsModel.indexFromItem(newItem) proxyIdx = self.groupsFilter.mapFromSource(itemIdx) self.groupsTree.selectionModel().select(proxyIdx, QtGui.QItemSelectionModel.ClearAndSelect | QtGui.QItemSelectionModel.Rows) self.groupsTree.sortByColumn(0, QtCore.Qt.AscendingOrder) #Make item's passwords loaded so new key-value entries can be created #right away - better from UX perspective. self.loadPasswords(newItem) self.setModified(True)
def cachedPassword(self, row): """ Retrieve cached password for given row of currently selected group. Returns password as string or None if no password cached. """ item = self.passwordTable.item(row, MainWindow.CACHE_IDX) cached = item.data(QtCore.Qt.UserRole) if cached.isValid(): return q2s(cached.toString()) return None
def deleteGroup(self, item): msgBox = QtGui.QMessageBox(text="Are you sure about delete?") msgBox.setStandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) res = msgBox.exec_() if res != QtGui.QMessageBox.Yes: return name = q2s(item.text()) self.selectedGroup = None del self.pwMap.groups[name] itemIdx = self.groupsModel.indexFromItem(item) self.groupsModel.takeRow(itemIdx.row()) self.passwordTable.setRowCount(0) self.groupsTree.clearSelection() self.setModified(True)
def createPassword(self): """ Slot to create key-value password entry. """ if self.selectedGroup is None: return group = self.pwMap.groups[self.selectedGroup] dialog = AddPasswordDialog() if not dialog.exec_(): return rowCount = self.passwordTable.rowCount() self.passwordTable.setRowCount(rowCount + 1) item = QtGui.QTableWidgetItem(dialog.key()) pwItem = QtGui.QTableWidgetItem("*****") self.passwordTable.setItem(rowCount, self.KEY_IDX, item) self.passwordTable.setItem(rowCount, self.PASSWORD_IDX, pwItem) plainPw = q2s(dialog.pw1()) encPw = self.pwMap.encryptPassword(plainPw, self.selectedGroup) bkupPw = self.pwMap.backupKey.encryptPassword(plainPw) group.addEntry(q2s(dialog.key()), encPw, bkupPw) self.cachePassword(rowCount, plainPw) self.passwordTable.resizeRowsToContents() self.setModified(True)
def loadPasswords(self, item): """ Slot that should load items for group that has been clicked on. """ #self.passwordTable.clear() name = q2s(item.text()) self.selectedGroup = name group = self.pwMap.groups[name] self.passwordTable.setRowCount(len(group.entries)) self.passwordTable.setColumnCount(2) i = 0 for key, encValue, bkupValue in group.entries: item = QtGui.QTableWidgetItem(s2q(key)) pwItem = QtGui.QTableWidgetItem("*****") self.passwordTable.setItem(i, self.KEY_IDX, item) self.passwordTable.setItem(i, self.PASSWORD_IDX, pwItem) i = i+1 self.passwordTable.resizeRowsToContents()
def loadPasswords(self, item): """ Slot that should load items for group that has been clicked on. """ #self.passwordTable.clear() name = q2s(item.text()) self.selectedGroup = name group = self.pwMap.groups[name] self.passwordTable.setRowCount(len(group.entries)) self.passwordTable.setColumnCount(2) i = 0 for key, encValue, bkupValue in group.entries: item = QtGui.QTableWidgetItem(s2q(key)) pwItem = QtGui.QTableWidgetItem("*****") self.passwordTable.setItem(i, self.KEY_IDX, item) self.passwordTable.setItem(i, self.PASSWORD_IDX, pwItem) i = i + 1 self.passwordTable.resizeRowsToContents()
def createGroup(self): """ Slot to create a password group. """ dialog = AddGroupDialog(self.pwMap.groups) if not dialog.exec_(): return groupName = dialog.newGroupName() newItem = QtGui.QStandardItem(groupName) self.groupsModel.appendRow(newItem) self.pwMap.addGroup(q2s(groupName)) # make new item selected to save a few clicks itemIdx = self.groupsModel.indexFromItem(newItem) proxyIdx = self.groupsFilter.mapFromSource(itemIdx) self.groupsTree.selectionModel().select( proxyIdx, QtGui.QItemSelectionModel.ClearAndSelect | QtGui.QItemSelectionModel.Rows) self.groupsTree.sortByColumn(0, QtCore.Qt.AscendingOrder) # Make item's passwords loaded so new key-value entries can be created # right away - better from UX perspective. self.loadPasswords(newItem) self.setModified(True)
def __init__(self): self.dbFilename = None self.settings = QtCore.QSettings("ConstructibleUniverse", "TrezorPass") fname = self.settings.value("database/filename") if fname.isValid(): self.dbFilename = q2s(fname.toString())