Esempio n. 1
0
def input23(prompt=u''):  # Py2-vs-Py3:
    """
	Utility function to bridge Py2 and Py3 incompatibilities.
	Maps Py2 raw_input() to input() for Py2.
	Py2: raw_input()
	Py3: input()
	"""
    if sys.version_info[0] < 3:  # Py2-vs-Py3:
        return normalize_nfc(raw_input(prompt))
    else:
        return normalize_nfc(input(prompt))
Esempio n. 2
0
	def editPassword(self, item):
		row = self.passwordTable.row(item)
		group = self.pwMap.groups[self.selectedGroup]
		try:
			decrypted = self.cachedOrDecryptPassword(row)
			decryptedComments = self.cachedOrDecryptComments(row)
		except CallException:
			return

		dialog = AddPasswordDialog(self.pwMap.trezor, self.settings)
		entry = group.entry(row)
		dialog.keyEdit.setText(encoding.normalize_nfc(entry[0]))
		dialog.pwEdit1.setText(encoding.normalize_nfc(decrypted))
		dialog.pwEdit2.setText(encoding.normalize_nfc(decrypted))
		doc = QTextDocument(encoding.normalize_nfc(decryptedComments), parent=self)
		dialog.commentsEdit.setDocument(doc)

		if not dialog.exec_():
			return

		item = QTableWidgetItem(dialog.key())
		pwItem = QTableWidgetItem("*****")
		commentsItem = QTableWidgetItem("*****")
		self.passwordTable.setItem(row, self.KEY_IDX, item)
		self.passwordTable.setItem(row, self.PASSWORD_IDX, pwItem)
		self.passwordTable.setItem(row, self.COMMENTS_IDX, commentsItem)

		plainPw = dialog.pw1()
		plainComments = dialog.comments()
		if len(plainPw) + len(plainComments) > basics.MAX_SIZE_OF_PASSWDANDCOMMENTS:
			self.settings.mlogger.log("Password and/or comments too long. "
				"Combined they must not be larger than %d." %
				basics.MAX_SIZE_OF_PASSWDANDCOMMENTS,
				logging.CRITICAL, "User IO")
			return

		plainPwComments = ("%4d" % len(plainPw)) + plainPw + plainComments

		encPw = self.pwMap.encryptPassword(plainPwComments, self.selectedGroup)
		bkupPw = self.pwMap.backupKey.encryptPassword(plainPwComments)
		group.updateEntry(row, dialog.key(), encPw, bkupPw)

		self.cachePasswordComments(row, plainPw, plainComments)

		self.setModified(True)
		self.settings.mlogger.log("Password and comments entry "
			"for '%s', row '%d' was edited." % (dialog.key(), row),
			logging.DEBUG, "GUI IO")
    def obfuscateFilename(self, plaintextFileName):
        """
		Plaintext filename -> pad16 -> AES encrypt on Trezor --> base64 encode
			--> homegrown padding == obfuscated filename
		input: string
		output: string
		"""
        namebytes = encoding.tobytes(plaintextFileName)
        pad16 = Padding(BLOCKSIZE).pad(namebytes)
        # self.settings.mlogger.log("Press confirm on Trezor device to encrypt file "
        # 	"name %s (if necessary).", plaintextFileName)
        # we do not use an IV here so that we can quickly deobfuscate
        # filenames without having to read the file
        encFn = self.trezor.encrypt_keyvalue(
            basics.Magic.fileNameNode,
            basics.Magic.fileNameKey,
            pad16,
            ask_on_encrypt=False,
            ask_on_decrypt=not self.settings.QArg,
            iv=self.baddressIv)
        bs64 = base64.urlsafe_b64encode(encFn)  # mod 4
        bs64Str = encoding.normalize_nfc(bs64)
        ret = PaddingHomegrown().pad(bs64Str)  # mod 16
        self.settings.mlogger.log(
            "The obfuscated filename for \"%s\" is \"%s\"." %
            (plaintextFileName, ret), logging.DEBUG, "Encryption")
        # self.settings.mlogger.log("\n\tplaintext is %s (%d), \n\tpad16 is %s (%d), "
        # 	"\n\tencFn is %s (%d), \n\tbs64 is %s (%d), \n\thgP is %s (%d)",
        # 	plaintextFileName, len(plaintextFileName), pad16, len(pad16),
        # 	binascii.hexlify(encFn), len(encFn), bs64, len(bs64), ret, len(ret))
        return ret
