示例#1
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)
    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
示例#3
0
    def encrypt(self, plaintext, iv, key):
        """
		Pad plaintext with PKCS#5 and encrypt it.
		"""
        cipher = AES.new(key, AES.MODE_CBC, iv)
        padded = Padding(BLOCKSIZE).pad(plaintext)
        return cipher.encrypt(padded)
    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
示例#5
0
    def decrypt(self, ciphertext, iv, key):
        """
		Decrypt ciphertext, unpad it and return
		"""
        cipher = AES.new(key, AES.MODE_CBC, iv)
        plaintext = cipher.decrypt(ciphertext)
        unpadded = Padding(BLOCKSIZE).unpad(plaintext)
        return unpadded
    def encrypt(self, plaintext, iv, key):
        """
		Pad plaintext with PKCS#5 and encrypt it.
		"""
        self.settings.mlogger.log(
            "AES CBC encryption with key of size %d bits." % (len(key) * 8),
            logging.DEBUG, "Encryption")
        cipher = AES.new(key, AES.MODE_CBC, iv)
        padded = Padding(BLOCKSIZE).pad(plaintext)
        return cipher.encrypt(padded)
    def decrypt(self, ciphertext, iv, key):
        """
		Decrypt ciphertext, unpad it and return
		"""
        self.settings.mlogger.log(
            "AES CBC decryption with key of size %d bits." % (len(key) * 8),
            logging.DEBUG, "Encryption")
        cipher = AES.new(key, AES.MODE_CBC, iv)
        plaintext = cipher.decrypt(ciphertext)
        unpadded = Padding(BLOCKSIZE).unpad(plaintext)
        return unpadded
示例#8
0
文件: backup.py 项目: dr3wme/deoscore
    def unwrapPrivateKey(self):
        """ Decrypt private RSA key using self.encryptedEphemeral
        from self.encryptedPrivate. Encrypted ephemeral key will
        be decrypted with Trezor.

        @returns RSA private key as Crypto.RSA._RSAobj
        """
        ephemeral = self.trezor.decrypt_keyvalue(Magic.backupNode,
                                                 Magic.backupKey,
                                                 self.encryptedEphemeral,
                                                 ask_on_encrypt=False,
                                                 ask_on_decrypt=True)
        cipher = AES.new(ephemeral, AES.MODE_CBC, self.ephemeralIv)
        padded = cipher.decrypt(self.encryptedPrivate)
        privateDer = Padding(self.BLOCKSIZE).unpad(padded)
        privateKey = RSA.importKey(privateDer)
        return privateKey
示例#9
0
文件: backup.py 项目: dr3wme/deoscore
 def wrapPrivateKey(self, privateKey):
     """ Wrap serialized private key by encrypting it with trezor.
     """
     # Trezor client won't allow to encrypt whole serialized RSA
     # key in one go - it's too big. We need an ephemeral symmetric
     # key and encrypt the small ephemeral with Trezor.
     rng = Random.new()
     ephemeral = rng.read(self.SYMMETRIC_KEYSIZE)
     self.ephemeralIv = rng.read(self.BLOCKSIZE)
     cipher = AES.new(ephemeral, AES.MODE_CBC, self.ephemeralIv)
     padded = Padding(self.BLOCKSIZE).pad(privateKey)
     self.encryptedPrivate = cipher.encrypt(padded)
     self.encryptedEphemeral = self.trezor.encrypt_keyvalue(
         Magic.backupNode,
         Magic.backupKey,
         ephemeral,
         ask_on_encrypt=False,
         ask_on_decrypt=True)
    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
