Python如何玩转加密?

发布于 2022-07-20 15:17:40
Python如何玩转加密?

查看更多

关注者
0
被浏览
981
5 个回答
laowang
laowang 2022-07-20
This guy hasn't written anything yet

Python支持加密的方式非常多,有许多现成的库和模块可以使用,下面我简单介绍几种常见的加密方式,感兴趣的朋友可以自己尝试一下,实验环境win10+python3.6,主要内容如下:

MD5加密

这是一种使用非常广泛的加密方式,不可逆的,在日常字符串加密中经常会用到,下面我简单介绍一下这种方式,主要用到Python自带的模块hashlib,测试代码如下,先创建一个md5对象,然后直接加密就行:

程序运行截图如下,已经成功进行md5加密:

哈希加密

这里以SHA1(安全哈希)为例,简单介绍一下Python是如何进行哈希加密的,也用到hashlib这个模块,测试代码如下,非常简单,先创建sha1对象,然后直接加密就行,这里也支持 SHA224,SHA256等加密方式:

程序运行截图如下,已经成功进行SHA1加密:

DES加密

这是一个分组加密算法,解密和加密是同一个算法,下面我简单介绍一下这种方式,主要用到pycryptodome这个模块,windows平台安装的话,直接在cmd窗口输入安装命令“pip install pycryptodomex”就行,测试代码如下,需要单独定义一个密钥:

程序运行截图如下,已经成功进行DES加密和解密:

AES加密

这也是一种广泛使用的加密方法,是对DES的改进和替代,下面我简单介绍一下这种方式,也用到pycryptodome这个模块,测试代码如下,稍微有些复杂:

程序运行截图如下,已经成功进行AES加密解密:

RSA加密

这是一种非对称加密算法,在公开密钥加密和电子商业中经常会用到,下面我简单介绍一下这种方式,主要用到rsa这个模块,安装的话,直接在cmd窗口输入安装命令“pip install rsa”就行,测试代码如下,需要单独定义一个公钥和私钥:

程序运行截图如下,已经成功进行rsa加密和解密:

至此,我们就完成了利用Python来进行加密。总的来说,整个过程不难,有现成的模块可以直接使用,只要你有一定的Python基础,熟悉一下上面的代码和示例,很快就能掌握的,当然,你也可以自己来实现加密算法,不过需要一定的数学基础,感兴趣的话,可以到网上搜一下相关教程,介绍的非常详细,希望以上分享的内容能对你有所帮助吧,也欢迎大家评论、留言进行补充。

ipython
ipython 2022-07-20
This guy hasn't written anything yet

一、生成公钥、私钥对

使用openssl工具生成RSA公钥、私钥对。

1.下载openssl工具。下载地址

2.打开 openssl 文件夹下的 bin 文件夹,执行 openssl.exe 文件;

3.生成RSA私钥命令:

这里生成的密钥文件是2048比特。

genrsa -out rsa_private_key.pem 2048

4.生成RSA公钥命令:

注意,公钥和私钥是成对的,所以你在生成一个后,另一个的生成是基于前一个的文件名,否则生成的不是一对哦!!

rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

生成后的文件应该在你的用户目录下,或者在openssl的bin文件夹下(有时候在有时又不在,真是搞不懂,反正你就在这两个地方都找一下,肯定在的)。

5.这里介绍一下RSA密钥文件的规律,文件名都是以.pem为后缀,生成的RSA密钥,可以看到都是

以-----BEGIN RSA PRIVATE KEY-----开头,-----END RSA PRIVATE KEY-----结尾的没有换行的字符串,这个就是原始的 RSA 私钥。

二、安装python支持的加密库—pycryptodome

我用的python3.6版本,网上搜了一下,在python3.6之前的版本大部分是用pycrypto来进行加密的,而在python3.6之后,因无人维护pycrypto,所以改名为pycryptodome,这个库的强大之处在于,他是pycrypto库的扩展,用起来更加方便,更灵活啊~~功能杠杠滴

1.安装pycryptodome

如果你安装了pip,那么就很简单了。

pip3 install pycryptodome

2.将密钥文件导入到程序中。

from Crypto.PublicKey import RSA

# 读取标准的rsa公私钥pem文件

def load_rsa_file(fn):

key = None

try:

key = RSA.importKey(open(fn).read())

except Exception as err:

