A-A+

pyDes 实现 Python 版的 AES DES 对称加密/解密

2021年04月10日 23:57 汪洋大海 暂无评论 阅读 54 views 次

手头有个 Java 版的 DES 加密/解密程序,最近想着将其 Python 重构下,方便后续脚本解析,捣鼓了两下 pyDes 貌似很方便,不过据网上其他同学测试说 PyCrypto 性能要比 pyDes 高一个数量级,这里我没有做具体性能测试,也没有选用 PyCrypto 主要原因有三:

(1)PyCrypto 在 windows 下依赖 VC++9.0,安装麻烦

(2)PyCrypto 默认不支持 padmode,且对秘钥以及偏转向量长度有严格要求,扩展性很差

(3)不是用来搞暴力破解,性能要求不高,所以就不关注性能了,能用就行 ^ _ ^

下面直接上代码吧~

1、Java 版

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class EncryptHelper {
	private static String strKey = "test_KEY", strParam = "test__IV";
	public static String desEncrypt(String source) throws Exception {
		if (source == null || source.length() == 0)
			return null;
		Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
		DESKeySpec desKeySpec = new DESKeySpec(strKey.getBytes("UTF-8"));
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
		IvParameterSpec iv = new IvParameterSpec(strParam.getBytes("UTF-8"));
		cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
		return StringHelper.toHexString(
				cipher.doFinal(source.getBytes("UTF-8"))).toUpperCase();
	}
 
	public static String desDecrypt(String source) throws Exception {
		if (source == null || source.length() == 0)
			return null;
		byte[] src = StringHelper.fromHexString(source);
		Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
		DESKeySpec desKeySpec = new DESKeySpec(strKey.getBytes("UTF-8"));
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
		IvParameterSpec iv = new IvParameterSpec(strParam.getBytes("UTF-8"));
		cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
		byte[] retByte = cipher.doFinal(src);
		return new String(retByte);
	}
 
	public static void main(String[] args) throws Exception {
		System.out
		.println(EncryptHelper
				.desDecrypt("886f930f65f29132f6ace2683c448b5580d681a1fec3fc91cf3161f074b53b935d1c8fe80f99201077b36f923a42ac0e05cabe579308fda08d8ff463ad334677"));
		System.out.println(EncryptHelper.desEncrypt("https://mail.google.com/mail/u/0/#inbox/a1ed0e2f6f28e06b4361"));
	}
}
 
//结果:
//https://mail.google.com/mail/u/0/#inbox/a1ed0e2f6f28e06b4361
//886F930F65F29132F6ACE2683C448B5580D681A1FEC3FC91CF3161F074B53B935D1C8FE80F99201077B36F923A42AC0E05CABE579308FDA08D8FF463AD334677

 
 
2、Python 版
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# -*- coding:utf-8 -*-
import sys
 
reload(sys)
sys.setdefaultencoding('utf-8')
from pyDes import *
from binascii import b2a_hex, a2b_hex
 
# For Python3, you'll need to use bytes, i.e.:
#   data = b"Please encrypt my data"
#   k = des(b"DESCRYPT", CBC, b"\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
 
data = 'https://mail.google.com/mail/u/0/#inbox/a1ed0e2f6f28e06b4361'
KEY = "test_KEY"    #密钥
IV = "test__IV"     #偏转向量
# 使用DES对称加密算法的CBC模式加密
k = des(KEY, CBC, IV, pad=None, padmode=PAD_PKCS5)
d = k.encrypt(data)
print b2a_hex(d)
print "Decrypted: %r" % k.decrypt(d)
 
#结果:
#886f930f65f29132f6ace2683c448b5580d681a1fec3fc91cf3161f074b53b935d1c8fe80f99201077b36f923a42ac0e05cabe579308fda08d8ff463ad334677
#Decrypted: ' 
 
#或者单行命令如下:
python -c 'from pyDes import *;from binascii import a2b_hex;import sys;print des("test_KEY", CBC, "test__IV", pad=None, padmode=PAD_PKCS5).decrypt(a2b_hex(sys.stdin.readlines()[0].strip()))' <<<886f930f65f29132f6ace2683c448b5580d681a1fec3fc91cf3161f074b53b935d1c8fe80f99201077b36f923a42ac0e05cabe579308fda08d8ff463ad334677
#https://mail.google.com/mail/u/0/#inbox/a1ed0e2f6f28e06b4361

 
需要注意的是,DES 加密使用的密钥长度为 8 个字节,这也是我们将密钥变量设置为 8 个字符的原因。而我们需要加密的字符串的长度必须是 8 的倍数,所以我们创建了一个名为 pad 的函数,来给一个字符串末尾填充空格,直到它的长度是 8 的倍数。然后,我们创建了一个 DES 的实例,以及我们需要加密的文本。我们还创建了一个经过填充处理的文本。我们尝试着对未经填充处理的文本进行加密,啊欧,报了一个 ValueError 错误!我们需要对经过填充处理的文本进行加密,然后得到加密的字符串。(LCTT 译注:encrypt 函数的参数应为 byte 类型字符串,代码为:encrypted_text = des.encrypt(padded_text.encode('utf-8')))
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
########################################################################
# AES 版本:
########################################################################
 
from base64 import b64decode
from base64 import b64encode
 
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
# 解释Crypto模块怎么就这么"皮"?No module named "Crypto" 直接安装 pycryptodome 即可
# https://www.cnblogs.com/fawaikuangtu123/p/9761943.html
# Simple Python example of AES in CBC mode
# https://gist.github.com/forkd/168c9d74b988391e702aac5f4aa69e41
 
class AESCipher:
    def __init__(self, key):
        self.key = key[0:16].encode('utf-8')
        self.iv = key[-16:].encode('utf-8')
 
    def encrypt(self, data):
 
        self.cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        return b64encode(self.cipher.encrypt(pad(data.encode('utf-8'),
            AES.block_size)))
 
    def decrypt(self, data):
        raw = b64decode(data)
        self.cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        return unpad(self.cipher.decrypt(raw), AES.block_size)
 
if __name__ == '__main__':
    print('TESTING ENCRYPTION')
    msg = input('Message...: ')
    pwd = input('Password..: ')
    print('Ciphertext:', AESCipher(pwd).encrypt(msg).decode('utf-8'))
 
    print('\nTESTING DECRYPTION')
    cte = input('Ciphertext: ')
    pwd = input('Password..: ')
    print('Message...:', AESCipher(pwd).decrypt(cte).decode('utf-8'))

3、Refer
[1] pyDes库 实现python的des加密

pyDes库 实现python的des加密

[2] Cryptography and Python

http://lenciel.cn/2013/07/cryptography-and-python/

[3] 加密解密工具类 EncryptUtil

http://uule.iteye.com/blog/1925046

[4] implementing DES-X (mode CBC) using PyCrypto

https://gist.github.com/doublereedkurt/3921909

[5] python 对字符串的加密解密

python 对字符串的加密解密

[6] 数据加密算法

http://baike.baidu.com/view/878529.htm

[7] 非对称加密算法

http://baike.baidu.com/view/1490349.htm

[8] Pycrypto与RSA密码技术笔记

http://python.jobbole.com/84094/

文章来源:https://my.oschina.net/leejun2005/blog/586451

布施恩德可便相知重

微信扫一扫打赏

支付宝扫一扫打赏

×

给我留言