使用 Sublime 在打开时解密,在保存时加密
Decrypt on open, encrypt on save with Sublime
我正在编写一个简单的插件:
- 在加载时解密每个扩展名为
.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):
解决这个问题,并在保存操作后 恢复 未加密的明文。它有点工作,但是,即使文件已保存并且没有进行任何更改,Sublime 认为文件已被修改! (因为未加密的明文已经替换了保存的文件的加密版本)。
加载.crypt
文件时,在编辑器中显示密文window,如何在提示输入密码之前隐藏这个?
总的来说,这样的东西并不像我们希望的那样干净和无缝;底层系统假定 view
与磁盘上的文件相关联,并且应直接跟踪任何修改。因此,尝试使用未出现在该文件中的内容来表示与文件关联的 view
的内容是有问题的。
虽然它不是那么无缝,但就像让一个命令在后台执行它自己的加密保存(这会留下两个文件)并捕获视图的内容,关闭它并从中重新创建适合的原始文件更符合 Sublime 期望事情如何运作。
I tried to solve this with def on_post_save(view):
and restore the unencrypted plaintext after a save operation. It kind of works, but then, even if the file is saved and no change has been done, then Sublime thinks the file is modified! (because unencrypted plaintext has replaced the saved encrypted version of the file).
对缓冲区进行任何类型的修改都会将其标记为 dirty
,这就是发生这种情况的原因。只有两件事可以从文件中删除此状态。
其中比较明显的是save
命令;一旦 Sublime 将数据保存到磁盘,它就会从文件中删除 dirty
标志,
另一种是使用view.set_scratch(True)
将view
标记为临时视图;草稿视图根本不显示任何类型的修改状态,因此您可以使用它来暂时关闭表示文件已修改的标记。
一个问题是,一旦文件被标记为 scratch
,无论您进行多少更改,它都不会显示为已修改。此外,这只会阻止 Sublime 将状态渲染为脏;一旦删除了暂存状态,脏状态将 return(即使视图处于暂存模式时 view.is_dirty()
将 return False
)。
您可以在一定程度上解决这个问题,方法是将视图设置为 scratch
,然后对其应用视图设置,并让 on_modified
事件侦听器仅在该视图设置为启用并删除 scratch
状态(和设置),以便在您进行修改之前缓冲区看起来未被修改。
这并非没有问题;例如,您可以撤消将文件的加密版本替换为纯文本版本的操作,这可能是可取的,也可能是不可取的。
这里的另一种方法是通过手动将文件写入磁盘而不是让 Sublime 为您完成文件加密来保存自己;在那种情况下,您可以完全控制并且不需要更改缓冲区的内容,因此它只会在应该变脏时变脏。不利的一面是,这会留下一个未加密的文件版本(尽管您可以根据需要删除它 on_close
)。
When a .crypt file is loaded, the ciphertext is displayed in the editor window, how to hide this until the password is entered in the prompt?
一种方法是准备一个具有相同前景和背景字符的配色方案,并在输入密码之前覆盖 view
中的 color_scheme
设置,此时点你可以删除它。这会隐藏数据。
另一种方法是从文件中捕获数据,然后使用 view.close()
关闭选项卡(您可能还需要捕获其他信息,例如文件名)。然后您将能够创建一个新的空视图并用解密的数据填充它(尽管您仍然需要执行与上述相同的技巧以使其看起来不脏。
我正在编写一个简单的插件:
- 在加载时解密每个扩展名为
.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):
解决这个问题,并在保存操作后 恢复 未加密的明文。它有点工作,但是,即使文件已保存并且没有进行任何更改,Sublime 认为文件已被修改! (因为未加密的明文已经替换了保存的文件的加密版本)。加载
.crypt
文件时,在编辑器中显示密文window,如何在提示输入密码之前隐藏这个?
总的来说,这样的东西并不像我们希望的那样干净和无缝;底层系统假定 view
与磁盘上的文件相关联,并且应直接跟踪任何修改。因此,尝试使用未出现在该文件中的内容来表示与文件关联的 view
的内容是有问题的。
虽然它不是那么无缝,但就像让一个命令在后台执行它自己的加密保存(这会留下两个文件)并捕获视图的内容,关闭它并从中重新创建适合的原始文件更符合 Sublime 期望事情如何运作。
I tried to solve this with
def on_post_save(view):
and restore the unencrypted plaintext after a save operation. It kind of works, but then, even if the file is saved and no change has been done, then Sublime thinks the file is modified! (because unencrypted plaintext has replaced the saved encrypted version of the file).
对缓冲区进行任何类型的修改都会将其标记为 dirty
,这就是发生这种情况的原因。只有两件事可以从文件中删除此状态。
其中比较明显的是save
命令;一旦 Sublime 将数据保存到磁盘,它就会从文件中删除 dirty
标志,
另一种是使用view.set_scratch(True)
将view
标记为临时视图;草稿视图根本不显示任何类型的修改状态,因此您可以使用它来暂时关闭表示文件已修改的标记。
一个问题是,一旦文件被标记为 scratch
,无论您进行多少更改,它都不会显示为已修改。此外,这只会阻止 Sublime 将状态渲染为脏;一旦删除了暂存状态,脏状态将 return(即使视图处于暂存模式时 view.is_dirty()
将 return False
)。
您可以在一定程度上解决这个问题,方法是将视图设置为 scratch
,然后对其应用视图设置,并让 on_modified
事件侦听器仅在该视图设置为启用并删除 scratch
状态(和设置),以便在您进行修改之前缓冲区看起来未被修改。
这并非没有问题;例如,您可以撤消将文件的加密版本替换为纯文本版本的操作,这可能是可取的,也可能是不可取的。
这里的另一种方法是通过手动将文件写入磁盘而不是让 Sublime 为您完成文件加密来保存自己;在那种情况下,您可以完全控制并且不需要更改缓冲区的内容,因此它只会在应该变脏时变脏。不利的一面是,这会留下一个未加密的文件版本(尽管您可以根据需要删除它 on_close
)。
When a .crypt file is loaded, the ciphertext is displayed in the editor window, how to hide this until the password is entered in the prompt?
一种方法是准备一个具有相同前景和背景字符的配色方案,并在输入密码之前覆盖 view
中的 color_scheme
设置,此时点你可以删除它。这会隐藏数据。
另一种方法是从文件中捕获数据,然后使用 view.close()
关闭选项卡(您可能还需要捕获其他信息,例如文件名)。然后您将能够创建一个新的空视图并用解密的数据填充它(尽管您仍然需要执行与上述相同的技巧以使其看起来不脏。