使用libsodium实现Diffie-Hellman时共享密钥不一致问题求助
问题分析与解决
你的共享密钥不匹配的核心原因是通信双方错误地都使用了客户端模式的密钥派生函数。libsodium的crypto_kx模块采用客户端-服务器模型,双方必须分别调用对应角色的函数才能生成匹配的共享密钥。
具体错误点
你当前的代码只调用了sodium.crypto_kx_client_session_keys,但通信的另一方需要调用对应的服务器端函数sodium.crypto_kx_server_session_keys,而非同样使用客户端函数——这是密钥不匹配的直接原因。
修正方案
通信双方需明确角色:一方作为客户端,另一方作为服务器,分别调用对应函数,同时注意密钥对应关系:
- 客户端的
sharedRx对应 服务器的sharedTx - 客户端的
sharedTx对应 服务器的sharedRx
客户端(示例:Alice)代码
async function handleClientSharedSecret(clientSk, serverPk) { await _sodium.ready; const sodium = _sodium; // 生成客户端公钥 const clientPk = sodium.crypto_scalarmult_base(sodium.from_base64(clientSk)); // 调用客户端会话密钥函数 const sessionKeys = sodium.crypto_kx_client_session_keys( clientPk, sodium.from_base64(clientSk), sodium.from_base64(serverPk) ); // 客户端接收密钥,对应服务器发送密钥 return sodium.to_base64(sessionKeys.sharedRx); }
服务器端(示例:Bob)代码
async function handleServerSharedSecret(serverSk, clientPk) { await _sodium.ready; const sodium = _sodium; // 生成服务器公钥 const serverPk = sodium.crypto_scalarmult_base(sodium.from_base64(serverSk)); // 调用服务器端会话密钥函数 const sessionKeys = sodium.crypto_kx_server_session_keys( serverPk, sodium.from_base64(serverSk), sodium.from_base64(clientPk) ); // 服务器发送密钥,对应客户端接收密钥 return sodium.to_base64(sessionKeys.sharedTx); }
用你的密钥验证
使用你提供的密钥测试:
- Alice(客户端)私钥:
vrzVDcdX7PyN1BGo00CzJ_vdvWuOnK_sUeHGQbDAZHQ,公钥:SaKUG5MX0m5XP7Tbf8-LjHzhWdxn9Qn6ndRVBP1YeRI - Bob(服务器)私钥:
hzFTBbnif8I37ySoDi5eqtEUechU_dBE7n-oFYNENh0,公钥:_nGMQavOQuMf7FUyUYfaqvfBcj9hAFJPcc-Bo0JHEEw
Alice调用handleClientSharedSecret传入自己的私钥和Bob的公钥,得到的sharedRx会和Bob调用handleServerSharedSecret传入自己的私钥和Alice的公钥得到的sharedTx完全一致。
额外注意事项
- 确保双方交换的公钥未被篡改或传输错误,这也是密钥不匹配的常见诱因。
- 不要混淆私钥和公钥的传递方向:客户端需将自己的公钥传给服务器,服务器需将自己的公钥传给客户端。
内容的提问来源于stack exchange,提问作者Maverick 2000
相关产品推荐
相关产品推荐

