端到端加密是即时消息应用程序现在提出的最常见的函数之一,即使使用它们的人并不完全了解此函数可能带来的优缺点。Signal、WhatsApp、Wire等都采用了这样的模式。
这些应用程序的一个典型用例是实体之间的文本对话(一对一或群组),这意味着人们看不到对方,因此无法确定是否有人跟踪他们的消息或冒充参与者。此外,大部分通信是通过移动设备上的互联网渠道完成的,这些应用程序的攻击面非常大。即使有加密协议,但也不足以进行安全通信。
让我们从最简单的交流方式开始:涉及两个实体 A 和 B 的对话。
如果我们假设A和B之前共享了一个秘密s,那么它们可以使用一种经过验证的加密算法,例如AES-GCM或Chacha20-Poly1305来加密消息。让我们看看如何使用第一个协议 P0 进行:
A和B在秘密s上使用一个密钥派生函数(KDF)派生出一个会话密钥k;
A写入消息mA0,用密钥k对其进行加密,并将加密后的消息eA0发送给B;
B用密钥k解密eA0,现在可以读取消息;
B写入消息mB0,用密钥k加密后发送给a;
A用密钥k解密eB0,现在能够读取消息;
我们提供了该协议P0的Verifpal模型以及输出。攻击者可以复制一些消息。在P0中,没有加密的方法来检测eA0替换e0的情况。此外,如果秘密泄露,攻击者将能够解密所有的消息,包括过去和将来的消息。让我们首先解决解密过去消息的问题,这也解决了“交换”消息的问题。
在下面的描述中,我们假设存在一个传输消息的服务器,它还允许在接收者离线时存储消息。因此,服务器非常适合执行中间人攻击。然后,攻击者可以成为“系统”,而不仅仅是获取消息的路由器。注意,我们没有处理元数据存储,即使消息的内容对服务器来说仍然是未知的,元数据存储也可能显示足够多的私有信息。我们不处理可能(意外或恶意)出现的网络问题。
如果泄露用户的当前秘密不允许攻击者解密在攻击或泄漏之前交换的消息,则系统提供了完美的前置保密 (perfect forward secrecy,PFS)。
要达到完美前置保密的一种简单但接近现实的方法是:
仅使用永久加密材料对消息进行签名;
为每个会话绘制一个新的会话密钥;
以下是如何将 P0 演变为一个简化的临时 Diffie-Hellman-Merkle (DHE) 协议 P1。我们首先考虑 A 拥有非对称密钥对 (skA, pkA),B 拥有非对称密钥对 (skB, pkB),其中 pkA 和 pkB 是公钥。我们假设A和B之前已经验证过彼此的公钥。
A绘制一个随机的临时密钥对(eskA, epkA),通过私钥 skA 计算 sA 为 epkA 的签名,并将 epkA 和 sA 发送给 B;
B 用 epkA 和 pkA 验证签名 sA;
B随机选择一个临时密钥对(eskB, epkB),计算sB为私钥skB对epkB的签名,并将epkB和sB发送给A;
A用epkB和pkB验证签名sB;
A 使用 eskA 和 epkB 计算会话密钥 k,B 使用 eskB 和 epkA 计算相同的会话密钥。
请注意,必须为每条消息进行 Diffie-Hellman-Merkle 密钥交换,如本协议模型及其输出所示:实际上,在这个阶段,从一个会话密钥到另一个会话密钥的唯一方法是对每个消息执行DHE。
协议 P1 在构建加密密钥时是同步的。在P1的基础上,可以提出一个异步协议P2,它与我们在e2ee Mattermost插件中实现的协议非常接近。现在让我们考虑A拥有两个非对称密钥对:(skA, pkA) 签署;
(xskA, xpkA) 来执行密钥交换。
B拥有两个相似的密钥对,分别为(skB,pkB)和(xskB,xpkB),所有的公钥都由双方进行验证。A向B发送加密消息的过程是:
绘制一个随机会话密钥MK和初始向量IV;
加密(不使用认证的加密算法)要用MK和IV发送的消息;
绘制一个随机的临时密钥对(keyECDHE, pubECDHE);
利用keyECDHE和xpkB计算共享密钥DHSS,并从DHSS中导出密钥KWK;
用KWK加密MK以获得encryptedKey;
对IV、pubECDHE、公钥标识符(基本上是pkB || xpkB的哈希)和加密的消息进行签名。
使用这样的协议P2,通信可以异步完成,因为用于派生会话密钥的DHE可以在任何时候由双方完成。但是P2协议只实现了部分PFS。确实,如果B的秘密材料泄露,攻击者不可能解密他过去发送的消息;但如果泄露的是 A 的材料,攻击者就可以解密收到的所有消息。
为了完全(即双方)异步获得PFS,可以使用信号协议[DR],A 和 B 已经就共享秘密 s 达成一致,接下来将描述如何获得 s。
其想法是让会话密钥从一个共同的根演化而来,而不是每次都重新播种。为了从一个会话密钥演进到下一个会话密钥,需要使用一个KDF:将 KDF 应用于当前密钥会生成用于加密下一条消息的密钥。Signal 中使用的 KDF 被描述为ratchet(或单向函数):事实上,该KDF的一个特性是,给定当前会话密钥,就不可能计算上一个会话密钥(即用于计算当前密钥的密钥)。这给出了以下链:
新协议 P3 如下:
A和B都使用s上的KDF计算秘钥k0;
A使用密钥k0对消息m0进行加密,并将加密后的消息发送给B;
B使用k0解密消息;
A和B使用k0上的KDF计算下一个密钥k1;
B用密钥k1对消息m1进行加密,并将加密后的消息发送给A;
请注意,在这种情况下,我们有一个类似对讲机的对话(即按即说或按即传输)。由于对于大多数用例来说并不方便,因此 A 和 B 必须维护两个(对称)ratchet链,每个方向的消息用一条:
A的发射链与B的接收链同步;
B的发射链与A的接收链同步。
请注意:Signal 协议的名称“双ratchet”并不是指这两条链,而是指另一条链,这将在下面的 Post risk security 中进行描述。
与之前的方案 P2 相比,Signal 协议也需要更少的带宽,但发射链和接收链需要同步演进,这是另一类问题,我们不在这里讨论。除了共享秘密s协议外,P3协议是异步的。现在让我们看看如何将类似dhe的异步部分添加到P3中,使之完全异步化。
DHE 协议允许 A 和 B 在经过验证的通道上共享一个公共秘密 s,但双方必须同时在线。然而,为了让 A 计算共享密钥 s,A 只需要来自 B 的临时公钥 epkB,以及永久密钥skB提供的epkB签名sB。链接 A 和 B 的服务器可用于存储 i 个预取对(epkBi,sBi),以便不同的联系人发起对话。此时,P3协议的初始化步骤可以是:
B向服务器发送i对(epkBi, sBi),并将相应的eskBi存储在服务器另一头;
A向服务器查询其中一个对,并验证签名;
A绘制一个临时密钥对(eskA, epkA),并对eskA和epkBi执行DHE操作以获得s;
A启动ratchet链并向 B 发送加密消息,sA添加epkA和epkA的签名;
B从服务器获取epkA,验证sA,通过eskBi和epkA计算s,现在能够解密来自A的消息。
即使在实现的s计算中[X3DH]略有不同,但这里所展示的思想是有影响的。协议P3现在是完全异步的。
前面的协议P1、P2和P3中的一个关键概念是永久密钥的身份验证。这个设置步骤对于通信不是必需的,但是对于机密通信是必需的。要验证公钥,一种方法是通过已验证的通道验证出现在用户设备上的联系人的指纹(公钥)是否与该联系人设备上的指纹相同。执行这种验证的通常方法是扫描二维码编码的目标密钥的指纹。
这种通常可选的验证实际上是在 Olvid 中强制执行的。
如果泄露用户的当前机密,攻击者无法解密攻击或泄露后交换的消息,则系统提供了泄露后安全(post-compromise security, PCS)。这个概念在[CGCG16]中首次被形式化,用于经过身份验证的密钥交换。
在协议 P1 中,为了计算加密消息的每个密钥,提供了 PCS,因为密钥每次都会更改并且是随机选择的,但是请注意,如果私钥泄漏,攻击者可以冒充受害者,但无法解密在不知道相应的临时密钥的情况下加密的消息。
对于我们在 Mattermost 上用于端到端加密的协议 P2,没有完整的 PCS,原因与没有完整的 PFS 相同:确实,如果 A 的永久材料泄漏,所有她收到或将要收到的消息可能会被解密,但她发送或将要发送的消息不会被解密。
我们现在需要检查P3协议,即接近 Signal 的协议。因此,我们的协议不提供PCS,这将是双ratchet的目标,详述如下。
让我们回顾一下:
使用一个ratchet,Signal 协议通过使密钥通过单向函数演变来提供 PFS;
每条消息都有一个DHE,我们有 PFS 和 PCS;
混合解决方案是定期执行一个比X3DH更简单的新的DHE密钥交换,通过注入一些随机性来刷新用于获得PFS的ratchet:这一步是第二个(非对称)ratchet,最终我们实现双ratchet协议。
问题是如何定期执行第二个ratchet:对每条消息执行,我们回到协议 P1/P2。如果周期太长,这可能意味着大量泄漏,因为一旦执行攻击,在该周期内交换的所有消息都可以被解密。
在双ratchet [DR] 的文档中,这个提议是,每当发言者被打断并想要再次发言时,就进行DHE。在对讲机通信中,它确保每条消息的安全性与DHE相同,即协议P1。
因此,确实需要编辑Signal并在每一步执行一个新的DHE,从而在每条消息的附加数据中发送一个临时公钥,并签署该公钥以确保它确实来自发送者。为了处理丢失或无序的消息,发送方必须将过去的每个公钥添加到消息的额外数据中,直到消息得到确认。通常,我们需要在效率(以及可用性)和安全性之间做出选择。
可否认性
如果给定文本,用户可以否认参与了对话,则消息传递协议被称为可否认的,无论对话是真实的还是虚假的。特别是,如果任何用户 A 可以模拟与任何其他用户 B 与合法对话无法区分的对话记录,则该协议是可否认的:如果协议使得 B 在任何时候都没有提供给 A 的任何价值或信息,则这是可行的。在 Signal 中,我们达到了可否认性,因为一旦 A 从服务器接收到公钥包,就可以自己计算任何和所有以下密钥材料:B 通常会做的唯一事情是为非对称ratchet提供随机性,但没有办法区分 A 生成的随机值和 B 生成的随机值:因此她可以同时扮演这两个角色。
简而言之,我们不是通过证明B没有参与来实现可否认性,而是通过不能证明B确实参与了对话来实现可否认性。
请注意,可否认性是可取的,以确保用户不会被谴责或被诱骗生成有罪的消息。
将可否认性与消息的真实性混合在一起很容易产生混淆。我们可以将这两个属性总结如下:
真实性:A 想确定她正在与 B 交谈。
可否认性:A想向所有人证明她和B谈过。
我们可以同时确保这两个属性:真实性必须在对话内部,在主角之间证明,而可否认性必须在对话之外,对非参与者证明。例如,Signal 实现了可否认性和真实性。
如果端到端加密是指移动中的加密,那么了解消息在收到后会发生什么(无论是客户端还是服务器端)也很重要。
一个明显的选择是将它们按原样加密存储,即 A 从 B 接收 c=Enc(m),解密后读取它,然后应用程序将本地存储 c,获取它并根据需要重新解密它。然而,这意味着 A 必须保留用于解密 c 的任何密钥,从而失去前置保密性:在任何给定时间,应用程序的状态都将包含用于解密整个 backlog 的密钥。
另一种解决方案是使用另一个密钥重新加密消息,并使用设备的安全存储将它们存储在服务器端或客户端。在这种情况下,如果安全存储确实安全,则 PFS 可能不会被破坏。
在服务器上存储消息时,我们发现相同的选项,使用新密钥或按原样存储消息。这是最重要的插件的选择,它在服务器上存储 A 和 B 的加密消息,无论谁是发件人,都与 P2 所描述的相反(这只是部分 PFS)。因此,即使最重要的插件提供端到端加密,它也不提供PFS或PCS。
如前所述,我们可以将完整的 Signal 协议分为不同的步骤:
初始会话密钥交换(X3DH);
提供 PFS 的(对称)ratchet步骤;
提供 PCS 的(不对称)ratchet步骤;
提供 PFS 的(对称)ratchet步骤;
提供 PCS 的(不对称)ratchet步骤;
在前面的枚举中,偶数(对称)步骤已经是量子安全级别的;如果密钥大小很小(根据量子安全标准),将密钥大小加倍通常足以实现量子安全。
然而,依赖Diffie-Hellman-Merkle 协议的奇数(不对称)步骤并不是量子安全的。最重要的是协议的第一步:确实,实现PCS是由经典的DHE完成的,这不是Signal协议的特殊性,因此是独立研究的。然而,这并不是一个简单的问题,而X3DH则是这里更重要的讨论问题。
构建一个类似 X3DH 的后量子协议并不是那么容易。需要达到 X3DH 的所有安全目标,这些目标尚未完全形式化和建立。此外,量子安全密钥建立算法的命题的多样性是广泛的:至少如下所示:
4 个后量子密码标准化决赛入围者:3 个基于格的系统和 1 个基于代码的系统;
5 个备选候选者:1 个基于同源的系统、2 个基于格的系统和 1 个基于代码的系统;
CSIDH,这是一个基于同源的系统。
在经典密码学和后量子密码学中,群体对话的效率挑战都被突出显示。在第二部分,我们将详细介绍如何在多个模型中实现群聊,尽量在不牺牲安全性和用户友好性的情况下始提高效率。
参考及来源:https://blog.quarkslab.com/secure-messaging-apps-and-group-protocols-part-1.html
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.