Esempio n. 4
0
	def loadPasswords(self, item):
		"""
		Slot that should load items for group that has been clicked on.
		"""
		self.passwordTable.clear()  # clears cahce, but also clears the header, the 3 titles
		headerKey = QTableWidgetItem(u"Key")
		headerValue = QTableWidgetItem(u"Password/Value")
		headerComments = QTableWidgetItem(u"Comments")
		self.passwordTable.setColumnCount(self.NO_OF_PASSWDTABLE_COLUMNS)
		self.passwordTable.setHorizontalHeaderItem(self.KEY_IDX, headerKey)
		self.passwordTable.setHorizontalHeaderItem(self.PASSWORD_IDX, headerValue)
		self.passwordTable.setHorizontalHeaderItem(self.COMMENTS_IDX, headerComments)

		groupName = encoding.normalize_nfc(item.text())
		self.selectedGroup = groupName
		group = self.pwMap.groups[groupName]
		self.passwordTable.setRowCount(len(group.entries))

		i = 0
		for key, encValue, bkupValue in group.entries:
			item = QTableWidgetItem(key)
			pwItem = QTableWidgetItem("*****")
			commentsItem = QTableWidgetItem("*****")
			self.passwordTable.setItem(i, self.KEY_IDX, item)
			self.passwordTable.setItem(i, self.PASSWORD_IDX, pwItem)
			self.passwordTable.setItem(i, self.COMMENTS_IDX, commentsItem)
			i = i+1

		self.passwordTable.resizeRowsToContents()
		self.passwordTable.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
		self.passwordTable.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeToContents)
		self.passwordTable.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeToContents)
		self.settings.mlogger.log("Loaded password group '%s'." % (groupName),
			logging.DEBUG, "GUI IO")
Esempio n. 5
0
    def callback_PassphraseRequest(self, msg):
        if self.passphrase is not None:
            return proto.PassphraseAck(passphrase=str(self.passphrase))

        if self.readpassphrasefromstdin:
            # read passphrase from stdin
            try:
                passphrase = getpass.getpass(u"Please enter passphrase: ")
                passphrase = encoding.normalize_nfc(passphrase)
            except KeyboardInterrupt:
                sys.stderr.write(
                    u"\nKeyboard interrupt: passphrase not read. Aborting.\n")
                sys.exit(3)
            except Exception as e:
                sys.stderr.write(
                    u"Critical error: Passphrase not read. Aborting. (%s)" % e)
                sys.exit(3)
        else:
            dialog = TrezorPassphraseDialog()
            if not dialog.exec_():
                sys.exit(3)
            else:
                passphrase = dialog.passphrase()

        return proto.PassphraseAck(passphrase=passphrase)
Esempio n. 6
0
    def decryptPassword(self, encryptedPassword, groupName):
        """
		Decrypt a password. First block is IV. After decryption strips PKCS#5 padding.

		@param groupName key that will be shown to user on Trezor and
			was used to encrypt the password. A string in utf-8.
		@returns: string in unicode
		"""
        ugroup = tobytes(groupName)
        iv, encryptedPassword = encryptedPassword[:
                                                  BLOCKSIZE], encryptedPassword[
                                                      BLOCKSIZE:]
        # we junk the input, decrypt and reassemble the plaintext
        passwordBytes = b""
        first = not self.settings.NArg
        splits = [
            encryptedPassword[x:x + self.MAX_PADDED_TREZOR_ENCRYPT_SIZE]
            for x in range(0, len(encryptedPassword),
                           self.MAX_PADDED_TREZOR_ENCRYPT_SIZE)
        ]
        for junk in splits:
            plain = self.trezor.decrypt_keyvalue(basics.Magic.groupNode,
                                                 ugroup,
                                                 junk,
                                                 ask_on_encrypt=False,
                                                 ask_on_decrypt=first,
                                                 iv=iv)
            first = False
            passwordBytes += Padding(BLOCKSIZE).unpad(plain)
        return normalize_nfc(passwordBytes)
