构建完全端到端加密的 PHP 聊天应用程序

此时此刻,在某个地方,你自以为私密的对话正被不怀好意的人读取。数据泄露的新闻隔三差五就会见诸报端,老实说,隐私已经不再是你想当然的东西了。

如果你是一名 PHP 开发人员,你需要从一开始就把它建立起来。本文将研究使用 libsodium 进行端到端加密 (E2EE),像诺克斯堡一样锁住你的聊天应用程序。

构建完全端到端加密的 PHP 聊天应用程序

为什么 E2EE 很重要(为什么大多数应用程序都搞错了)?

大多数聊天应用程序都声称自己是 “安全的”,但他们并没有告诉你:仅有静态加密和传输层安全(TLS)是不够的。

如果你的数据可以在服务器上被解密,那么它就不是真正的隐私数据。真正的端到端加密意味着即使服务器也无法读取信息,只有发送方和接收方才掌握密钥。

大型科技公司因后门和元数据泄露而备受指责,如果你的用户将他们的数据托付给你,你至少应该为他们提供严密的加密。

幸运的是,PHP 有一个可靠的加密库,它不仅可以实现 E2EE,而且效率出奇的高。

技术堆栈

  • PHP 8+(因为性能很重要)
  • Libsodium(现代、经过验证的加密技术)
  • WebSockets(用于实时消息传递)
  • IndexedDB/Web Crypto API(在浏览器中安全存储密钥)

步骤 1:生成和管理密钥

加密从密钥开始,在 E2EE 中,每个用户都有自己的密钥对:

  • 私钥(用户保密)
  • 公钥(与其他用户共享,用于加密消息)
use ParagonIE\Sodium\CryptoBox;

// 为新用户生成密钥对
$keys = CryptoBox::keypair();

// 提取公钥与他人共享
$publicKey = CryptoBox::publickey($keys);
$privateKey = CryptoBox::secretkey($keys);

每个用户都需要将他们的私钥安全地存储在他们的设备上,而不要将其发送到服务器。

步骤 2:在消息离开客户端之前对其进行加密

消息离开用户浏览器的那一刻,它就应该被加密了。任何明文都不应该触及你的数据库或日志。以下是使用另一个用户的公钥加密消息的方法:

$recipientPublicKey = '...'; // 从收件人的个人资料中检索
$encryptedMessage = CryptoBox::encrypt("Hey, this is secret!", $recipientPublicKey, $privateKey);

当收件人收到它时,会用他们的私钥解密它:

$decryptedMessage = CryptoBox::decrypt($encryptedMessage, $privateKey, $senderPublicKey);

现在,除了预定的收件人,其他人都无法读取这条消息。即使有人劫持了数据库,他们得到的也是纯粹的胡言乱语。

步骤 3:防止密钥被盗(因为黑客不傻)

存储私钥非常棘手。如果被攻击者窃取,游戏就结束了。

可靠的方法是什么?使用 Web Crypto API 和 IndexedDB,而不是将密钥存储在 cookie 或 localStorage 中。以下是在客户端安全生成和存储密钥的方法:

async function generateAndStoreKeys() {
    const keyPair = await window.crypto.subtle.generateKey(
        {
            name: "ECDH",
            namedCurve: "P-256"
        },
        true,
        ["deriveKey"]
    );
    
    const publicKey = await window.crypto.subtle.exportKey("spki", keyPair.publicKey);
    const privateKey = await window.crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
    
    // 存储在 IndexedDB 而不是 localStorage 
    await indexedDB.put("keys", { publicKey, privateKey });
}

现在,即使攻击者将 JavaScript 注入您的应用程序,他们也无法直接从 localStorage 中提取密钥。

步骤 4:使用 WebSocket 进行安全实时消息传递

加密固然好,但没人愿意刷新页面才能看到新消息。WebSockets 让聊天变得即时,而且你还可以安全地使用它们。

你的 WebSocket 服务器应仅中继加密消息:

$server -> on ( 'message' , function( $conn , $msg ) { 
    $data = json_decode ( $msg , true ); 
    $recipient = $data [ 'recipient' ]; 
    $encryptedText = $data [ 'message' ]; 
    
    // 转发加密消息而不解密
    sendToRecipient ( $recipient , $encryptedText ); 
});

因为只有客户端才持有解密密钥,所以服务器只是一个信使。

步骤 5:前向保密(因为仅有加密是不够的)

即使对消息进行了加密,如果用户的私人密钥泄露,过去的所有消息都会被解密。为了解决这个问题,我们使用了临时会话密钥,这意味着每封邮件都要使用新的密钥对:

$sessionKeyPair = CryptoBox::keypair();
$ephemeralPublicKey = CryptoBox::publickey($sessionKeyPair);

有了临时密钥,即使黑客窃取了你的私人密钥,他们也无法追溯阅读过去的信息。

你的聊天应用程序现在能防 NSA 吗?

没有一个系统是 100% 安全的。

但通过正确实施端到端加密,任何人,无论是黑客还是公司都很难窃听你的对话。

使用 PHP 和 libsodium,不只是添加了一项安全功能,还让用户能够控制自己的数据。

而在一个隐私不断受到攻击的世界里,这将改变游戏规则。

作者:Asian Digital Hub

本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/im/55703.html

(0)

相关推荐

发表回复

登录后才能评论