示例#11
0
    def encryptPassword(self, password, groupName):
        """
		Encrypt a password. Does PKCS#5 padding before encryption.
		Store IV as first block.

		@param password: text to encrypt (combined password+comments)
		@type password: string
		@param groupName: key that will be shown to user on Trezor and
			used to encrypt the password. A string in utf-8
		@type groupName: string
		@returns: bytes
		"""
        rnd = Random.new()
        rndBlock = rnd.read(BLOCKSIZE)
        ugroup = tobytes(groupName)
        password = tobytes(password)
        # 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 passwords+comments larger than 1023 we junk the passwords+comments
        encrypted = b""
        first = not self.settings.NArg
        splits = [
            password[x:x + self.MAX_UNPADDED_TREZOR_ENCRYPT_SIZE] for x in
            range(0, len(password), self.MAX_UNPADDED_TREZOR_ENCRYPT_SIZE)
        ]
        for junk in splits:
            padded = Padding(BLOCKSIZE).pad(junk)
            encrypted += self.trezor.encrypt_keyvalue(basics.Magic.groupNode,
                                                      ugroup,
                                                      padded,
                                                      ask_on_encrypt=False,
                                                      ask_on_decrypt=first,
                                                      iv=rndBlock)
            first = False
        ret = rndBlock + encrypted
        # print "Trezor encryption: plain-size =", len(password), ", encrypted-size =", len(encrypted)
        return ret
    def decryptOnTrezorDevice(self, encryptedblob, keystring):
        """
		Decrypt a blob. First block is IV. After decryption strips PKCS#5 padding.

		@param keystring: key that will be shown to user on Trezor and
			was used to encrypt the blob. A string in utf-8.
		@returns bytes
		"""
        if (len(encryptedblob) > 8388608):  # 8M+ and -2 option
            self.settings.mlogger.log(
                "This will take more than 10 minutes. Be ready to wait! "
                "Decrypting each Megabyte on the Trezor (model 1) takes about 75 seconds, "
                "or 0.8MB/min. This file will take about %d minutes. If you want to "
                "en/decrypt fast the next time around, remove the `-2` or `--twice` "
                "option when you encrypt a file." %
                (len(encryptedblob) // 819200), logging.WARNING, "Encryption")
        self.settings.mlogger.log(
            'Time entering decryptOnTrezorDevice: %s' %
            (datetime.datetime.now()), logging.DEBUG, "Encryption")
        ukeystring = encoding.normalize_nfc(
            keystring)  # keystring.decode("utf-8")
        iv, encryptedblob = encryptedblob[:BLOCKSIZE], encryptedblob[
            BLOCKSIZE:]
        # we junk the input, decrypt and reassemble the plaintext
        blob = b''
        first = not self.settings.QArg
        self.settings.mlogger.log(
            "Press confirm on Trezor device for second level "
            "file decryption on Trezor device itself (if necessary).",
            logging.DEBUG, "Encryption")
        self.settings.mlogger.log(
            "Trezor decryption: encrypted-size = %d" % (len(encryptedblob)),
            logging.DEBUG, "Encryption")
        splits = [
            encryptedblob[x:x + self.MAXPADDEDTREZORENCRYPTSIZE] for x in
            range(0, len(encryptedblob), self.MAXPADDEDTREZORENCRYPTSIZE)
        ]
        curr, max = 0, len(splits)
        for junk in splits:
            try:
                plain = self.trezor.decrypt_keyvalue(basics.Magic.levelTwoNode,
                                                     ukeystring,
                                                     junk,
                                                     ask_on_encrypt=False,
                                                     ask_on_decrypt=first,
                                                     iv=iv)
            except Exception as e:
                self.settings.mlogger.log('Trezor failed. (%s)' % (e),
                                          logging.CRITICAL, "Encryption")
                raise
            first = False
            blob += Padding(BLOCKSIZE).unpad(plain)
            curr += 1
            if self.logger.getEffectiveLevel() == logging.DEBUG:
                sys.stderr.write("\rdecrypting block %d of %d" % (curr, max), )
        if self.logger.getEffectiveLevel() == logging.DEBUG:
            sys.stderr.write(" --> done\n")
        self.settings.mlogger.log(
            "Trezor decryption: encrypted-size = %d, plain-size = %d" %
            (len(encryptedblob), len(blob)), logging.DEBUG, "Encryption")
        if len(blob) == 0:
            raise ValueError("Decrypting data failed. Wrong Trezor device?")
        self.settings.mlogger.log(
            'Time leaving decryptOnTrezorDevice: %s' %
            (datetime.datetime.now()), logging.DEBUG, "Encryption")
        self.innerIv = iv
        return blob