Esempio n. 7
0
	def comments(self):
		doc = self.commentsEdit.document().toPlainText()
		if doc is None:
			doc = u''
		else:
			doc = encoding.normalize_nfc(doc)
		return doc
    def encryptOnTrezorDevice(self, blob, keystring, innerIv=None):
        """
		Encrypt data. Does PKCS#5 padding before encryption.
		Store IV as first block.

		@param keystring: key that will be shown to user on Trezor and
			used to encrypt the data. A string in utf-8

		@returns: bytes
		"""
        self.settings.mlogger.log(
            'Time entering encryptOnTrezorDevice: %s' %
            (datetime.datetime.now()), logging.DEBUG, "Encryption")
        rnd = Random.new()
        rndBlock = rnd.read(BLOCKSIZE)
        if innerIv is not None:
            rndBlock = innerIv
        ukeystring = encoding.normalize_nfc(
            keystring)  # keystring.decode("utf-8")
        # minimum size of unpadded plaintext as input to trezor.encrypt_keyvalue() is 0    ==> padded that is 16 bytes
        # maximum size of unpadded plaintext as input to trezor.encrypt_keyvalue() is 1023 ==> padded that is 1024 bytes
        # plaintext input to trezor.encrypt_keyvalue() must be a multiple of 16
        # trezor.encrypt_keyvalue() throws error on anythin larger than 1024
        # In order to handle blobs larger than 1023 we junk the blobs
        encrypted = b''
        first = not self.settings.QArg
        splits = [
            blob[x:x + self.MAXUNPADDEDTREZORENCRYPTSIZE]
            for x in range(0, len(blob), self.MAXUNPADDEDTREZORENCRYPTSIZE)
        ]
        curr, max = 0, len(splits)
        for junk in splits:
            padded = Padding(BLOCKSIZE).pad(junk)
            try:
                encrypted += self.trezor.encrypt_keyvalue(
                    basics.Magic.levelTwoNode,
                    ukeystring,
                    padded,
                    ask_on_encrypt=False,
                    ask_on_decrypt=first,
                    iv=rndBlock)
            except Exception as e:
                self.settings.mlogger.log('Trezor failed. (%s)' % (e),
                                          logging.CRITICAL, "Encryption")
                raise
            first = False
            curr += 1
            if self.logger.getEffectiveLevel() == logging.DEBUG:
                sys.stderr.write("\rencrypting block %d of %d" % (curr, max), )
        if self.logger.getEffectiveLevel() == logging.DEBUG:
            sys.stderr.write(" --> done\n")
        ret = rndBlock + encrypted
        self.settings.mlogger.log(
            "Trezor encryption: plain-size = %d, encrypted-size = %d" %
            (len(blob), len(ret)), logging.DEBUG, "Encryption")
        self.settings.mlogger.log(
            'Time leaving encryptOnTrezorDevice: %s' %
            (datetime.datetime.now()), logging.DEBUG, "Encryption")
        return ret
Esempio n. 9
0
 def __str__(self):
     try:
         ss = u'[\n'
         for ee in self.entries:
             ss += u'(\t%s\n\t%s\n\t%s\n)' % (normalize_nfc(
                 ee[0]), binascii.hexlify(ee[1]), binascii.hexlify(ee[2]))
         return (ss + u'\n]')
     except Exception:
         ss = u'[\n'
         mydict = self.__dict__
         for instvarkey in mydict:
             instvarval = mydict[instvarkey]
             for ee in instvarval:
                 ss += u'(\t%s\n\t%s\n\t%s\n)' % (normalize_nfc(
                     ee[0]), normalize_nfc(binascii.hexlify(
                         ee[1])), normalize_nfc(binascii.hexlify(ee[2])))
         return (ss + u'\n]')
Esempio n. 10
0
    def prefillPassphrase(self, passphrase):
        """
		Instead of asking for passphrase, use this one
		"""
        if passphrase is not None:
            self.passphrase = encoding.normalize_nfc(passphrase)
        else:
            self.passphrase = None
