-
Oblivious HTTP support in Swift (feat. privacy)Swift 2025. 5. 17. 07:49
안녕하세요. 그린입니다 🍏
이번 포스팅에서는 SwiftNIO Oblivious HTTP에 대해 알아보려고 합니다 🙋🏻
부제를 붙여보자면 Swift에서 구현해보는 프라이버시 보호 HTTP 프로토콜일것 같아요!
Oblivious HTTP support in Swift
최근 애플을 비롯한 여러 기술 기업들이 프라이버시 중심의 네트워크 아키텍처를 강화하는 추세 속에서, Swift 커뮤니티 역시 이에 발맞춘 새로운 시도들을 내놓고 있어요.
바로 SwiftNIO 기반의 Oblivious HTTP 구현이 그 중 하나입니다.
이건 사용자의 식별 정보를 서버로부터 숨기기 위한 새로운 HTTP 통신 모델로 사용자 추적을 차단하면서도 HTTP 요청을 안전하게 처리할 수 있도록 설계되었습니다.
핵심 표준: RFC 9292 & RFC 9457
이 프로젝트는 다음 두 개의 IETF RFC 표준을 기반으로 하고 있습니다.
1️⃣ RFC 9292 - Binary HTTP Messages (BHTTP)
- HTTP 요청/응답을 이진 형식으로 직렬화하는 방법을 정의합니다.
- HTTP 메시지를 네트워크 상에서 압축된 형태로 처리할 수 있어 성능이 향상됩니다.
- Oblivious HTTP뿐 아니라, HTTP/3의 고성능 데이터 전송에도 응용될 수 있습니다.
2️⃣ RFC 9457 - Oblivious HTTP
- 클라이언트가 서버로 HTTP 요청을 암호화하여 중계 서버를 통해 전송하는 방식을 정의합니다.
- 이 암호화된 요청은 최종 origin 서버만 복호화할 수 있으며, 중간 게이트웨이는 요청 내용을 해독할 수 없습니다.
- 이를 통해 요청자 식별 정보 (IP, 쿠키, User-Agent 등)을 origin이 알아볼 수 없게 만듭니다.
SwiftNIO Oblivious HTTP 패키지 구성
Swift에서 이를 구현한 SwiftNIO Oblivious HTTP는 다음과 같은 구조로 구성되어 있어요 😃
1️⃣ ObliviousHTTP - RFC 9292 기반 BHTTP 직렬화 및 역직렬화 구현, SwiftNIO 지원
2️⃣ ObliviousX - Oblivious HTTP에 사용되는 XChaCha20-Poly1305 기반 암호화 기능 구현
BHTTP 메시지 직렬화
한번 예시를 살펴보려고 합니다.
기본적인 BHTTP 요청 직렬화 및 파싱은 아래와 같이 구현됩니다.
import ObliviousHTTP import NIOCore import NIOHTTP1 let serializer = BHTTPSerializer() var buffer = ByteBuffer() serializer.serialize(.request(.head(.init(method: .GET))), into: &buffer) serializer.serialize(.request(.body("hello world!".data(using: .utf8)!)), into: &buffer) serializer.serialize(.request(.end(nil)), into: &buffer) var parser = BHTTPParser(role: .server) parser.append(buffer) parser.completeBodyReceived() while let message = try parser.nextMessage() { print(message) }
일반적인 HTTP 요청을 BHTTP 형식으로 직렬화하고 다시 서버 측에서 역직렬화해 메시지를 복원하는 흐름입니다.
Oblivious HTTP 암호화 흐름
이제 그럼 Oblivious HTTP의 핵심 기능인 Encapsulation과 Decapsulation을 실제 코드 예제를 통해 살펴볼께요!
먼저 OHTTPEncapsulation을 이용해 요청을 캡슐화 합니다.
import ObliviousHTTP import NIOCore // 1. BHTTP 요청 메시지 생성 let request = HTTPRequest(method: .GET, scheme: "https", authority: "example.com", path: "/hello") let payload = ByteBuffer(string: "This is the request body") var buffer = ByteBuffer() let serializer = BHTTPSerializer() serializer.serialize(.request(.head(request)), into: &buffer) serializer.serialize(.request(.body(payload)), into: &buffer) serializer.serialize(.request(.end(nil)), into: &buffer) // 2. 오리진 서버의 공개키 로딩 let publicKeyBytes: [UInt8] = [/* 공개키 바이트 배열 */] let publicKey = try ObliviousKeyConfig(fromBytes: publicKeyBytes) // 3. 요청 캡슐화 let encapsulatedRequest = try OHTTPEncapsulation.encapsulateRequest( request: buffer, config: publicKey ) // 4. 캡슐화된 요청 전송 // encapsulatedRequest.request를 중계 서버로 전송
여기서 OHTTPEncapsulation.encapsulateRequest()를 사용하여 BHTTP 형식의 요청을 캡슐화합니다.
캡슐화된 요청은 중계 서버를 통해 origin 서버로 전달되며, origin 서버는 해당 요청을 복호화해 처리합니다.
다음으로 복호화하는 과정을 보겠습니다 🙋🏻
// 1. 오리진 서버의 개인키 로딩 let privateKeyBytes: [UInt8] = [/* 개인키 바이트 배열 */] let privateKey = try ObliviousPrivateKey(fromBytes: privateKeyBytes) // 2. 응답 복호화 let decryptedResponse = try OHTTPEncapsulation.decapsulateResponse( response: encryptedResponse, privateKey: privateKey ) // 3. 복호화된 응답 처리 // decryptedResponse를 BHTTPParser를 사용하여 처리
이런 방식을 통해 클라이언트와 서버 간 통신에서 사용자의 식별 정보를 보호할 수 있습니다.
참고로, 이 예제는 본문을 참고해 아주 간단히 간소화해 재구성해본것입니다.
When use Oblivious HTTP?
아래와 같은 상황에서 활용될 수 있어요.
1️⃣ Apple Private Relay - 사용자의 IP 주소를 숨기고 웹 트래픽을 암호화
2️⃣ Private Cloud Compute - 사용자가 보낸 민감한 데이터를 클라우드로 전송할 때 식별 불가능하게 처리
3️⃣ 분산 개인 정보 보호 통계 시스템 - 중앙 서버가 각 사용자를 추적하지 않으면서도 집계된 정보를 수집
Conclusion
우리가 프라이버시 보호 HTTP 기술들을 어떻게 프로젝트에서 적용해볼 수 있는지 간략한 가이드를 주고 있습니다.
생소하고 내용이 어려워 보이지만 앞으로의 프라이버시를 중요시 하는 흐름에서는 이 또한 같이 중요한 기술이 될것 같습니다.
References
Introducing Oblivious HTTP support in Swift
We’re excited to introduce an implementation of provisional support for Oblivious HTTP to the Swift ecosystem, with the availability of a new package called SwiftNIO Oblivious HTTP.
www.swift.org
'Swift' 카테고리의 다른 글
gRPC Swift 2 (2) 2025.05.10 swiftly 1.0 (0) 2025.05.06 Swift 6.1 (1) 2025.04.25 Swift Protocol 다중 채택 (0) 2025.02.26 Property Observers (willSet, didSet) (7) 2025.01.27