andrewdo/php-double-ratchet

使用 Curve25519 处理双摇杆算法的会话管理器

dev-master 2019-08-26 23:28 UTC

This package is auto-updated.

Last update: 2024-09-27 10:30:20 UTC


README

这是一个处理两个当事人之间传递的消息加密的库,使用“双摇杆”算法。它使用 Curve25519 生成密钥和签名。

要求

  • PHP 7.1.3 或更高版本

安装

composer require andrewdo/php-double-ratchet

用法

首先,您需要生成或加载您的身份私钥

// generate random private key
$ourIdentity = KeyPair::getNewKeyPair();

// load from a base64 string
$ourIdentity = new KeyPair(new PrivateKey(base64_decode($base64String)));

为了与另一方开始会话,您需要从他们那里获得一个已签名的 预密钥。签名验证是可选的,但建议使用。如果您事先知道,最好也硬编码另一方的公钥。

$theirPublicKey = new Key(...their 32 byte public key...);
$theirPreKeyPublicKey = new Key(...their 32 byte pre key public key...);
$theirPreKeySignature = ...signature of the pre key...;
if (!$theirPublicKey->isValidSignature($theirPreKeySignature, $theirPreKey->getValue())) {
    throw new Exception('Sketchy...');
} 

然后您可以创建一个 SessionManager 实例。

注意:如果您是生成 预密钥 并拥有其私钥的人,您需要将其传递。

$sessionManager = new SessionManager(
    $ourIdentity->getPrivateKey(),
    $theirPublicKey,
    $theirPreKeyPublicKey,
    $preKeyPrivateKey ?: null,  // if we are the receiver of the first message
    $logger ?: null,
    $options ?: []
);

会话管理器将处理 JSON 负载的加密和解密,以及密钥的双摇杆。它将在每个 JSON 请求/响应中包含 Ratchet Key。默认情况下,该字段的密钥为 ratchet_key,但可以使用 SessionManager 的选项参数进行更改。

$encryptedMessageStr = $sessionManager->encryptData(['grandmas_cookbook' => '...']);
$decryptedData = $sessionManager->decryptMessage($encryptedMessageStr);
// var_dump($decryptedData)
// array(2) { ["ratchet_key"]=> string(4) "asdf" ["grandmas_cookbook"]=> ... }

如果您需要持久化 SessionManager 实例,可以使用

$sessionManagerString = $sessionManager->getAsEncryptedString();
// var_dump($sessionManagerString)
// string(2801) "/6Iq=...A==:eoNnkPa2sCE0F8ezC9TJzA=="

$sessionManager = SessionManager::getFromEncryptedString(
    $ourIdentity->getPrivateKey(),
    $sessionManagerString
);

生成预密钥

为了从某人那里接收加密消息,您必须以某种方式提供您的公钥和已签名的预密钥。要生成一个

$preKey = KeyPair::getNewKeyPair();
$preKeyPublicKey = $preKey->getPublicKey();
$signature = $ourIdentity->getSignature($preKeyPublicKey->getValue());