Esempio n. 11
0
	def generatePassword(self):
		trezor_entropy = self.trezor.get_entropy(32)
		urandom_entropy = os.urandom(32)
		passwdBytes = hashlib.sha256(trezor_entropy + urandom_entropy).digest()
		# base85 encoding not yet implemented in Python 2.7, (requires Python 3+)
		# so we use base64 encoding
		# remove the base64 buffer char =, remove easily confused chars 0 and O, as well as I and l
		passwdB64bytes = base64.urlsafe_b64encode(passwdBytes)
		passwdB64bytes.replace(b'=', '')
		passwdB64bytes.replace(b'0', '')
		passwdB64bytes.replace(b'O', '')
		passwdB64bytes.replace(b'I', '')
		passwdB64bytes.replace(b'l', '')
		# print "bin =", passwdBin, ", base =", passwdB64, " binlen =", len(passwdBin), "baselen =", len(passwdB64)
		# instead of setting the values, we concatenate them to the existing values
		# This way, by clicking the "Generate password" button one can create an arbitrary long random password.
		self.pwEdit1.setText(self.pw1() + encoding.normalize_nfc(passwdB64bytes))
		self.pwEdit2.setText(self.pw2() + encoding.normalize_nfc(passwdB64bytes))
Esempio n. 12
0
    def setSelectedFile(self, fileNames):
        """
		Takes a py list as input and concatenates it and
		then places it into the single-line text field
		"""
        filenamesconcat = ""
        for file in fileNames:
            head, tail = os.path.split(file)
            filenamesconcat += '"' + tail + '"' + ' '
        self.selectedFileEdit.setText(encoding.normalize_nfc(filenamesconcat))
Esempio n. 13
0
	def importCsv(self):
		"""
		Read a properly formated CSV file from disk
		and add its contents to the current entries.

		Import format in CSV should be : group, key, password, comments

		There is no error checking, so be extra careful.

		Make a backup first.

		Entries from CSV will be *added* to existing pwdb. If this is not desired
		create an empty pwdb file first.

		GroupNames are unique, so if a groupname exists then
		key-password-comments tuples are added to the already existing group.
		If a group name does not exist, a new group is created and the
		key-password-comments tuples are added to the newly created group.

		Keys are not unique. So key-password-comments are always added.
		If a key with a given name existed before and the CSV file contains a
		key with the same name, then the key-password-comments is added and
		after the import the given group has 2 keys with the same name.
		Both keys exist then, the old from before the import, and the new one from the import.

		Examples of valid CSV file format: Some example lines
		First Bank account,login,myloginname,	# no comment
		[email protected],2-factor-authentication key,abcdef12345678,seed to regenerate 2FA codes	# with comment
		[email protected],recovery phrase,"passwd with 2 commas , ,",	# with comma
		[email protected],large multi-line comments,,"first line, some comma,
		second line"
		"""
		if self.modified:
			self.saveDatabase()
		copyfile(self.settings.dbFilename, self.settings.dbFilename + ".beforeCsvImport.backup")
		self.settings.mlogger.log("WARNING: You are about to import entries from a "
			"CSV file into your current password-database file. For safety "
			"reasons please make a backup copy now.\nFurthermore, this"
			"operation can be slow, so please be patient.", logging.NOTSET,
			"CSV import")
		dialog = QFileDialog(self, "Select CSV file to import",
			"", "CSV files (*.csv)")
		dialog.setAcceptMode(QFileDialog.AcceptOpen)

		res = dialog.exec_()
		if not res:
			return

		fname = encoding.normalize_nfc(dialog.selectedFiles()[0])
		listOfAddedGroupNames = self.pwMap.importCsv(fname)
		for groupNameNew in listOfAddedGroupNames:
			item = QStandardItem(groupNameNew)
			self.groupsModel.appendRow(item)
		self.groupsTree.sortByColumn(0, Qt.AscendingOrder)
		self.setModified(True)
