mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-06-14 11:42:02 +08:00
feat(rustdesk): 完整实现RustDesk协议和P2P连接
重大变更: - 从prost切换到protobuf 3.4实现完整的RustDesk协议栈 - 新增P2P打洞模块(punch.rs)支持直连和中继回退 - 重构加密系统:临时Curve25519密钥对+Ed25519签名 - 完善HID适配器:支持CapsLock状态同步和修饰键映射 - 添加音频流支持:Opus编码+音频帧适配器 - 优化视频流:改进帧适配器和编码器协商 - 移除pacer.rs简化视频管道 扩展系统: - 在设置向导中添加扩展步骤(ttyd/rustdesk切换) - 扩展可用性检测和自动启动 - 新增WebConfig handler用于Web服务器配置 前端改进: - SetupView增加第4步扩展配置 - 音频设备列表和配置界面 - 新增多语言支持(en-US/zh-CN) - TypeScript类型生成更新 文档: - 更新系统架构文档 - 完善config/hid/rustdesk/video/webrtc模块文档
This commit is contained in:
@@ -194,48 +194,14 @@ pub fn verify_password(password: &str, salt: &str, expected_hash: &[u8]) -> bool
|
||||
computed == expected_hash
|
||||
}
|
||||
|
||||
/// RustDesk symmetric key negotiation result
|
||||
pub struct SymmetricKeyNegotiation {
|
||||
/// Our temporary public key (to send to peer)
|
||||
pub our_public_key: Vec<u8>,
|
||||
/// The sealed/encrypted symmetric key (to send to peer)
|
||||
pub sealed_symmetric_key: Vec<u8>,
|
||||
/// The actual symmetric key (for local use)
|
||||
pub symmetric_key: secretbox::Key,
|
||||
}
|
||||
|
||||
/// Create symmetric key message for RustDesk encrypted handshake
|
||||
/// Decrypt symmetric key using Curve25519 secret key directly
|
||||
///
|
||||
/// This implements RustDesk's `create_symmetric_key_msg` protocol:
|
||||
/// 1. Generate a temporary keypair
|
||||
/// 2. Generate a symmetric key
|
||||
/// 3. Encrypt the symmetric key using the peer's public key and our temp secret key
|
||||
/// 4. Return (our_temp_public_key, sealed_symmetric_key, symmetric_key)
|
||||
pub fn create_symmetric_key_msg(their_public_key_bytes: &[u8; 32]) -> SymmetricKeyNegotiation {
|
||||
let their_pk = box_::PublicKey(*their_public_key_bytes);
|
||||
let (our_temp_pk, our_temp_sk) = box_::gen_keypair();
|
||||
let symmetric_key = secretbox::gen_key();
|
||||
|
||||
// Use zero nonce as per RustDesk protocol
|
||||
let nonce = box_::Nonce([0u8; box_::NONCEBYTES]);
|
||||
let sealed_key = box_::seal(&symmetric_key.0, &nonce, &their_pk, &our_temp_sk);
|
||||
|
||||
SymmetricKeyNegotiation {
|
||||
our_public_key: our_temp_pk.0.to_vec(),
|
||||
sealed_symmetric_key: sealed_key,
|
||||
symmetric_key,
|
||||
}
|
||||
}
|
||||
|
||||
/// Decrypt symmetric key received from peer during handshake
|
||||
///
|
||||
/// This is the server-side of RustDesk's encrypted handshake:
|
||||
/// 1. Receive peer's temporary public key and sealed symmetric key
|
||||
/// 2. Decrypt the symmetric key using our secret key
|
||||
pub fn decrypt_symmetric_key_msg(
|
||||
/// This is used when we have a fresh Curve25519 keypair for the connection
|
||||
/// (as per RustDesk protocol - each connection generates a new keypair)
|
||||
pub fn decrypt_symmetric_key(
|
||||
their_temp_public_key: &[u8],
|
||||
sealed_symmetric_key: &[u8],
|
||||
our_keypair: &KeyPair,
|
||||
our_secret_key: &SecretKey,
|
||||
) -> Result<secretbox::Key, CryptoError> {
|
||||
if their_temp_public_key.len() != box_::PUBLICKEYBYTES {
|
||||
return Err(CryptoError::InvalidKeyLength);
|
||||
@@ -247,47 +213,7 @@ pub fn decrypt_symmetric_key_msg(
|
||||
// Use zero nonce as per RustDesk protocol
|
||||
let nonce = box_::Nonce([0u8; box_::NONCEBYTES]);
|
||||
|
||||
let key_bytes = box_::open(sealed_symmetric_key, &nonce, &their_pk, &our_keypair.secret_key)
|
||||
.map_err(|_| CryptoError::DecryptionFailed)?;
|
||||
|
||||
secretbox::Key::from_slice(&key_bytes).ok_or(CryptoError::InvalidKeyLength)
|
||||
}
|
||||
|
||||
/// Decrypt symmetric key using Ed25519 signing keypair (converted to Curve25519)
|
||||
///
|
||||
/// RustDesk clients encrypt the symmetric key using the public key from IdPk,
|
||||
/// which is our Ed25519 signing public key converted to Curve25519.
|
||||
/// We must use the corresponding converted secret key to decrypt.
|
||||
pub fn decrypt_symmetric_key_with_signing_keypair(
|
||||
their_temp_public_key: &[u8],
|
||||
sealed_symmetric_key: &[u8],
|
||||
signing_keypair: &SigningKeyPair,
|
||||
) -> Result<secretbox::Key, CryptoError> {
|
||||
use tracing::debug;
|
||||
|
||||
if their_temp_public_key.len() != box_::PUBLICKEYBYTES {
|
||||
return Err(CryptoError::InvalidKeyLength);
|
||||
}
|
||||
|
||||
let their_pk = PublicKey::from_slice(their_temp_public_key)
|
||||
.ok_or(CryptoError::InvalidKeyLength)?;
|
||||
|
||||
// Convert our Ed25519 secret key to Curve25519 for decryption
|
||||
let our_curve25519_sk = signing_keypair.to_curve25519_sk()?;
|
||||
|
||||
// Also get our converted public key for debugging
|
||||
let our_curve25519_pk = signing_keypair.to_curve25519_pk()?;
|
||||
|
||||
debug!(
|
||||
"Decrypting with converted keys: our_curve25519_pk={:02x?}, their_temp_pk={:02x?}",
|
||||
&our_curve25519_pk.as_ref()[..8],
|
||||
&their_pk.as_ref()[..8]
|
||||
);
|
||||
|
||||
// Use zero nonce as per RustDesk protocol
|
||||
let nonce = box_::Nonce([0u8; box_::NONCEBYTES]);
|
||||
|
||||
let key_bytes = box_::open(sealed_symmetric_key, &nonce, &their_pk, &our_curve25519_sk)
|
||||
let key_bytes = box_::open(sealed_symmetric_key, &nonce, &their_pk, our_secret_key)
|
||||
.map_err(|_| CryptoError::DecryptionFailed)?;
|
||||
|
||||
secretbox::Key::from_slice(&key_bytes).ok_or(CryptoError::InvalidKeyLength)
|
||||
|
||||
Reference in New Issue
Block a user