버전 2026.1.0부터 E2EE(종단 간 암호화)를 지원해요(eSeGeCe All-Access 구독자 전용).
E2EE(종단 간 암호화)는 통신하는 당사자만 교환된 메시지 내용을 읽을 수 있도록 보장해요. 메시지를 라우팅하는 서버조차 복호화할 수 없어요. 이 글에서는 공개키 암호화를 사용해 두 피어 간에 메시지를 안전하게 교환하는 E2EE의 동작 원리를 설명해요.
E2EE 설명
E2EE의 핵심 원리
두 피어 E2EE 시스템에서:
- 각 피어는 장치를 떠나지 않는 개인 키를 소유해요.
- 각 피어는 다른 사람이 볼 수 있는 공개 키를 공개해요.
- 메시지는 발신자 장치에서 암호화되고 수신자 장치에서만 복호화돼요.
- 서버는 신뢰할 수 있는 당사자가 아닌 메시지 중계자 역할만 해요.
키 자료 개요
각 피어(예: Alice와 Bob)는 다음을 보유해요:
- 개인 키
로컬에 저장된 비밀 값이에요. 절대 공유해서는 안 돼요. - 공개 키
개인 키에서 파생된 값이에요. 자유롭게 공유할 수 있어요.
공개 키와 개인 키는 수학적으로 연결돼 있지만, 공개 키를 알아도 개인 키는 알 수 없어요.
1단계: 공개 키 교환
암호화된 통신이 이루어지기 전에 Alice와 Bob은 서로의 공개 키를 알아야 해요.
일반적인 방법:
- 서버가 공개 키를 저장하고 요청 시 전달해요.
- 계정 생성 또는 첫 번째 연락 시 공개 키를 교환해요.
공개 키는 비밀이 아니므로 이 교환은 보안을 침해하지 않아요.
Step 2: Establishing a Shared Secret (ECDH)
메시지를 효율적으로 암호화하기 위해 Alice와 Bob은 먼저 타원 곡선 Diffie-Hellman(ECDH)을 사용해 공유 비밀을 도출해요.
ECDH의 개념적 동작 원리- Alice computes a shared secret using:
- Her private key
- Bob's public key
- Bob computes a shared secret using:
- His private key
- Alice's public key
타원 곡선의 수학적 특성 덕분에 두 계산은 비밀을 전송하지 않고도 동일한 비밀 값을 생성해요.
공유 비밀은 어느 시점에서도 네트워크를 통해 전송되지 않아요.
3단계: 대칭 암호화 키 도출
원시 ECDH 공유 비밀은 암호화에 직접 사용되지 않아요. 대신 SHA-256과 같은 암호화 해시를 사용하는 키 파생 함수(KDF)를 통해 처리돼요.
키 파생의 목적:
- 올바른 길이의 키 생성(예: AES-256의 경우 32바이트)
- 원시 ECDH 출력의 구조적 편향 제거
- 암호화 강건성 향상
결과는 Alice와 Bob만 아는 대칭 암호화 키예요.
Step 4: Encrypting the Message
Alice가 Bob에게 메시지를 보내려 할 때:
- Alice가 메시지를 바이트로 변환해요.
- Alice encrypts the message using a symmetric cipher (commonly AES-GCM) with:
- The derived symmetric key
- A random initialization vector (IV)
- Alice는 암호화된 메시지와 IV를 서버를 통해 Bob에게 보내요.
AES-GCM은 다음을 제공하기 때문에 일반적으로 사용돼요:
- 기밀성(암호화)
- 무결성(변조 감지)
- 인증(위조 메시지 감지)
5단계: 메시지 복호화
Bob이 암호화된 메시지를 받을 때:
- Bob은 ECDH와 동일한 KDF를 사용해 독립적으로 동일한 대칭 키를 도출해요.
- Bob은 대칭 키와 IV를 사용해 메시지를 복호화해요.
- 인증에 성공하면 Bob은 원본 평문을 얻어요.
메시지가 변조되었거나 잘못된 키가 사용되면 복호화가 실패해요.
서버의 역할
이 아키텍처에서 서버는:
- 공개 키를 전달해요
- 암호화된 메시지를 라우팅해요
- 사용자 존재 여부 또는 메타데이터를 관리해요
서버는 다음을 할 수 없어요:
- 공유 비밀을 도출할 수 없어요
- 메시지를 복호화할 수 없어요
- 유효한 암호화 메시지를 위조할 수 없어요
이것이 종단 간 암호화의 핵심 속성이에요.
요약
두 피어 간의 종단 간 암호화는 다음을 결합해 작동해요:
- 공개키 암호화 (키 합의용)
- 대칭 암호화 (효율적인 메시지 암호화용)
- 키 파생 함수 (보안 및 정확성을 위해)
결과는 다음과 같은 시스템이에요:
- 피어만 메시지를 읽을 수 있어요
- 서버는 전송 역할로만 축소돼요
- 개인정보는 정책이 아닌 설계로 보호돼요
This model is the cryptographic backbone of modern secure messaging systems.
E2EE 예제
// ... Create the Server
WSServer := TsgcWebSocketHTTPServer.Create(nil);
WSServer.Port := 80;
WSPE2EE := TsgcWSPServer_E2EE.Create(nil);
WSPE2EE.Server := WSServer;
WSServer.Active := True;
// ... Create 2 clients
WSClient1 := TsgcWebSocketClient.Create(nil);
WSClient1.Host := '127.0.0.1';
WSClient1.Port := 80;
E2EE1 := TsgcWSPClient_E2EE.Create(nil);
E2EE1.Client := WSClient1;
E2EE1.E2EE_Otpions.UserId := 'client-1';
WSClient1.Active := True;
WSClient2 := TsgcWebSocketClient.Create(nil);
WSClient2.Host := '127.0.0.1';
WSClient2.Port := 80;
E2EE2 := TsgcWSPClient_E2EE.Create(nil);
E2EE2.OnE2EEMessageText := OnE2EEMessageTextEvent;
E2EE2.E2EE_Otpions.UserId := 'client-2';
E2EE2.Client := WSClient2;
WSClient2.Active := True;
// ... client-1 send a message to client-2
E2EE1.SendDirectMessage('client-2', 'Hello Client-2');
// ... read the message in the OnE2EEMessageText event
procedure OnE2EEMessageText(Sender: TObject; const aFrom, aText: string);
begin
DoLog('#direct_message: ' + aText);
end;