Esempio n. 14
0
def migrateToUnicode(groupsDictBytes, settings):
    """
	In an old version of TrezorPass groupName and key (0-element of tuple)
	were in Py2 type 'str' (not in 'unicode') and did not allow
	foreign characters. To fix this when we read the pwdb file
	we must migrate from Py2 'str' to 'unicode'.

	Takes an instance such as PasswordMap.groups
	which is a dictionary of PasswordGroup instances.
	Each PasswordGroup instance is an object with entries
	which are lists of tuples.

	Migrated unpickled pwdb data of groups from Py2 to Py3 format.
	Takes an unpickled pwdb groups object in Py2 and
	returns an unpickled pwdb groups object in Py3 format.

	@params groupsDictBytes: un unpickled password groups instance
	@type groupsDictBytes: a bytes (Py3) or str (py2) version of unpickled dictionary {} of PasswordGroup instances
	@returns: a dictionary {} of PasswordGroup instances with groupName and key in str (Py3) or unicode (Py2)
	"""
    groupsDictStr = {}  # dictionary of PasswordGroup() instances
    ii = 0
    for groupName in groupsDictBytes:
        ii += 1
        # groupName is of type bytes
        pwGroup = groupsDictBytes[groupName]
        # pwGroup is of type PasswordGroup
        # create and add a new empty group in Py3, convert groupname to type string.
        groupsDictStr[normalize_nfc(groupName)] = PasswordGroup()
        # settings.mlogger.log("Password group %d read: \n%s" % (ii, normalize_nfc(groupName)),
        # 	logging.DEBUG, "TrezorPass database migration")
        for entry in pwGroup.entries:
            key, encPw, bkupPw = entry
            # add tuple to Py3 group
            groupsDictStr[normalize_nfc(groupName)].addEntry(
                normalize_nfc(key), encPw, bkupPw)
    settings.mlogger.log(
        "%d password groups have been migrated "
        "to unicode." % (ii), logging.DEBUG, "TrezorPass database migration")

    return (groupsDictStr)
Esempio n. 15
0
	def deleteGroup(self, item):  # without checking user
		groupName = encoding.normalize_nfc(item.text())
		self.selectedGroup = None
		del self.pwMap.groups[groupName]

		itemIdx = self.groupsModel.indexFromItem(item)
		self.groupsModel.takeRow(itemIdx.row())
		self.passwordTable.setRowCount(0)
		self.groupsTree.clearSelection()

		self.setModified(True)
		self.settings.mlogger.log("Group '%s' was deleted." % (groupName),
			logging.DEBUG, "GUI IO")
Esempio n. 16
0
	def editGroupWithCheck(self, item):
		"""
		Slot to edit name a password group.
		"""
		groupNameOld = encoding.normalize_nfc(item.text())
		dialog = AddGroupDialog(self.pwMap.groups, self.settings)
		dialog.setWindowTitle("Edit group name")
		dialog.groupNameLabel.setText("New name for group")
		dialog.setNewGroupName(groupNameOld)
		if not dialog.exec_():
			return

		groupNameNew = dialog.newGroupName()
		self.editGroup(item, groupNameOld, groupNameNew)
Esempio n. 17
0
def safetyCheckEncrypt(plaintextFname, encryptedFname, fileMap, settings):
    """
	check if previous encryption worked by
	renaming plaintextFname file to plaintextFname.<random number>.org
	decrypting file named encryptedFname producing new file decryptedFname
	comparing/diffing decryptedFname to original file now named plaintextFname.<random number>.org
	removing decrypted file decryptedFname
	renaming original file plaintextFname.<random number>.org back to input plaintextFname

	@param plaintextFname: name of existing plaintext file whose previous encryption needs to be double-checked
	@type plaintextFname: C{string}
	@param encryptedFname: name of existing encrypted file (i.e. the plaintext file encrypted)
	@type encryptedFname: C{string}
	@param settings: holds settings for how to log info/warnings/errors
	@type settings: L{Settings}
	@param fileMap: object to use to handle file format of encrypted file
	@type fileMap: L{file_map.FileMap}
	@returns: True if safety check passes successfuly, False otherwise
	@rtype: C{bool}
	"""
    urandom_entropy = os.urandom(64)
    randomBytes = hashlib.sha256(urandom_entropy).digest()
    # randomBytes is bytes in Py3, str in Py2
    # base85 encoding not yet implemented in Python 2.7, (requires Python 3+)
    # so we use base64 encoding
    # replace the base64 buffer char =
    randomB64bytes = base64.urlsafe_b64encode(randomBytes)
    # randomB64bytes is bytes in Py3, str in Py2
    randomB64str = encoding.normalize_nfc(randomB64bytes)
    randomB64str = randomB64str.replace(u'=', u'-')
    originalFname = plaintextFname + u"." + randomB64str + u".orignal"
    os.rename(plaintextFname, originalFname)
    decryptedFname = decryptFile(encryptedFname, settings, fileMap)
    aresame = filecmp.cmp(decryptedFname, originalFname, shallow=False)
    ihead, itail = os.path.split(plaintextFname)
    ohead, otail = os.path.split(encryptedFname)
    if aresame:
        settings.mlogger.log(
            "Safety check of file \"%s\" (\"%s\") was successful." %
            (otail, itail), logging.INFO, "File encryption")
    else:
        settings.mlogger.log(
            "Fatal error: Safety check of file \"%s\" (\"%s\") failed! "
            "You must inestigate. Encryption was flawed!" % (otail, itail),
            logging.CRITICAL, "File encryption")
    os.remove(decryptedFname)
    os.rename(originalFname, plaintextFname)
    return aresame
