文本数据加密和身份验证
导言
在当今的数字世界中,通过开放渠道传输信息时的保护是关键任务之一。 此示例显示文本消息的对称加密,同时验证其完整性。 该解决方案基于CBC模式下的AES-256算法与HMAC-SHA256身份验证代码相结合。
什么是AES?
高级加密标准(AES)是美国国家标准与技术研究所于2001年采用的对称分组密码。 它被称为对称,因为相同的密钥用于加密和解密。 它是块状的,因为它使用固定大小的块。 在AES的情况下,块大小是128位(16字节),密钥长度可以是128、192或256位。 在这个例子中,最大长度为256位,提供了最高水平的耐久性。 AES取代了过时的DES,现在用于TLS,Wi-Fi,磁盘加密系统和许多其他应用程序。
简单块加密的问题
如果独立地加密每个块,则该模式称为电子码本(ECB)。 它有一个根本的缺陷:相同的明文块变成相同的密文块。 这允许观察者在不知道密钥的情况下得出关于数据结构的结论。 一个典型的例子:在ECB中加密的图像仍然可以通过其轮廓来区分。 因此,真实世界的任务使用消除此问题的模式。
中国工商银行
密码块链(CBC)是一种模式,在加密之前,每个明文块都与前一个密文块进行异或。 对于第一个块,使用初始化向量(IV)而不是前一个。 由于串联,相同的明文块产生不同的密文块。 但是,CBC本身仅提供机密性,并不能防止数据修改。
HMAC
基于哈希的消息认证码(HMAC)是一种用于验证完整性和真实性的机制。 它接受一个键和数据,并输出一个称为标签的短的固定长度值。 只有密钥的所有者才能计算出正确的标记。 任何数据更改都会导致完全不同的标签。 如果入侵者更改了至少一个位,但不知道HMAC密钥,他们将无法伪造标签。
经过身份验证的加密
将加密和认证相结合的方案称为认证加密。 它同时提供两个属性:机密性和完整性。 没有身份验证的简单加密不提供第二个保证。 而且,没有认证的CBC容易受到攻击,这些攻击逐渐解密没有密钥的消息。 添加HMAC并在解密之前检查标记完全关闭此漏洞。 在本例中,使用encrypt-then-MAC方案:首先对数据进行加密,然后使用密文计算标记。 在接受时,首先检查标记,并且只有当它匹配时,才执行解密。
加入图书馆
添加必要的库:
*Nettle是GNU Nettle库的包装器,并提供AES,CBC模式,HMAC和辅助块添加操作的实现。;
*Base64负责编码和解码为Base64格式。 由于密文是任意字节,因此不能通过文本通道直接传输。 Base64将字节转换为适用于电子邮件,即时通讯,JSON和其他文本协议的可打印字符序列。;
*Random用于生成密码随机值,即salt和初始化向量。
using Nettle, Base64, Random
加密功能
功能 зашифровать 接受文本和密码,返回包含所有要解密的数据的Base64字符串。
соль 这些是随机添加到密码中的8个字节,以便相同的密码给出不同的密钥。 这不是秘密,它是公开传播的。
密钥由函数生成 gen_key32_iv16 从密码和盐。 其长度为AES-256的32字节(256位)。 该功能是确定性的,因此接收者自己恢复密钥。
iv16 这些是第一个CBC块的随机16个字节。 它对于每条消息都必须是唯一的,因此它是随机生成的。 它是公开传播的。
HMAC密钥是标签的单独密钥,通过SHA-256散列盐和密码获得。 加密密钥和身份验证密钥不能匹配。
SHA-256是将数据转换为256位的散列函数。 输入中最轻微的变化会给出完全不同的结果。
加密是通过 encrypt 与AES-256和CBC模式。 由于AES在16字节的块中工作,因此应用了加法。 add_padding_PKCS5():等于其数量的字节被添加到末尾。 结果称为密文。
标签是基于32字节密文的HMAC-SHA256。 证明密文没有被改变。 在接受时,标签被重新计算;如果不匹配,解密被拒绝。
所有组件都组合成一个包: соль, iv16, шифр, тег. 由于尺寸是固定的,因此该订单允许您明确划分包装。 包以Base64编码。
function зашифровать(текст, пароль)
соль = rand(UInt8, 8)
(ключ, _) = gen_key32_iv16(Vector{UInt8}(пароль), соль)
iv16 = rand(UInt8, 16)
hmac_ключ = hex2bytes(hexdigest("sha256", соль, Vector{UInt8}(пароль)))
шифр = encrypt(Encryptor("AES256", ключ), :CBC, iv16, add_padding_PKCS5(Vector{UInt8}(текст), 16))
тег = hex2bytes(hexdigest("sha256", hmac_ключ, шифр))
return base64encode(vcat(соль, iv16, шифр, тег))
end
解密函数
功能 расшифровать 接受Base64字符串和密码,返回源文本或引发错误。:
*Base64解码和解析成四个部分进行。 соль 需要字节1-8, iv16 9–24, тег 最后32个字节,介于两者之间的一切都是 шифр;
*加密密钥和HMAC密钥是从salt和密码新生成的。 如果密码正确,它们将与加密期间使用的密码相匹配。;
*使用密码和恢复的HMAC密钥计算标签,并与传输的密钥进行比较。 如果不匹配,则函数立即抛出错误,并且不执行解密。 这是安全方面的一个关键阶段。
function расшифровать(сообщение, пароль)
принято = base64decode(сообщение)
соль = принято[1:8]
iv16 = принято[9:24]
шифр = принято[25:end-32]
тег = принято[end-31:end]
(ключ, _) = gen_key32_iv16(Vector{UInt8}(пароль), соль)
hmac_ключ = hex2bytes(hexdigest("sha256", соль, Vector{UInt8}(пароль)))
if hex2bytes(hexdigest("sha256", hmac_ключ, шифр)) != тег
error("ОШИБКА: Данные повреждены или подделаны!")
end
return String(trim_padding_PKCS5(decrypt(Decryptor("AES256", ключ), :CBC, iv16, шифр)))
end
初始数据
我们将在此基础上确定生成加密密钥的密码,并设置秘密加密消息的源文本。
пароль = "qwerty123";
текст = "Это секретное сообщение. Cтрого конфиденциально."
加密技术
参考函数 зашифровать(). 让我们加密源文本数据。
сообщение = зашифровать(текст, пароль);
发送信息
想象一下,数据是通过开放的文本通道传输的。 收件人只会看到base64格式的加密数据。 他必须知道密码才能解密它。
пароль = nothing
текст = nothing
display(сообщение)
接收和解密消息
让我们考虑可能的进一步方案:
*输入的密码不正确;
*输入了正确的密码,并替换了一位数据;
*已输入正确的密码,并传送了真实的讯息。
密码无效
如果输入错误的密码,将显示错误消息。
неверный_пароль = "qwerty12345"
текст = расшифровать(сообщение, неверный_пароль);
display(text)
消息替换
我们来模拟传输过程中数据失真的情况。 让我们显示第25个字节中的位的内容。
байты = base64decode(сообщение)
bitstring(байты[25])
让我们替换其中的一个位。
байты[25] ⊻= 0x01
bitstring(байты[25])
它会做一个消息替换。
подмена = base64encode(байты)
让我们比较传输和加密消息中的字符。
for i in 1:length(сообщение)
if сообщение[i] != подмена[i]
println("职位 ", i, ": '", сообщение[i], "' → '", подмена[i], "'")
end
end
在消息中,符号位于第34个位置。 代之以 . 尝试解密时,即使使用正确的密码,也会显示错误消息。
пароль = "qwerty123"
расшифровать(подмена, пароль)
一个真实的消息和一个有效的密码
当密码正确且传输的数据完好无损时,对消息进行解密。
пароль = "qwerty123"
текст = расшифровать(сообщение, пароль)
display(текст)
结论
此示例演示文本消息安全传输的完整方案。 显示没有认证的加密不能确保数据完整性,并且HMAC的添加使得能够检测甚至单个比特变化。
这些原则是许多现实世界系统的基础。 提供HTTPS安全的TLS协议使用类似的方案。 安全信使对每条消息使用对称加密和身份验证。 磁盘加密系统(如LUKS或BitLocker)使用块密码进行身份验证。 安全电子邮件协议、VPN隧道和电子文档管理系统也依赖于这些原则。
显然,你永远不应该使用像这样的密码 "qwerty123" 实际上,您需要使用尽可能多的区分大小写的字符,数字和特殊字符的密码,最好是长密码或随机的256位密钥。 密码不能通过同一通道传输、公开存储或重复使用。
可靠的消息保护由几个元素组成:强大的加密算法,正确选择的模式,身份验证机制,正确的密钥生成和密码管理纪律。