相信很多使用Python的同学熟悉编解码,比如:
1 |
|
这样可以在字符串和unicode之前转换,不过细心的同学可能发现了,我使用了「utf-8」和「utf8」,这2个词长得很像。事实上都能正常使用是由于他们都是「utf_8」的别名,这些别名的对应关系可以用如下方法找到:
1 |
|
encodings是标准库中自带的编码库,其中包含了上百个标准的编码转换方案。但是通常并不需要使用encodings,而是使用codecs。
codecs包含了编码解码器的注册和其他基本的类,开发者还可以通过codecs提供的接口自定义编/解码方案,也就是可以创造一个新的编解码转换方案,使用encode(‘XX’)和decode(‘XX’)的方式使用。今天我给大家演示直接进行Fernet对称加密的例子。
互联网安全的重要性不必在复述了,大家都应该接触过一些加密技术,可能听过M2Crypto、PyCrypto、Cryptography之类的库。在这里歪个楼,现在的主流是使用Cryptography,它的出现就是为了替代之前的那些库,具体的可以看官方文档。我们使用Cryptography提供的Fernet类来实现,首先实现一个Codec类:
1 |
|
当然也不必在类中实现encode和decode方法,单独的2个函数也可以。我这里是为了给之后的演示到的类复用。
如果你看过内置的字符串encode的方法,它的文档说还接收第二个参数,让你告诉它当出现出错的时候如何去处理,默认是strict,直接就会抛出来错误。
其余可选的还有ignore、replace、xmlcharrefreplace:
1 |
|
事实上Python还内置了其他的选项,如backslashreplace、namereplace、surrogatepass、surrogateescape等,有兴趣的可以看源码实现.
我也会定义2种错误函数,因为在解密(执行decrypt)的时候可能会报InvalidToken错误,但是InvalidToken不包含任何参数,而对错误处理的时候需要知道起始和结束的位置,所以我就直接抛一个UnicodeDecodeError错误了。
接着我们定义递增式和流式的编码类:
1 |
|
由于这个要加密的字符串不会很长,没有必要实现这些类,我就简单的继承然后pass了。接着开开放入口:
1 |
|
其实incrementalencoder、streamwriter这些参数不传递也是可以的,默认是None,今天只是为了让大家知道是有这部分接口的。然后是注册这个入口,为了提供更好的性能,我创建一个函数加上缓存功能:
1 |
|
这里简单介绍下normalize_encoding的意义,之前我说到了别名,我们再感受下:
1 |
|
这种中划线和下划线最后无差别对待,就是通过这个函数标准化的。
codecs模块底层维护了一个搜索函数的列表,通过调用codecs.register方法就把上述函数append进去了。
最后我们注册2个错误处理的函数:
1 |
|
默认使用的是fernet.strict这种处理方案,也可以使用fallback模式。ok,我们现在感受一下:
1 |
|
好了,自定义的加解密方案完成了,整理全部的代码如下:
1 |
|
版权声明:本文由 董伟明 原创,未经作者授权禁止任何微信公众号和向掘金(juejin.im)转载,技术博客转载采用 保留署名-非商业性使用-禁止演绎 4.0-国际许可协议
python