Esempio n. 18
0
    def decryptPassword(self, encryptedPassword, privateKey):
        """
		Decrypt RSA-OAEP encrypted password.
		@param encryptedPassword: encrypted password entry, key/value pair
		@type encryptedPassword: bytes
		@returns: decrypted pasword of type string (unicode)
		"""
        cipher = PKCS1_OAEP.new(privateKey)
        passwordBytes = b''
        splits = [
            encryptedPassword[x:x + self.RSA_BLOCKSIZE]
            for x in range(0, len(encryptedPassword), self.RSA_BLOCKSIZE)
        ]
        for junk in splits:
            passwordBytes += cipher.decrypt(junk)

        return (encoding.normalize_nfc(passwordBytes))
Esempio n. 19
0
    def __init__(self, logger=None, mlogger=None):
        """
		@param logger: holds logger for where to log info/warnings/errors
			If None, a default logger will be created.
		@type logger: L{logging.Logger}
		@param mlogger: holds mlogger for where to log info/warnings/errors
			If None, a default mlogger will be created.
		@type mlogger: L{utils.MLogger}
		"""
        super(Settings, self).__init__(logger, mlogger)
        self.dbFilename = None  # pwdb file name
        self.qsettings = QSettings(u"ConstructibleUniverse", u"TrezorPass")
        fname = self.qsettings.value(u"database/filename")
        # returns None or unicode string
        if fname is not None:
            self.dbFilename = encoding.normalize_nfc(fname)
        self.TArg = False  # Terminal mode
        self.NArg = False  # noconfirm mode
        self.PArg = None  # passphrase
        self.QArg = False  # set pwdb file as Defaut
        self.FArg = None  # pwdb file name, None or a string

        self.AArg = False  # add flag
        self.CArg = False  # clip flag
        self.SArg = False  # show
        self.OArg = False  # showcomments
        self.BArg = False  # showboth
        self.EArg = False  # showkeys
        self.XArg = False  # showgroups
        self.DArg = False  # delete
        self.RArg = False  # rename group
        self.UArg = False  # update password entries
        self.YArg = None  # importcsv
        self.ZArg = None  # exportcsv
        self.WArg = None  # password/secret, None or a string
        self.MArg = None  # comments, None or a string
        self.GArg = None  # group name, None or a string
        self.KArg = None  # key name, None or a string
        self.n0Arg = None  # new group name, None or a string
        self.n1Arg = None  # new key name, None or a string
        self.n2Arg = None  # new password, None or a string
        self.n3Arg = None  # new comments, None or a string
    def deobfuscateFilename(self, obfuscatedFileName):
        """
		obfuscated filename --> homegrown unpadding --> base64 decode
			--> AES decrypt on Trezor -->  unpad16 == Plaintext filename
		input: string
		output: string
		"""
        hgUp = PaddingHomegrown().unpad(obfuscatedFileName)  # mod 4
        hgUpBytes = encoding.tobytes(hgUp)
        bs64 = base64.urlsafe_b64decode(hgUpBytes)  # mod anything
        self.settings.mlogger.log(
            "Press confirm on Trezor device to decrypt "
            "file name %s (if necessary)." % (obfuscatedFileName),
            logging.DEBUG, "Encryption")
        if len(bs64) % BLOCKSIZE != 0:
            raise ValueError("Critical error. File name " +
                             obfuscatedFileName +
                             " could not be deobfuscated. Skipping it.")
        # we do not use an IV here so that we can quickly deobfuscate filenames
        # without reading the file, even for files that do not exist
        decFn = self.trezor.decrypt_keyvalue(
            basics.Magic.fileNameNode,
            basics.Magic.fileNameKey,
            bs64,
            ask_on_encrypt=False,
            ask_on_decrypt=not self.settings.QArg,
            iv=self.baddressIv)
        ret = Padding(BLOCKSIZE).unpad(decFn)
        retStr = encoding.normalize_nfc(ret)
        # self.settings.mlogger.log("\n\tobfuscatedFileName is %s (%d), "
        # 	"\n\thgUp is %s (%d), \n\tbs64 is %s (%d), \n\tdecFn is %s (%d), "
        # 	"\n\tret is %s (%d)", obfuscatedFileName, len(obfuscatedFileName),
        # 	hgUp, len(hgUp), binascii.hexlify(bs64), len(bs64),
        # 	decFn, len(decFn), ret, len(ret))
        if len(retStr) == 0:
            # try the old version, maybe it is an old file
            return (self.deobfuscateFilenameOld(obfuscatedFileName))
        self.settings.mlogger.log(
            "The plaintext filename for %s is %s." %
            (obfuscatedFileName, retStr), logging.DEBUG, "Encryption")
        return retStr
