我知道,一般建议是“不要碰加密货币”。安全加密备份数据的标准方法是使用 GnuPG。但是,对于一个相当学术的练习,我想通过一个仅与从 POSIX shell 调用的 OpenSSL 标准工具(即 dgst、enc、rsautl 和 Co)一起工作的协议来考虑。
该场景包括一个或多或少受信任的系统,在该系统上创建备份 - 例如,这可能是一个邮件或文件服务器。然后是一个不是 100% 可信的存储(例如云存储,或不完全由我控制的备份服务器)。因此,加密的目的是在存储在不受信任的存储上时保护数据的机密性和完整性。这种保护也应该在受信任系统受到损害的情况下起作用——至少对于受信任系统受到损害之前存储的数据。
所以这是一种应该满足上述标准的协议:
第 1 步:RSA 密钥对
此步骤只需执行一次。需要一个 RSA 密钥对。该密钥对不应在“受信任”系统上创建,而是在真正受信任的盒子上创建(例如,受信任的工作站或您信任的任何地方以保存您的 GPG 密钥环)。由于私钥仅用于恢复,因此它永远不会进入受信任系统或不受信任存储的领域。密钥大小需要为 4096 位或以上(我们稍后会谈到)。OpenSSL 通常通过这些命令提供密钥生成和分离:
编辑:切换到 PKCS#8 作为键,可能更能抵抗暴力攻击
openssl genpkey -aes-256-cbc -algorithm RSA -pkeyopt 'rsa_keygen_bits:8192' -out private.key
openssl pkey -in private.key -out public.key -pubout
第 2 步:生成会话秘密
对于每个加密过程,应生成专用秘密(密钥、初始化向量和盐):
编辑:根据 Ctulhu 的评论删除盐
key=$(openssl rand -hex 32)
iv=$(openssl rand -hex 16)
hmacpw=$(openssl rand -base64 48)
请注意:我知道这将使受信任机器的内存中的机密不受保护。但是,如果攻击者能够以某种方式访问机器,他可以浏览备份进程的内存,那么他可能已经可以访问受这些机密保护的数据。
第 3 步:压缩和加密
数据应在加密前进行压缩。无论如何都需要压缩,所以我认为在加密数据之前进行压缩是个好主意:
编辑:根据 Ctulhu 的评论删除盐
data-generator | xz -zc | openssl enc -e -aes-256-ctr -K $key -iv $iv -out message.enc
第 4 步:生成 HMAC 并打包密钥
最后一步是生成刚刚加密数据的 HMAC,并将其与会话机密一起打包到 RSA 加密文件中,使用公钥进行加密:
编辑:根据 Ctulhu 的评论删除盐
hmac=$(openssl dgst -sha512 -hmac $hmacpw -hex message.enc | sed 's/^.*=[[:space:]]//g')
echo "${key}:${iv}:${hmacpw}:${hmac}" | openssl rsautl -inkey public.key -pubin -encrypt -out message.key
在这里,为什么 RSA 密钥必须那么大变得很明显:shell 字符串中的十六进制数字每个都计为一个字节,而不是半字节。因此,密钥字符串的大小总和为 (2x32 + 2x16 + 64 + 128 + 5) = 293 Bytes = 2344 Bits。
同样,我知道在命令行上公开秘密通常是一个坏主意,但鉴于这种情况,我看不出这会如何损害所述系统上以纯文本形式提供的数据的机密性或完整性,其中攻击者可以更容易地损害他们的隐私或完整性。但是,如果我真的要实现它,我宁愿使用命名管道来避免在进程列表中弹出秘密。
现在我的问题:
- 我错过了什么?您是否看到我尚未注意到的任何缺陷或潜在的攻击媒介?
openssl dgst -sha512 -sign private.key -out message.sig message.enc
考虑到这将要求私钥驻留在或多或少受信任的系统上,使用 来创建签名会更安全吗?