Финальный обмен ключами шифрования, все готово для установки WebRTC соединения

This commit is contained in:
RoyceDa
2026-03-11 17:22:29 +02:00
parent e06d58facf
commit e79282755b
3 changed files with 36 additions and 5 deletions

View File

@@ -26,6 +26,10 @@ export interface CallContextValue {
export enum CallState { export enum CallState {
CONNECTING, CONNECTING,
KEY_EXCHANGE, KEY_EXCHANGE,
/**
* Финальная стадия сигналинга, на которой обе стороны обменялись ключами и теперь устанавливают защищенный канал связи для звонка,
* через WebRTC, и готовятся к активному звонку.
*/
WEB_RTC_EXCHANGE, WEB_RTC_EXCHANGE,
ACTIVE, ACTIVE,
ENDED, ENDED,
@@ -59,6 +63,7 @@ export function CallProvider(props : CallProviderProps) {
const [sessionKeys, setSessionKeys] = useState<nacl.BoxKeyPair | null>(null); const [sessionKeys, setSessionKeys] = useState<nacl.BoxKeyPair | null>(null);
const send = useSender(); const send = useSender();
const publicKey = usePublicKey(); const publicKey = usePublicKey();
const peerConnectionRef = useRef<RTCPeerConnection | null>(null);
const roleRef = useRef<CallRole | null>(null); const roleRef = useRef<CallRole | null>(null);
const [sharedSecret, setSharedSecret] = useState<string>(""); const [sharedSecret, setSharedSecret] = useState<string>("");
@@ -74,10 +79,24 @@ export function CallProvider(props : CallProviderProps) {
* У нас уже есть активный звонок, игнорируем все сигналы, кроме сигналов от текущего звонка * У нас уже есть активный звонок, игнорируем все сигналы, кроме сигналов от текущего звонка
*/ */
if(packet.getSrc() != activeCall){ if(packet.getSrc() != activeCall){
console.info("Received signal from " + packet.getSrc() + " but active call is with " + activeCall + ", ignoring");
info("Received signal for another call, ignoring"); info("Received signal for another call, ignoring");
return; return;
} }
} }
if(signalType == SignalType.END_CALL){
/**
* Сбросили звонок
*/
setActiveCall("");
setCallState(CallState.ENDED);
setShowCallView(false);
setSessionKeys(null);
setSharedSecret("");
setDuration(0);
roleRef.current = null;
return;
}
if(signalType == SignalType.CALL){ if(signalType == SignalType.CALL){
/** /**
* Нам поступает звонок * Нам поступает звонок
@@ -87,6 +106,7 @@ export function CallProvider(props : CallProviderProps) {
setShowCallView(true); setShowCallView(true);
} }
if(signalType == SignalType.KEY_EXCHANGE && roleRef.current == CallRole.CALLER){ if(signalType == SignalType.KEY_EXCHANGE && roleRef.current == CallRole.CALLER){
console.info("EXCHANGE SIGNAL RECEIVED, CALLER ROLE");
/** /**
* Другая сторона сгенерировала ключи для сессии и отправила нам публичную часть, * Другая сторона сгенерировала ключи для сессии и отправила нам публичную часть,
* теперь мы можем создать общую секретную сессию для шифрования звонка * теперь мы можем создать общую секретную сессию для шифрования звонка
@@ -105,12 +125,14 @@ export function CallProvider(props : CallProviderProps) {
*/ */
const signalPacket = new PacketSignal(); const signalPacket = new PacketSignal();
signalPacket.setSrc(publicKey); signalPacket.setSrc(publicKey);
signalPacket.setDst(packet.getDst()); signalPacket.setDst(packet.getSrc());
signalPacket.setSignalType(SignalType.KEY_EXCHANGE); signalPacket.setSignalType(SignalType.KEY_EXCHANGE);
signalPacket.setSharedPublic(Buffer.from(sessionKeys.publicKey).toString('hex')); signalPacket.setSharedPublic(Buffer.from(sessionKeys.publicKey).toString('hex'));
send(signalPacket); send(signalPacket);
setCallState(CallState.WEB_RTC_EXCHANGE);
} }
if(signalType == SignalType.KEY_EXCHANGE && roleRef.current == CallRole.CALLEE){ if(signalType == SignalType.KEY_EXCHANGE && roleRef.current == CallRole.CALLEE){
console.info("EXCHANGE SIGNAL RECEIVED, CALLEE ROLE");
/** /**
* Мы отправили свою публичную часть ключа другой стороне, * Мы отправили свою публичную часть ключа другой стороне,
* теперь мы получили ее публичную часть и можем создать общую * теперь мы получили ее публичную часть и можем создать общую
@@ -128,6 +150,7 @@ export function CallProvider(props : CallProviderProps) {
const computedSharedSecret = nacl.box.before(Buffer.from(sharedPublic, 'hex'), sessionKeys.secretKey); const computedSharedSecret = nacl.box.before(Buffer.from(sharedPublic, 'hex'), sessionKeys.secretKey);
info("Generated shared secret for call session: " + Buffer.from(computedSharedSecret).toString('hex')); info("Generated shared secret for call session: " + Buffer.from(computedSharedSecret).toString('hex'));
setSharedSecret(Buffer.from(computedSharedSecret).toString('hex')); setSharedSecret(Buffer.from(computedSharedSecret).toString('hex'));
setCallState(CallState.WEB_RTC_EXCHANGE);
} }
}, [activeCall, sessionKeys]); }, [activeCall, sessionKeys]);
@@ -143,6 +166,7 @@ export function CallProvider(props : CallProviderProps) {
setCallState(CallState.CONNECTING); setCallState(CallState.CONNECTING);
setShowCallView(true); setShowCallView(true);
const signalPacket = new PacketSignal(); const signalPacket = new PacketSignal();
signalPacket.setSrc(publicKey);
signalPacket.setDst(dialog); signalPacket.setDst(dialog);
signalPacket.setSignalType(SignalType.CALL); signalPacket.setSignalType(SignalType.CALL);
send(signalPacket); send(signalPacket);
@@ -150,6 +174,12 @@ export function CallProvider(props : CallProviderProps) {
} }
const close = () => { const close = () => {
const packetSignal = new PacketSignal();
packetSignal.setSrc(publicKey);
packetSignal.setDst(activeCall);
packetSignal.setSignalType(SignalType.END_CALL);
send(packetSignal);
peerConnectionRef.current = null;
setActiveCall(""); setActiveCall("");
setCallState(CallState.ENDED); setCallState(CallState.ENDED);
setShowCallView(false); setShowCallView(false);
@@ -170,6 +200,7 @@ export function CallProvider(props : CallProviderProps) {
*/ */
const keys = generateSessionKeys(); const keys = generateSessionKeys();
const signalPacket = new PacketSignal(); const signalPacket = new PacketSignal();
signalPacket.setSrc(publicKey);
signalPacket.setDst(activeCall); signalPacket.setDst(activeCall);
signalPacket.setSignalType(SignalType.KEY_EXCHANGE); signalPacket.setSignalType(SignalType.KEY_EXCHANGE);
signalPacket.setSharedPublic(Buffer.from(keys.publicKey).toString('hex')); signalPacket.setSharedPublic(Buffer.from(keys.publicKey).toString('hex'));

View File

@@ -1,8 +1,8 @@
export const SERVERS = [ export const SERVERS = [
//'wss://cdn.rosetta-im.com', //'wss://cdn.rosetta-im.com',
//'ws://10.211.55.2:3000', //'ws://10.211.55.2:3000',
//'ws://127.0.0.1:3000', 'ws://127.0.0.1:3000',
'wss://wss.rosetta.im' //'wss://wss.rosetta.im'
]; ];
export function selectServer(): string { export function selectServer(): string {