Esempio n. 21
0
	def exportCsv(self):
		"""
		Uses backup key encrypted by Trezor to decrypt all passwords
		at once and export them into a single paintext CSV file.

		Export format is CSV: group, key, password, comments
		"""
		self.settings.mlogger.log("WARNING: During backup/export all passwords will be "
			"written in plaintext to disk. If possible you should consider performing this "
			"operation on an offline or air-gapped computer. Be aware of the risks.",
			logging.NOTSET,	"CSV export")
		dialog = QFileDialog(self, "Select backup export file",
			"", "CSV files (*.csv)")
		dialog.setAcceptMode(QFileDialog.AcceptSave)

		res = dialog.exec_()
		if not res:
			return

		fname = encoding.normalize_nfc(dialog.selectedFiles()[0])
		self.pwMap.exportCsv(fname)
Esempio n. 22
0
	def setPw2(self, pw):
		self.masterEdit2.setText(encoding.normalize_nfc(pw))
Esempio n. 23
0
 def pin(self):
     return encoding.normalize_nfc(self.pinEdit.text())
Esempio n. 24
0
 def passphrase(self):
     return encoding.normalize_nfc(self.passphraseEdit.text())
Esempio n. 25
0
    def parseArgs(self, argv, settings=None, logger=None):
        """
		Parse the command line arguments and store the results in `settings`.
		Report errors to `logger`.

		This method should be implemented in the subclass.
		Calling this method is only useful when the application has exactly
		the 3 arguments -h -v -l [level]

		@param settings: place to store settings;
			if None the default settings from the Args class will be used.
			So, usually this argument would be None.
		@type settings: L{Settings}
		@param logger: holds logger for where to log info/warnings/errors
			if None the default logger from the Args class will be used.
			So, usually this argument would be None.
		@type logger: L{logging.Logger}
		"""
        # get defaults
        if logger is None:
            logger = self.logger
        if settings is None:
            settings = self.settings
        try:
            opts, args = getopt.getopt(argv, "vhl:",
                                       ["version", "help", "logging="])
        except getopt.GetoptError as e:
            msgBox = QMessageBox(QMessageBox.Critical, u"Wrong arguments",
                                 u"Error: %s" % e)
            msgBox.exec_()
            logger.critical(u'Wrong arguments. Error: %s.', e)
            sys.exit(2)
        loglevelused = False
        for opt, arg in opts:
            arg = normalize_nfc(arg)
            if opt in ("-h", "--help"):
                self.printUsage()
                sys.exit()
            elif opt in ("-v", "--version"):
                self.printVersion()
                sys.exit()
            elif opt in ("-l", "--logging"):
                loglevelarg = arg
                loglevelused = True

        if loglevelused:
            try:
                loglevel = int(loglevelarg)
            except Exception:
                self.settings.mlogger.log(
                    u"Logging level not specified correctly. "
                    "Must be integer between 1 and 5. (%s)" % loglevelarg,
                    logging.CRITICAL, "Wrong arguments", True, logger)
                sys.exit(18)
            if loglevel > 5 or loglevel < 1:
                self.settings.mlogger.log(
                    u"Logging level not specified correctly. "
                    "Must be integer between 1 and 5. (%s)" % loglevelarg,
                    logging.CRITICAL, "Wrong arguments", True, logger)
                sys.exit(19)
            settings.LArg = loglevel * 10  # https://docs.python.org/2/library/logging.html#levels
        logger.setLevel(settings.LArg)

        self.settings.mlogger.log(
            u"%s Version: %s (%s)" %
            (basics.NAME, basics.VERSION_STR, basics.VERSION_DATE_STR),
            logging.INFO, "Version", True, logger)
        self.settings.mlogger.log(
            u"Python: %s" % sys.version.replace(" \n", "; "), logging.INFO,
            "Version", True, logger)
        self.settings.mlogger.log(u"Qt Version: %s" % QT_VERSION_STR,
                                  logging.INFO, "Version", True, logger)
        self.settings.mlogger.log(u"PyQt Version: %s" % PYQT_VERSION_STR,
                                  logging.INFO, "Version", True, logger)
        self.settings.mlogger.log(
            u'Logging level set to %s (%d).' %
            (logging.getLevelName(settings.LArg), settings.LArg), logging.INFO,
            "Logging", True, logger)
        self.settings.mlogger.log(settings, logging.DEBUG, "Settings", True,
                                  logger)
