解密时打开,保存时使用Sublime加密

问题描述 投票:0回答:1

我正在编写一个简单的插件,它:

  • 在加载时解密每个扩展名为.crypt的文件,提示输入密码
  • 在保存时对它们进行加密(如果在加载过程中已经询问过,则不重新询问密码;仅在要保存的新文件时询问密码)

在下面的代码中,加密方法很简单:password是整数,并且加密移位+password的每个字符;解密会移动-password的每个字符(即,将password减去每个字符的值)。这不是真正的加密也不是安全的方法;当然,以后我将用AES加密或类似的方法代替它,但是在此示例中,这足以说明我在此问题中遇到的问题。

import sublime_plugin, sublime

password = None

class PromptCryptCommand(sublime_plugin.WindowCommand):
    def run(self):
        panel = self.window.show_input_panel("Enter password", "2", self.on_done, None, None)

    def on_done(self, pwd):
        global password
        password = int(pwd)
        self.window.run_command(action)

class EncryptCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        region = sublime.Region(0, self.view.size())
        plaintext = self.view.substr(region)
        ciphertext = ''.join([chr(ord(c)+password) for c in plaintext])
        self.view.replace(edit, region, ciphertext)

class DecryptCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        region = sublime.Region(0, self.view.size())
        ciphertext = self.view.substr(region)
        plaintext = ''.join([chr(ord(c)-password) for c in ciphertext])
        self.view.replace(edit, region, plaintext)

class LoadSaveListener(sublime_plugin.EventListener):
    def on_load(self, view):
        global action
        if view.file_name().endswith(".crypt"):
            action = 'decrypt'
            view.window().run_command('prompt_crypt')

    def on_pre_save(self, view):
        global action
        if view.file_name().endswith(".crypt"):
            if password == None:  # password not entered yet, let's prompt for it
                action = 'encrypt'
                view.window().run_command('prompt_crypt')
            else:  # password already asked when file was loaded, 
                view.window().run_command('encrypt')

我遇到了这些我不知道如何解决的问题:

  • 我用CTRL + S重新保存了多次,文件被重新保存,即被重新加密。例如:

    plaintext = 'abc'
    password = 2
    after one CTRL+S, content = 'cde'
    after one more CTRS+S, content = 'efg'
    after one more CTRS+S, content = 'ghi' etc.
    

    我尝试用def on_post_save(view):restore解决未保存的纯文本,然后进行保存操作。确实可以,但是即使保存了文件且未进行任何更改,Sublime 认为文件已修改也可以! (因为未加密的纯文本已替换文件的已保存加密版本)。

  • 当加载.crypt文件时,密文显示在编辑器窗口中,如何隐藏该密文,直到在提示中输入密码?

sublimetext3 sublimetext2 sublimetext sublime-text-plugin
1个回答
0
投票
总的来说,这样的事情并不像我们希望的那样干净,无缝。基础系统假定view与磁盘上的文件关联,并且应直接跟踪任何修改。因此,尝试使用未出现在文件中的内容来表示与该文件关联的view的内容是有问题的。

尽管不是那么无缝,但是像命令一样,它会在后台自己加密保存(这将保留两个文件)并捕获视图的内容,然后关闭视图并从中重新创建原始文件以及Sublime期望事情如何运作。

我尝试使用def on_post_save(view):解决此问题,并在保存操作后恢复未加密的纯文本。这样做是可行的,但是,即使保存了文件且未进行任何更改,Sublime仍认为文件已修改! (因为未加密的纯文本已替换文件的已保存加密版本)。

对缓冲区进行任何形式的修改都将其标记为dirty,这就是这种情况的原因。只有两件事可以从文件中删除此状态。

其中最明显的是save命令;一旦Sublime将数据持久保存到磁盘,它就会从文件中删除dirty标志,

另一种方法是使用viewview.set_scratch(True)标记为草稿视图;临时视图根本不显示任何修改状态,因此您可以使用它暂时关闭表示文件已修改的标记。

与此相关的问题是,一旦文件被标记为scratch,无论您进行了多少更改,它都将永远不会显示为已修改。另外,这只会阻止Sublime将状态渲染为脏状态;一旦删除暂存状态,脏状态将返回(即使视图处于暂存模式时view.is_dirty()将返回False。)>

您可以通过以下方法在某种程度上解决此问题:将视图设置为scratch,然后对其应用视图设置,并使on_modified事件侦听器仅在启用该视图设置时触发,并删除scratch状态(和设置),以便在您进行修改之前,缓冲区看起来没有被修改。

这并非没有问题;例如,您可以通过用纯文本替换文件的加密版本的操作来撤消操作,这可能是不希望的。

这里的另一种选择是通过手动将文件写入磁盘而不是让Sublime替您完成文件加密来节省文件的加密;在这种情况下,您完全可以控制,不需要更改缓冲区的内容,因此只有在本应为脏的情况下它才会脏。不利的一面是,它将留下未加密版本的文件(尽管您可以根据需要将其删除on_close)。

当加载.crypt文件时,密文会显示在编辑器窗口中,如何隐藏该密文,直到在提示中输入密码?

执行此操作的一种方法是,准备一种具有相同前景和背景字符的配色方案,并覆盖color_scheme中的view设置,直到输入密码后,您才能将其删除。这将隐藏数据。

一种替代方法是从文件中捕获数据,然后使用view.close()关闭选项卡(例如,您可能还需要捕获其他信息,例如文件名)。然后,您将能够创建一个新的空视图,并使用解密的数据填充它(尽管您仍然需要执行与上述相同的技巧,以使其看起来不会变脏。

© www.soinside.com 2019 - 2024. All rights reserved.