密码与通信

密码技术是一门历史悠久的技术。信息传播离不开加密与解密。密码技术的用途主要源于两个方面,加密/解密和签名/验签

python中的加密库hashlib与pycrypto

Python的hashlib提供了常用的摘要算法,比如md5, sha1, sha224, sha256, sha384, sha512等。
摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。
摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。
而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。常见的摘要算法MD5.

摘要算法应用

  1. 存储用户登录的用户名和口令时, 存储用户口令的摘要
  2. 对配置文件某些配置生成签名,防止篡改
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import hashlib
def getHash(file_path):
f = open(file_path, "rb") #以二进制读模式打开
line = f.readline()
hash = hashlib.md5()
while(line):
hash.update(line.encode('utf8'))
line = f.readline()
f.close()
return hash.hexdigest()
def IsHashEqual(file_path1, file_path2):
str1 = getHash(file_path1)
str2 = getHash(file_path2)
return str1 == str2
if __name__ == '__main__':
if IsHashEqual("E:\\GIT\\1.txt", "E:\\GIT\\2.txt"):
print "文件内容相同!"
else:
print "文件内容不同!"
# 例子: 对配置文件中配置选项进行加密, 这里加密的不一定非得是文件,或者文件中某一个字符串, 也可以是你组合生成的字符串,但是
# 组合生成的字符串格式内容是固定的.
# 自动记录设备hash值
def _record_device_hash(device_ini_path, base_ini_path):
ini = load_config(device_ini_path)
if not ini.has_section('DeviceSignature'):
ini.add_section('DeviceSignature')
ini.write(open(device_ini_path, "w", encoding="utf-8"))
device_hash = _get_device_hash(device_ini_path, base_ini_path)
write_config(device_ini_path, "DeviceSignature", "signature", device_hash)
# 配置文件配置选项签名,防篡改
# 获取设备信息的hash值
def _get_device_hash():
import hashlib
axis_cards = _get_axiscards()
ini = basic.sysData("ini/base.ini")
manufacturer = ini['sys']['manufacturer']
axis_cards.append(manufacturer)
model = ini['sys']['model']
axis_cards.append(model)
secret_key = 'you never guess'
axis_cards.append(secret_key)
devices_str = ','.join(axis_cards)
device_hash = hashlib.md5()
device_hash.update(devices_str.encode('utf-8'))
return device_hash.hexdigest()
# 判断hash值是否相等
def _is_hash_equal():
hash1 = _get_device_hash()
ini = basic.sysData("ini/device.ini")
if ini.has_option('DeviceSignature', 'signature'):
hash2 = ini['DeviceSignature']['signature']
if hash2 is None:
return False
return hash1 == hash2
else:
return False

关于pycrypto加密

PyCrypto是一个免费的加密算法库,支持常见的DES、AES加密以及MD5、SHA各种HASH运算.

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
41
42
43
44
45
46
47
48
49
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
class Mycrypto():
def __init__(self, key='keyskeyskeyskeys', iv = 'keyskeyskeyskeys'):
self.key = key
# iv 长度必须是16字节, iv可以与key不一样
self.iv = iv
self.mode = AES.MODE_CBC
# 加密函数,如果text不是16的倍数【加密文本text必须为16的倍数!】,那就补足为16的倍数
def encrypt(self, text):
cryptor = AES.new(self.key, self.mode, self.iv)
# 这里密钥key 长度必须为16(AES-128)、24(AES-192)、或32(AES-256)Bytes 长度.目前AES-128足够用
my_add = 16 - (len(text) % 16)
text = text + ('\0' * my_add)
self.ciphertext = cryptor.encrypt(text)
# 因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
# 所以这里统一把加密后的字符串转化为16进制字符串
return b2a_hex(self.ciphertext)
# 解密后,去掉补足的空格用strip() 去掉
def decrypt(self, text):
cryptor = AES.new(self.key, self.mode, self.iv)
plain_text = cryptor.decrypt(a2b_hex(text))
return plain_text.decode('utf-8').rstrip('\0')
# 创建加密对象
mycrypto = Mycrypto()
# 加密信息
device_ini_path = os.path.join(sysDir, "ini", "device.ini")
device_info = load_config(device_ini_path)
if device_info.has_section("DeviceDetail"):
for k, v in device_info["DeviceDetail"].items():
encrypt_text = mycrypto.encrypt(v)
print("encrypt_text = {}".format(encrypt_text))
write_config(device_ini_path, "DeviceDetail", k, str(encrypt_text)[2:-1])
# 获取解密后的配置信息
def _get_axiscards_decrypto_config():
import mycrypto
mycrypto_ = mycrypto.Mycrypto()
axiscards_detail = {}
ini = basic.sysData("ini/device.ini")
for k, v in ini["DeviceDetail"].items():
plain_text = mycrypto_.decrypt(v)
print("plain_text = {}".format(plain_text))
axiscards_detail[k] = int(plain_text)
return axiscards_detail