print('导入rsa的KEY文件出错', fn, err)

return key

# 标准字符串密钥转rsa格式密钥

def rsa_key_str2std(skey):

ret = None

try:

ret = RSA.importKey(skey)

except Exception as err:

print('字符串密钥转rsa格式密钥错误', skey, err)

return ret

3.RSA加密

from Crypto.Cipher import PKCS1_OAEP

# RSA_加密

def rsa_enc(data, rsa_key):

ciphertext = b''

try:

cipher = PKCS1_OAEP.new(rsa_key)

ciphertext = cipher.encrypt(data)

except Exception as err:

print('RSA加密失败', '', err)

return ciphertext

由于RSA在加密过程中,每次加密只能加密最大长度的字符串,如果你的加密数据超长,在加密过程中需要分段加密,同理,解密也是分段解密的。

1024位的证书,加密时最大支持117个字节,解密时为128;

2048位的证书,加密时最大支持245个字节,解密时为256。

加密时支持的最大字节数:证书位数/8 -11(比如:2048位的证书,支持的最大加密字节数:2048/8 - 11 = 245)

其中,11位字节为保留字节。

上面我的密钥文件是2048比特,所以加密分块长度为245字节。

4.加密分块

# 根据key长度计算分块大小

def get_block_size(rsa_key):

try:

# RSA仅支持限定长度内的数据的加解密,需要分块

# 分块大小block_reversed_size=11

reserve_size = block_reversed_size

key_size = rsa_key.size_in_bits()

if (key_size % 8) != 0:

raise RuntimeError('RSA 密钥长度非法')

# 密钥用来解密,解密不需要预留长度

if rsa_key.has_private():

reserve_size = 0

bs = int(key_size / 8) - reserve_size

except Exception as err:

print('计算加解密数据块大小出错', rsa_key, err)

return bs

# 返回块数据

def block_data(data, rsa_key):

bs = get_block_size(rsa_key)

for i in range(0, len(data), bs):

yield data[i:i + bs]

RSA在解密分段时与加密时用的分段大小无关,都是按照密钥长度/8来分段解密的。

5.RSA解密

from Crypto.Cipher import PKCS1_OAEP

# RSA解密

def rsa_dec(data, rsa_key):

ret_data = b''

try:

cipher = PKCS1_OAEP.new(rsa_key)

ret_data = cipher.decrypt(data)

except Exception as err:

print('RSA解密失败', '', err)

return ret_data

6.RSA签名

from Crypto.Signature import pkcs1_15

from Crypto.Hash import SHA256

# RSA签名

def rsa_sign(data, rsa_key):

signature = ''

try:

h = SHA256.new(data)

signature = pkcs1_15.new(rsa_key).sign(h)

except Exception as err:

print('RSA签名失败', '', err)

return signature

7.RSA验签名

# RSA签名验证

def rsa_sign_verify(data, sig, rsa_key):

try:

h = SHA256.new(data)

pkcs1_15.new(rsa_key).verify(h, sig)

ret = True

except (ValueError, TypeError):

ret = False

return ret

8.RSA加解密类(我将RSA加解密封装成一个类,方便后续直接调用),完整代码如下:

# -*- coding: utf-8 -*-

import Crypto.Cipher as Cipher

import Crypto.Signature as Sign

import Crypto.Hash as Hash

from Crypto.PublicKey import RSA

from Crypto.Cipher import PKCS1_v1_5 as PKCS1_v1_5_cipper

from Crypto.Signature import PKCS1_v1_5 as PKCS1_v1_5_sign

from Crypto.Hash import SHA1

class Rsa:

'''RSA加解密签名类

'''

def __int__(self, ciper_lib=PKCS1_v1_5_cipper, sign_lib=PKCS1_v1_5_sign, hash_lib=SHA1,

pub_file=None, pri_file=None, pub_skey=None, pri_skey=None, pub_key=None, pri_key=None,

reversed_size=11):

# 加解密库

self.ciper_lib = ciper_lib

self.sign_lib = sign_lib

self.hash_lib = hash_lib

# 公钥密钥

if pub_key:

self.pub_key = pub_key

elif pub_skey:

self.pub_key = RSA.importKey(pub_skey)

elif pub_file:

self.pub_key = RSA.importKey(open(pub_file).read())

if pri_key:

self.pri_key = pri_key

elif pri_skey:

self.pri_key = RSA.importKey(pri_skey)

elif pri_file:

self.pri_key = RSA.importKey(open(pri_file).read())

# 分块保留长度

self.block_reversed_size = reversed_size

# 根据key长度计算分块大小

def get_block_size(self, rsa_key):

try:

# RSA仅支持限定长度内的数据的加解密,需要分块

# 分块大小

reserve_size = self.block_reversed_size

key_size = rsa_key.size_in_bits()

if (key_size % 8) != 0:

raise RuntimeError('RSA 密钥长度非法')

# 密钥用来解密,解密不需要预留长度

if rsa_key.has_private():

reserve_size = 0

bs = int(key_size / 8) - reserve_size

except Exception as err:

print('计算加解密数据块大小出错', rsa_key, err)

return bs

# 返回块数据

def block_data(self, data, rsa_key):

bs = self.get_block_size(rsa_key)

for i in range(0, len(data), bs):

yield data[i:i + bs]

# 加密

def enc_bytes(self, data, key=None):

text = b''

try:

rsa_key = self.pub_key

if key:

rsa_key = key

cipher = self.ciper_lib.new(rsa_key)

for dat in self.block_data(data, rsa_key):

cur_text = cipher.encrypt(dat)

text += cur_text

except Exception as err:

print('RSA加密失败', data, err)

return text

# 解密

def dec_bytes(self, data, key=None):

text = b''

try:

rsa_key = self.pri_key

if key:

rsa_key = key

cipher = self.ciper_lib.new(rsa_key)

for dat in self.block_data(data, rsa_key):

if type(self.ciper_lib) == Cipher.PKCS1_OAEP:

cur_text = cipher.decrypt(dat)

else:

cur_text = cipher.decrypt(dat, '解密异常')

text += cur_text

except Exception as err:

print('RSA解密失败', data, err)

return text

# RSA签名

def sign_bytes(self, data, key=None):

signature = ''

try:

rsa_key = self.pri_key

if key:

rsa_key = key

h = self.hash_lib.new(data)

signature = self.sign_lib.new(rsa_key).sign(h)

except Exception as err:

print('RSA签名失败', '', err)

return signature

# RSA签名验证

def sign_verify(self, data, sig, key=None):

try:

rsa_key = self.pub_key

if key:

rsa_key = key

h = self.hash_lib.new(data)

self.sign_lib.new(rsa_key).verify(h, sig)

ret = True

except (ValueError, TypeError):

ret = False

return ret

def main():

pass

if __name__ == '__main__':

main()

laowang
laowang 2022-07-20
This guy hasn't written anything yet
Python配置文件配置数据库,中间件敏感信息,还是加个密进行读取,稳当点。


平时都习惯配置文件直接配置,但是部署服务器可能还是不太安全,于是乎,简单做了下密钥变量加密,程序运行的时候读取一下环境变量,进行解密配置文件。因为不想设置变量被记录,又稍微临时设置了下系统。


为了防止日志里打印敏感信息,又去掉了日志的打印。


不想大改造,就这种折衷方式先看看效果,折腾中不断改进。
laowang
laowang 2022-07-20
This guy hasn't written anything yet
Python给了想要了解编程的编程爱好者一个好的入门方式,Python编的基本上是自动化脚本,大都是给自己用的,工具自造自用,并且拥有很多第三方库。

脚本语言适合个体户自用,写个闹铃、写个一键删除文件,不用的时候就把脚本删了,很方便。而编译的话中间文件就搞的很麻烦了。只是因为是小任务,运行速度上差别也很难被看出来。

python无法加密或者是加密困难,于是卖软件的企业基本上就不需要这个了。除非内勤自己玩。或者合同里写明了提高全套源代码。PY适合小工具,大了就是噩梦!
laowang
laowang 2022-07-20
This guy hasn't written anything yet
为什么Python开发者写GUI不用Tkinter,而要选择PyQt?Python写的gui,受限于py本身源码加密困难,以及性能问题,一般都是内部中小型专用软件。

而py商用桌面软件反正我是一个都没见过。pyqt协议许可比Python宽松,可以商用闭源。QSS是难点,PYQT很人性化,不用designer都可以很快地完成界面,就是做好看的样式比较麻烦。另外pyinstaller打包出来四五十兆 ,采用精简pyqt库的话只要十几兆。

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览