本章介绍 python 中用于加密和解密信息的主要模块,如 pycrypto 和 cryptography。此外,我们还介绍了隐写术技术以及如何使用stepic
模块在图像中隐藏信息。
本章将介绍以下主题:
pycrypto
信息加解密模块cryptography
信息加解密模块- 图像信息隐藏的主要隐写技术
- 如何使用
stepic
模块隐藏图像中的信息
本章的示例和源代码可在 GitHub 存储库的chapter13
文件夹中找到 https://github.com/PacktPublishing/Mastering-Python-for-Networking-and-Security 。
您需要在本地计算机上安装至少有 4GB 内存的 python 发行版。
在本节中,我们将回顾加密算法和用于加密和解密数据的pycrypto
模块。
密码学可以定义为隐藏信息的实践,包括消息完整性检查、发送方/接收方身份验证和数字签名技术。
以下是四种最常见的加密算法:
- **散列函数:**也称为单向加密,没有密钥。
hash
函数为明文输入输出固定长度的哈希值,理论上无法恢复明文的长度或内容。单向cryptographic
功能在网站中用于以无法检索的方式存储密码。 - **键控哈希函数:**用于构建消息认证码(MAC);Mac 旨在防止暴力攻击。因此,它们被有意设计为缓慢。
- **对称加密:**使用可变密钥为某些文本输入输出密文,我们可以使用相同的密钥对密文进行解密。加密和解密使用相同密钥的算法称为对称密钥算法。
- **公钥算法:**对于公钥算法,我们有两个不同的密钥:一个用于加密,另一个用于解密。这种做法使用一对密钥:一个用于加密,另一个用于解密。这项技术的用户发布他们的公钥,同时对他们的私钥保密。这使任何人都可以向他们发送一条用公钥加密的消息,只有私钥持有者才能解密。这些算法的设计使得即使攻击者知道相应的公钥,也很难找到私钥。
例如,对于散列函数,Python 提供了一些模块,例如hashlib
。
下面的脚本返回文件的md5
校验和。
您可以在hashlib
文件夹内的md5.py
文件中找到以下代码:
import hashlib
def md5Checksum(filePath):
fh = open(filePath, 'rb')
m = hashlib.md5()
while True:
data = fh.read(8192)
if not data:
break
m.update(data)
return m.hexdigest()
print('The MD5 checksum is', md5Checksum('md5.py'))
上一个脚本的输出为:
The MD5 checksum is 8eec2037fe92612b9a141a45b60bec26
说到用 Python 加密信息,我们有一些选择,但最可靠的是 PyCrypto 加密库,它支持块加密、流加密和散列计算功能。
PyCrypto
模块提供了在 Python 程序中实现强加密所需的所有函数,包括哈希函数和加密算法。
例如,pycrypto
支持的分组密码为:
- AES
- ARC2
- 河豚
- 铸造
- DES
- DES3
- 主意
- RC5
通常,所有这些密码都以相同的方式使用。
我们可以使用Crypto.Cipher
包导入特定的密码类型:
from Crypto.Cipher import [Chiper_Type]
我们可以使用新的方法构造函数初始化密码:
new ([key], [mode], [Vector IV])
使用这种方法,只有密钥是必需的,我们必须考虑加密类型是否要求它具有特定的大小。可能的模式有MODE_ECB
、MODE_CBC
、MODE_CFB
、MODE_PGP
、MODE_OFB
、MODE_CTR
和MODE_OPENPGP
。
如果使用MODE_CBC
或MODE_CFB
模式,则必须初始化第三个参数(向量 IV),这允许为密码提供初始值。某些密码可能具有可选参数,例如 AES,它可以使用block_size
和key_size
参数指定块和密钥大小。
与 hashlib 相同,pycrypto
也支持 hash 函数。一般哈希函数与pycrypto
的用法类似:
- 我们可以使用**
Crypto.Hash
包导入特定的哈希类型:from Crypto.Hash import [Hash Type]
** *** 我们可以使用更新方法设置需要获取哈希的数据:update('data')
*** 我们可以使用hexdigest()
方法生成哈希:hexdigest()
****
****下面是我们在获取文件校验和时看到的相同示例,在本例中,我们使用pycrypt
而不是hashlib
。
您可以在pycrypto
文件夹内的hash.py
文件中找到以下代码:
from Crypto.Hash import MD5
def md5Checksum(filePath):
fh = open(filePath, 'rb')
m = MD5.new()
while True:
data = fh.read(8192)
if not data:
break
m.update(data)
return m.hexdigest()
print('The MD5 checksum is' + md5Checksum('hash.py'))
要加密和解密数据,我们可以使用**encrypt**
和**decrypt**
函数:
encrypt ('clear text')
decrypt ('encrypted text')
DES 是一种分组密码,这意味着要加密的文本是 8 的倍数,因此我在文本末尾添加了空格。当我破译它的时候,我把它们去掉了。
下面的脚本对用户和密码进行加密,最后模拟是服务器接收到这些凭据,解密并显示这些数据。
您可以在pycrypto
文件夹内的Encrypt_decrypt_DES.py
文件中找到以下代码:
from Crypto.Cipher import DES
# How we use DES, the blocks are 8 characters
# Fill with spaces the user until 8 characters
user = "user "
password = "password"
# we create the cipher with DES
cipher = DES.new('mycipher')
# encrypt username and password
cipher_user = cipher.encrypt(user)
cipher_password = cipher.encrypt(password)
# we send credentials
print("User: " + cipher_user)
print("Password: " + cipher_password)
# We simulate the server where the messages arrive encrypted.
# we decode messages and remove spaces with strip()
cipher = DES.new('mycipher')
decipher_user = cipher.decrypt(cipher_user).strip()
decipher_password = cipher.decrypt(cipher_password)
print("SERVER decipher:")
print("User: " + decipher_user)
print("Password: " + decipher_password)
该程序使用 DES 对数据进行加密,因此它要做的第一件事是导入DES
模块并使用以下指令创建编码器:
cipher = DES.new('mycipher')
“mycipher
”参数值是加密密钥。正如您在示例程序中看到的,一旦创建了密码,加密和解密就相当简单了。
AES 加密需要一个强密钥。密钥越强,您的加密越强。我们的 AES 密钥需要 16、24 或 32 字节长,我们的初始化向量需要16 字节长。这将使用random
和string
模块生成。
要使用 AES 等加密算法,我们可以从**Crypto.Cipher.AES
**包中导入。由于 PyCrypto 块级加密 API 的级别非常低,因此它分别只接受 AES-128、AES-196 和 AES-256 的 16、24 或 32 字节长的密钥。密钥越长,加密越强。
此外,对于使用 pycrypto 的 AES 加密,您需要确保数据长度为 16 字节的倍数。如果缓冲区不是,则填充缓冲区,并在输出的开头包含数据的大小,以便接收器可以正确解密。
您可以在pycrypto
文件夹内的Encrypt_decrypt_AES.py
文件中找到以下代码:
# AES pycrypto package
from Crypto.Cipher import AES
# key has to be 16, 24 or 32 bytes long
encrypt_AES = AES.new('secret-key-12345', AES.MODE_CBC, 'This is an IV-12')
# Fill with spaces the user until 32 characters
message = "This is the secret message "
ciphertext = encrypt_AES.encrypt(message)
print("Cipher text: " , ciphertext)
# key must be identical
decrypt_AES = AES.new('secret-key-12345', AES.MODE_CBC, 'This is an IV-12')
message_decrypted = decrypt_AES.decrypt(ciphertext)
print("Decrypted text: ", message_decrypted.strip())
上一个脚本的输出为:
('Cipher text: ', '\xf2\xda\x92:\xc0\xb8\xd8PX\xc1\x07\xc2\xad"\xe4\x12\x16\x1e)(\xf4\xae\xdeW\xaf_\x9d\xbd\xf4\xc3\x87\xc4')
('Decrypted text: ', 'This is the secret message')
AES 加密要求写入的每个块的大小为 16 字节的倍数。因此,我们以块的形式读取、加密和写入数据。区块大小必须是 16 的倍数。
以下脚本加密参数提供的文件。
您可以在pycrypto
文件夹内的aes-file-encrypt.py
文件中找到以下代码:
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
import os, random, struct
def encrypt_file(key, filename):
chunk_size = 64*1024
output_filename = filename + '.encrypted'
# Initialization vector
iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
#create the encryption cipher
encryptor = AES.new(key, AES.MODE_CBC, iv)
#Determine the size of the file
filesize = os.path.getsize(filename)
#Open the output file and write the size of the file.
#We use the struct package for the purpose.
with open(filename, 'rb') as inputfile:
with open(output_filename, 'wb') as outputfile:
outputfile.write(struct.pack('<Q', filesize))
outputfile.write(iv)
while True:
chunk = inputfile.read(chunk_size)
if len(chunk) == 0:
break
elif len(chunk) % 16 != 0:
chunk += ' ' * (16 - len(chunk) % 16)
outputfile.write(encryptor.encrypt(chunk))
password = "password"
def getKey(password):
hasher = SHA256.new(password)
return hasher.digest()
encrypt_file(getKey(password), 'file.txt');
上一个脚本的输出是一个名为file.txt.encrypted
的文件,其中包含与原始文件相同的内容,但信息不清晰。
前面的脚本的工作方式是,首先加载所有必需的模块并定义加密文件的函数:
from Crypto.Cipher import AES
import os, random, struct
def encrypt_file(key, filename, chunk_size=64*1024):
output_filename = filename + '.encrypted'
此外,我们还需要获得初始化向量。需要一个 16 字节的初始化向量,其生成如下:
# Initialization vector
iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
然后我们可以在PyCrypto
模块中初始化 AES 加密方法:
encryptor = AES.new(key, AES.MODE_CBC, iv)
filesize = os.path.getsize(filename)
对于解密,我们需要反转前面的过程,使用 AES 对文件进行解密
您可以在pycrypto
文件夹中的**aes-file-decrypt.py
**文件中找到以下代码:
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
import os, random, struct
def decrypt_file(key, filename):
chunk_size = 64*1024
output_filename = os.path.splitext(filename)[0]
#open the encrypted file and read the file size and the initialization vector.
#The IV is required for creating the cipher.
with open(filename, 'rb') as infile:
origsize = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0]
iv = infile.read(16)
#create the cipher using the key and the IV.
decryptor = AES.new(key, AES.MODE_CBC, iv)
#We also write the decrypted data to a verification file,
#so we can check the results of the encryption
#and decryption by comparing with the original file.
with open(output_filename, 'wb') as outfile:
while True:
chunk = infile.read(chunk_size)
if len(chunk) == 0:
break
outfile.write(decryptor.decrypt(chunk))
outfile.truncate(origsize)
password = "password"
def getKey(password):
hasher = SHA256.new(password)
return hasher.digest()
decrypt_file(getKey(password), 'file.txt.encrypted');
在本节中,我们将回顾用于加密和解密数据的cryptography
模块。Cryptography
是一个较新的模块,它比pycrypto
具有更好的性能和安全性。
pypi
存储库中提供了加密技术,您可以使用pip install cryptography
命令进行安装。
在中 https://pypi.org/project/cryptography URL,我们可以看到此模块的最新版本。
For more information about installation and supported platforms, check out https://cryptography.io/en/latest/installation/.
密码学包括普通密码算法的高级和低级接口,如对称密码、消息摘要和密钥派生函数。例如,我们可以对fernet
包使用对称加密。
Fernet 是对称加密的一种实现,它保证在没有密钥的情况下无法操作或读取加密消息。
为了生成密钥,我们可以从Fernet
接口使用generate_key()
方法。
您可以在加密文件夹中的**encrypt_decrypt.py
文件中找到以下代码:**
**```py from cryptography.fernet import Fernet
key = Fernet.generate_key() cipher_suite = Fernet(key)
print("Key "+str(cipher_suite)) message = "Secret message"
cipher_text = cipher_suite.encrypt(message) plain_text = cipher_suite.decrypt(cipher_text)
print("\n\nCipher text: "+cipher_text)
print("\n\nPlain text: "+plain_text)
这是上一个脚本的输出:
![](img/8ff216ff-69d5-4ad1-be86-befeb736603c.png)
# 在 fernet 软件包中使用密码
可以将密码与 Fernet 一起使用。为此,您需要通过密钥派生函数运行密码,例如**PBKDF2HMAC。**
**PBKDF2(基于密码的密钥派生函数 2)**通常用于从密码派生加密密钥。
More information about key derivation functions can be found at [https://cryptography.io/en/latest/hazmat/primitives/key-derivation-functions/](https://cryptography.io/en/latest/hazmat/primitives/key-derivation-functions/).
在本例中,我们使用此函数从密码生成密钥,并使用该密钥创建用于加密和解密数据的 Fernet 对象。在本例中,要加密的数据是一个简单的消息字符串。我们可以使用`verify()`方法,该方法检查从提供的密钥派生新密钥是否会生成与预期的 _ 密钥相同的密钥。
您可以在加密文件夹中的**`encrypt_decrypt_kdf.py`文件中找到以下代码:**
**```py
import base64
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
password = "password"
salt = os.urandom(16)
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),length=32,salt=salt,iterations=100000,backend=default_backend())
key = kdf.derive(password)
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),length=32,salt=salt,iterations=100000,backend=default_backend())
#verify() method checks whether deriving a new key from
#the supplied key generates the same key as the expected_key,
#and raises an exception if they do not match.
kdf.verify(password, key)
key = base64.urlsafe_b64encode(key)
fernet = Fernet(key)
token = fernet.encrypt("Secret message")
print("Token: "+token)
print("Message: "+fernet.decrypt(token))
这是上一个脚本的输出:
如果我们使用verify()
方法验证密钥,并且在验证过程中检查密钥不匹配,则会启动cryptography.exceptions.InvalidKey
异常:
来自cryptography
模块的密码包提供了一个对称加密类**cryptography.hazmat.primitives.ciphers.Cipher
类。**
**密码对象将算法(如 AES)与模式(如 CBC 或 CTR)相结合。
在下面的脚本中,我们可以看到一个使用 AES 加密然后解密内容的示例。
您可以在加密文件夹中的encrypt_decrypt_AES.py
文件中找到以下代码:
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
backend = default_backend()
key = os.urandom(32)
iv = os.urandom(16)
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
encryptor = cipher.encryptor()
print(encryptor)
message_encrypted = encryptor.update("a secret message")
print("\n\nCipher text: "+message_encrypted)
ct = message_encrypted + encryptor.finalize()
decryptor = cipher.decryptor()
print("\n\nPlain text: "+decryptor.update(ct))
这是上一个脚本的输出:
在本节中,我们将回顾隐写术技术和 stepic 作为在图像中隐藏信息的python
模块。
隐写术(http://en.wikipedia.org/wiki/Steganography 是密码学的一个特殊分支,它允许我们将秘密信息隐藏到公共信息中,也就是说,隐藏到明显无害的信息中。
隐藏信息的主要技术之一是使用最低有效位(LSB)。
当通过图像的每个像素时,我们得到一个由(0)到(255)的整数组成的 RGB 三元组,由于每个数字都有自己的二进制表示形式,我们将该三元组转换为其等价的二进制表示形式;例如,由(148、28、202)形成的像素是二进制的,相当于(100101001001110011001010)。
目标是编辑最低有效位,即最后一个到右边的位。在下面的 LSB 列中,我们更改了位(红色),但其余的位仍然保持不变,RGB 三元组的结果经历了一些更改,但它们是最小的。如果仔细地将它们设置为两种颜色,它们不太可能发现任何视觉上的差异,但实际上发生了变化,在改变最低有效位后,RGB 三元组与我们开始时的不同,但颜色显然是相同的。
我们可以更改信息并发送,而攻击者不会意识到有什么奇怪的东西。
一切都是 1 和 0,我们可以让 LSB 遵循我们想要的顺序,例如,如果我们想隐藏单词“Hacking”,我们必须记住每个字母(字符)都可以用一个字节表示,即“H”=01001000,因此如果我们有 3 个像素,我们可以使用 LSB 隐藏该序列。
在这幅图中,我们可以看到“H”字母以二进制和 LSB 格式表示:
因为每个像素有三个值这就构成了它,在每一个字母中我们只能改变一位,那么隐藏字母“H”需要三个像素,因为它的二进制表示对应于八位。上表非常直观;为了得到原始图像的三个像素,我们取出它们各自的 RGB,因为我们想在二进制中隐藏字母“H”,我们只需按“H”的顺序替换最低有效位。然后我们回去重建三个像素,只是现在我们在其中隐藏了字母,它们的值已经发生了变化,但肉眼看不到变化。
这样,我们不仅可以隐藏文本,还可以隐藏各种信息,因为一切都可以用二进制值表示;恢复信息的方法就是接收修改后的图像并开始读取最低有效位,因为每八位,我们就有一个字符的表示。
在下一个脚本中,我们将用 python 实现这项技术。
您可以在隐写术文件夹中的steganography_LSB.py
文件中找到以下代码
首先,我们定义 get 函数,设置最低有效位(LSB)**,并设置读取图像并访问每个像素对 LSB 的extract_message()
方法:
#!/usr/bin/env python
#Hide data in lsbs of an image
#python 3.x compatible
from PIL import Image
def get_pixel_pairs(iterable):
a = iter(iterable)
return zip(a, a)
def set_LSB(value, bit):
if bit == '0':
value = value & 254
else:
value = value | 1
return value
def get_LSB(value):
if value & 1 == 0:
return '0'
else:
return '1'
def extract_message(image):
c_image = Image.open(image)
pixel_list = list(c_image.getdata())
message = ""
for pix1, pix2 in get_pixel_pairs(pixel_list):
message_byte = "0b"
for p in pix1:
message_byte += get_LSB(p)
for p in pix2:
message_byte += get_LSB(p)
if message_byte == "0b00000000":
break
message += chr(int(message_byte,2))
return message
现在,我们定义了我们的hide_message
方法,该方法读取图像并使用每个像素的 LSB 隐藏图像中的消息:
def hide_message(image, message, outfile):
message += chr(0)
c_image = Image.open(image)
c_image = c_image.convert('RGBA')
out = Image.new(c_image.mode, c_image.size)
width, height = c_image.size
pixList = list(c_image.getdata())
newArray = []
for i in range(len(message)):
charInt = ord(message[i])
cb = str(bin(charInt))[2:].zfill(8)
pix1 = pixList[i*2]
pix2 = pixList[(i*2)+1]
newpix1 = []
newpix2 = []
for j in range(0,4):
newpix1.append(set_LSB(pix1[j], cb[j]))
newpix2.append(set_LSB(pix2[j], cb[j+4]))
newArray.append(tuple(newpix1))
newArray.append(tuple(newpix2))
newArray.extend(pixList[len(message)*2:])
out.putdata(newArray)
out.save(outfile)
return outfile
if __name__ == "__main__":
print("Testing hide message in python_secrets.png with LSB ...")
print(hide_message('python.png', 'Hidden message', 'python_secrets.png'))
print("Hide test passed, testing message extraction ...")
print(extract_message('python_secrets.png'))
Stepic 提供了一个Python
模块和一个命令行界面,用于隐藏图像中的任意数据。它稍微修改图像中像素的颜色以存储数据。
要设置 stepic,只需使用pip install stepic
命令安装即可。
Stepic 的Steganographer
类是模块的主要类,在这里我们可以看到可用于编码和解码图像中数据的方法:
在下面与 python 2.x 版兼容的脚本中,我们可以看到这些函数的实现。
您可以在steganography
文件夹内的**stepic.py**
文件中找到以下代码:****
****```py
'''Python image steganography Stepic hides arbitrary data inside PIL images. Stepic uses the Python Image Library (apt: python-imaging, web: http://www.pythonware.com/products/pil/). ''' from PIL import Image
def _validate_image(image): if image.mode not in ('RGB', 'RGBA', 'CMYK'): raise ValueError('Unsupported pixel format: ''image must be RGB, RGBA, or CMYK') if image.format == 'JPEG': raise ValueError('JPEG format incompatible with steganography')
在这部分代码中,我们可以看到与使用 LSB 对图像中的数据进行编码相关的方法。
Stepic 从顶部开始从左到右读取图像像素。每个像素由 0 到 255 之间的三个整数组成,第一个提供红色分量,第二个提供绿色分量,第三个提供蓝色分量。它一次读取三个像素,每个像素包含三个值:红色、绿色和蓝色。每组像素有九个值。一个字节的数据有八位,因此如果每种颜色都可以稍微修改,通过将最低有效位设置为零或一,这三个像素可以存储一个字节,剩下一个颜色值:
```py
def encode_imdata(imdata, data):
'''given a sequence of pixels, returns an iterator of pixels with encoded data'''
datalen = len(data)
if datalen == 0:
raise ValueError('data is empty')
if datalen * 3 > len(imdata):
raise ValueError('data is too large for image')
imdata = iter(imdata)
for i in xrange(datalen):
pixels = [value & ~1 for value in
imdata.next()[:3] + imdata.next()[:3] + imdata.next()[:3]]
byte = ord(data[i])
for j in xrange(7, -1, -1):
pixels[j] |= byte & 1
byte >>= 1
if i == datalen - 1:
pixels[-1] |= 1
pixels = tuple(pixels)
yield pixels[0:3]
yield pixels[3:6]
yield pixels[6:9]
def encode_inplace(image, data):
'''hides data in an image'''
_validate_image(image)
w = image.size[0]
(x, y) = (0, 0)
for pixel in encode_imdata(image.getdata(), data):
image.putpixel((x, y), pixel)
if x == w - 1:
x = 0
y += 1
else:
x += 1
def encode(image, data):
'''generates an image with hidden data, starting with an existing
image and arbitrary data'''
image = image.copy()
encode_inplace(image, data)
return image
在这部分代码中,我们可以看到使用 LSB 对图像中的数据进行解码的相关方法。基本上,给定图像中的像素序列,它返回图像中编码字符的迭代器:
def decode_imdata(imdata):
'''Given a sequence of pixels, returns an iterator of characters
encoded in the image'''
imdata = iter(imdata)
while True:
pixels = list(imdata.next()[:3] + imdata.next()[:3] + imdata.next()[:3])
byte = 0
for c in xrange(7):
byte |= pixels[c] & 1
byte <<= 1
byte |= pixels[7] & 1
yield chr(byte)
if pixels[-1] & 1:
break
def decode(image):
'''extracts data from an image'''
_validate_image(image)
return ''.join(decode_imdata(image.getdata()))
Stepic 使用最低有效位(http://en.wikipedia.org/wiki/Least_significant_bit 此剩余值的)表示数据的结束。编码方案不提供图像是否包含数据的线索,因此 Stepic 将始终从任何图像中提取至少一个字节,是否有人故意在那里隐藏数据。
要对其进行解码,我们可以使用以下功能:
decode_imdata(imdata)
我们可以看到,该函数与encode_imdata(imdata, data)
函数相反,即从左到右、从上到下同时读取三个像素,直到读取其等于 1 的最后一个像素的最后一种颜色的最后一位。
在下面的脚本中,我们使用PIL
模块表单中的图像包读取图像。一旦我们读取了图像,我们就使用 stepic 的 encode 函数来隐藏图像中的一些文本。我们将此信息保存在第二个图像中,并使用解码功能获取隐藏文本。
您可以在steganography
文件夹内的stepic_example.py
文件中找到以下代码:
**```py from PIL import Image import stepic
#Open an image file in which you want to hide data image = Image.open("python.png")
#Encode some text into the source image. #This returns another Image instance, which can save to a new file
image2 = stepic.encode(image, 'This is the hidden text') image2.save('python_secrets.png','PNG')
#Use the decode() function to extract data from an image:
image2 = Image.open('python_secrets.png') s = stepic.decode(image2) data = s.decode() print("Decoded data: " + data)
# 总结
本章的目标之一是了解允许我们使用 AES 和 DES 算法加密和解密信息的`pycrypto`和`cryptography`模块。我们还研究了隐写术技术,如最低有效位,以及如何使用 stepic 模块在图像中隐藏信息。
为了结束这本书,我想强调的是,读者应该更多地了解他们认为最重要的话题。每章都涵盖了基本思想,读者可以从*进一步阅读*部分找到更多信息的参考资料。
# 问题
1. 哪种算法类型使用相同的密钥加密和解密数据?
2. 哪种算法类型使用两种不同的密钥,一种用于加密,另一种用于解密?
3. 我们可以在 pycrypto 中使用哪个包来使用加密算法,如 AES?
4. 哪种算法需要确保数据长度为 16 字节的倍数?
5. `cryptography`模块的哪个包可以使用对称加密?
6. 使用哪种算法从密码派生加密密钥?
7. 是什么提供了用于对称加密的 fernet 包,以及用于生成密钥**的方法是什么?**
8. 哪个类别提供密码包对称加密?
9. stepic 的哪种方法生成包含隐藏数据的图像,从现有的
图像和任意数据开始?
10. pycrypto 的哪个包包含一些允许单向加密的`hash`函数?
# 进一步阅读
在这些链接中,您将找到有关本章中提到的工具及其官方文档的更多信息:
`Pycryptodome`是一个基于`pypi`存储库中可用的`pycrypto`库的模块:
[https://pypi.org/project/pycryptodome/](https://pypi.org/project/pycryptodome/)
[https://github.com/Legrandin/pycryptodome](https://github.com/Legrandin/pycryptodome)
[https://www.pycryptodome.org/en/latest/](https://www.pycryptodome.org/en/latest/)
在这些链接中,我们可以看到与`Pycrypto`模块相关的其他示例:
[https://github.com/X-Vector/Crypt0x/tree/master/Crypt0x](https://github.com/X-Vector/Crypt0x/tree/master/Crypt0x)
[https://github.com/jmortega/pycon-security_criptography](https://github.com/jmortega/pycon-security_criptography)
如果您需要更深入地探索密码生成,您可以找到其他有趣的模块,如 Secrets:
[https://docs.python.org/3/library/secrets.html#module-秘密](https://docs.python.org/3/library/secrets.html#module-secrets)
`secrets`模块用于生成适用于管理数据的加密强随机数,如密码、帐户身份验证、安全令牌和相关机密。******************