Esempio n. 26
0
    def importCsv(self, fname):
        """
		See also the method with the same name in Dialog class in dialogs.py

		@param fname: name of CSV file
		@type fname: string
		@returns list of srings reflecting the list of NEW group names
			that were ADDED to the known group names by reading
			from the CSV file
		"""
        if not os.path.isfile(fname):
            raise KeyError('File "%s" does not exist, is not a proper file, '
                           'or is a directory. Aborting.' % fname)
        if not os.access(fname, os.R_OK):
            raise KeyError('File "%s" is not readable. Aborting.' % fname)
        # list to track all new group names read from the CSV file,
        # that did not exist before
        listOfAddedGroupNames = []
        with open(fname, "r") as f:
            csv.register_dialect("escaped", doublequote=False, escapechar='\\')
            reader = csv.reader(f, dialect="escaped")
            for csvEntry in reader:
                # self.settings.mlogger.log("CSV Entry: len=%d 0=%s" % (len(csvEntry), csvEntry[0]),
                # 	logging.DEBUG, "CSV import")
                # self.settings.mlogger.log("CSV Entry: 0=%s, 1=%s, 2=%s, 3=%s" %
                # 	(csvEntry[0], csvEntry[1], csvEntry[2], csvEntry[3]), logging.DEBUG,
                # 	"CSV import")
                try:
                    groupName = normalize_nfc(csvEntry[0])
                    key = normalize_nfc(csvEntry[1])
                    plainPw = normalize_nfc(csvEntry[2])
                    plainComments = normalize_nfc(csvEntry[3])
                except Exception as e:
                    raise IOError(
                        "Critical Error: Could not import CSV file. "
                        "CSV Entry: len=%d (should be 4) element[0]=%s. (%s)" %
                        (len(csvEntry), csvEntry[0], e))

                groupNames = self.groups.keys()
                if groupName not in groupNames:  # groups are unique
                    self.addGroup(groupName)
                    listOfAddedGroupNames.append(groupName)

                if len(plainPw) + len(
                        plainComments) > basics.MAX_SIZE_OF_PASSWDANDCOMMENTS:
                    self.settings.mlogger.log(
                        "Password and/or comments too long. "
                        "Combined they must not be larger than %d." %
                        basics.MAX_SIZE_OF_PASSWDANDCOMMENTS, logging.NOTSET,
                        "CSV import")
                    return
                group = self.groups[groupName]
                plainPwComments = ("%4d" %
                                   len(plainPw)) + plainPw + plainComments
                encPw = self.encryptPassword(plainPwComments, groupName)
                bkupPw = self.backupKey.encryptPassword(plainPwComments)
                group.addEntry(
                    key, encPw, bkupPw
                )  # keys are not unique, multiple items with same key are allowed

        self.settings.mlogger.log(
            "TrezorPass has finished importing CSV file "
            "from \"%s\" into \"%s\"." % (fname, self.settings.dbFilename),
            logging.INFO, "CSV import")
        return (listOfAddedGroupNames)
Esempio n. 27
0
	def key(self):
		return encoding.normalize_nfc(self.keyEdit.text())
Esempio n. 28
0
	def pw1(self):
		return encoding.normalize_nfc(self.pwEdit1.text())
Esempio n. 29
0
	def pw2(self):
		return encoding.normalize_nfc(self.masterEdit2.text())
Esempio n. 30
0
	def pwFile(self):
		return encoding.normalize_nfc(self.pwFileEdit.text())