注意
제안 단계는 종료되었습니다. 공식 사양은 SPEC 를 참조하십시오. 이 제안은 여전히 배경 정보를 위해 참조될 수 있습니다.
개요
이 제안은 다양한 형태의 자동 식별 및 공격에 대한 NTCP(NTCP )의 내성을 높이는 인증된 키 협상 프로토콜을 설명합니다.
이 제안은 다음과 같이 구성됩니다: 보안 목표가 제시된 다음, 기본 프로토콜에 대한 논의가 이어집니다. 다음으로 모든 프로토콜 메시지에 대한 완전한 사양이 제공됩니다. 마지막으로, 라우터 주소 및 버전 식별에 대한 논의가 있습니다. 또한 일반적인 패딩 方案에 대한 공격에 대한 논의가 부록으로 포함되어 있습니다.
동기
NTCP 데이터는 첫 번째 메시지 이후 암호화되므로 payload 분석을 통해 프로토콜 식별을 방지합니다. 그러나 여전히 흐름 분석을 통해 프로토콜 식별이 가능합니다. 첫 번째 4개의 메시지(즉, 핸드셰이크)는 고정된 길이(288, 304, 448, 48 바이트)이기 때문입니다.
랜덤한 양의 랜덤 데이터를 각 메시지에 추가함으로써 이를 훨씬 더 어렵게 만들 수 있습니다.
설계 목표
NTCP 1 및 2를 단일 포트에서 지원하고 자동으로 감지하며 단일 “transport”(즉, RouterAddress)로 NetDB에 게시합니다.
NetDB에 버전 1만, 버전 2만, 또는 버전 1+2를 게시하고 기본적으로 버전 1만 사용합니다(버전 지원을 특정 라우터 버전에 바인딩하지 않음).
모든 구현(Java/i2pd/Kovri/go)이 자신의 일정에 따라 버전 2 지원을 추가할 수 있도록 합니다.
핸드셰이크 및 데이터 메시지를 포함한 모든 NTCP 메시지에 랜덤 패딩을 추가합니다(즉, 길이 오브스커션으로 모든 메시지가 16바이트의 배수가 되지 않도록 함).
옵션 메커니즘을 통해 양측이 최소 및 최대 패딩과/또는 패딩 분포를 요청할 수 있도록 합니다. 패딩 분포의 세부 사항은 구현에 따라 다를 수 있으며 프로토콜 자체에 지정되지 않을 수도 있습니다.
암호화되지 않은 메시지의 내용을 DPI 박스 및 AV 서명이 쉽게 분류하지 못하도록 충분히 오브스커션합니다. 또한 단일 피어 또는 피어 집합으로 보내는 메시지가 비슷한 비트 패턴을 갖지 않도록 합니다.
자바 형식 Ticket1112 로 인해 DH에서 손실된 비트를 수정합니다. 아마도 X25519으로 전환함으로써 가능합니다.
실제 키 파생 함수(KDF)를 사용하여 DH 결과를 직접 사용하는 대신 이를 수정합니다.
“탐지 저항”(Tor가 이를 부르는 것)을 추가합니다. 이는 재전송 저항을 포함합니다.
2방향 인증된 키 교환(2W-AKE)을 유지합니다. 1W-AKE는 우리의 응용 프로그램에 충분하지 않습니다.
게시된 RouterIdentity 서명 키의 변수 유형, 변수 길이 서명을 인증의 일부로 계속 사용합니다. 또한 RouterInfo에 게시된 정적 공개 키를 인증의 또 다른 부분으로 사용합니다.
향후 확장성을 위한 옵션/버전을 핸드셰이크에 추가합니다.
악의적인 MitM TCP 세그먼테이션에 대한 저항을 추가할 수 있다면 합니다.
연결 설정에 필요한 CPU를 크게 추가하지 않습니다. 가능하다면 이를 크게 줄입니다.
메시지 인증(MAC)을 추가하고 Adler 체크섬을 제거합니다. 아마도 HMAC-SHA256 및 Poly1305를 사용할 수 있습니다.
I2NP 헤더를 단축하고 단순화합니다.
- SSU와 마찬가지로 만기 시간을 4바이트로 단축합니다.
- 1바이트截断 SHA256 체크섬을 제거합니다.
가능하다면 4개의 메시지, 2회의 왕복 핸드셰이크를 3개의 메시지, 1회의 왕복 핸드셰이크로 단축합니다. 이는 Bob의 메시지 4의 서명을 메시지 2로 이동하는 것을 필요로 합니다. 10년 전 이메일/상태/미팅 아카이브에서 이유를 조사합니다.
패딩 이전의 프로토콜 오버헤드를 최소화합니다. 패딩이 추가되고 가능하다면 많은 패딩이 추가되더라도 패딩 이전의 오버헤드는 여전히 오버헤드입니다. 저대역폭 노드는 NTCP2를 사용할 수 있어야 합니다.
재전송 및 왜곡 감지를 위한 타임스탬프를 유지합니다.
타임스탬프에서 2038년 문제를 피합니다. 적어도 2106년까지 작동해야 합니다.
최대 메시지 크기를 16K에서 32K 또는 64K로 늘립니다.
새로운 암호학적 원시 함수는 Java(1.7), C++ 및 Go 라우터 구현을 위한 라이브러리에서 쉽게 사용할 수 있어야 합니다.
디자인에 Java, C++ 및 Go 라우터 개발자 대표를 포함합니다.
변경을 최소화합니다(그러나 여전히 많은 변경이 있을 것입니다).
공통 코드 세트에서 버전 1과 2를 모두 지원합니다(이것은 구현에 따라 다를 수 있으며 경우에 따라 구현에 의존할 수 있음).
비목표
완벽한 DPI 저항… 이는 플러그인 전송(Prop109 )입니다.
TLS 기반(또는 HTTPS와 유사한) 전송… 이는 Prop104 입니다.
대칭 스트림 암호를 변경하는 것이 괜찮습니다.
타이밍 기반 DPI 저항(메시지 간 타이밍/지연은 구현에 따라 다를 수 있으며 메시지 내 지연은 메시지 전송 전에 임의로 도입될 수 있음).
세션 참여에 대한 부인 가능성(서명이 포함되어 있으므로).
다음은 부분적으로 재고되거나 논의될 수 있는 비목표입니다.
DPI 시스템에 대한 보호 정도
양자 보안
부인 가능성
관련 목표
- NTCP 1/2 테스트 설정 구현
보안 목표
우리는 세 가지 당사자를 고려합니다.
- 앨리스, 새로운 세션을 설정하고자 하는 사람.
- 밥, 앨리스가 세션을 설정하고자 하는 사람.
- 몰리, 앨리스와 밥 사이의 “중간자”.
최대 두 참가자가 능동적 공격에 참여할 수 있습니다.
앨리스와 밥은 모두 정적 키 쌍을 소유하고 있으며, 이는 그들의 RouterIdentity에 포함되어 있습니다.
제안된 프로토콜은 앨리스와 밥이 공유된 비밀 키(K)를 다음과 같은 요구 사항에 따라 동의하도록 허용하려고 합니다.
개인 키 보안: 밥이나 몰리도 앨리스의 정적 개인 키에 대해 아무것도 배우지 못합니다. 대칭적으로, 앨리스도 밥의 정적 개인 키에 대해 아무것도 배우지 못합니다.
세션 키 K는 앨리스와 밥만이 알고 있습니다.
완전 전방 비밀성: 동의된 세션 키는 미래에 비밀로 유지되며, 앨리스와/또는 밥의 정적 개인 키가 동의된 키 이후에 공개되더라도如此합니다.
2방향 인증: 앨리스는 자신이 밥과 세션을 설정했다는 것을 확신할 수 있으며, 그 반대도 마찬가지입니다.
온라인 DPI에 대한 보호: 앨리스와 밥이 프로토콜에 참여하고 있는지 단순한 DPI 기술만으로 감지하는 것이 간단하지 않도록 합니다. 아래를 참조하십시오.
제한된 부인 가능성: 앨리스나 밥이 프로토콜 참여를 부인할 수는 없지만, 어느 한 쪽이 공유된 키를 누설하면 다른 쪽은 전송된 데이터의 내용을 부인할 수 있습니다.
추가 DPI 논의
온라인 DPI와 오프라인 DPI의 두 가지 구성 요소를 가정합니다.
1) 온라인 DPI
실시간으로 모든 흐름을 검사하는 온라인 DPI. 연결을 차단하거나 조작할 수 있습니다. 연결 데이터 또는 메타데이터를 오프라인 분석을 위해 식별하고 저장할 수 있습니다. 온라인 DPI는 I2P 네트워크 데이터베이스에 액세스할 수 없습니다. 온라인 DPI는 제한된 실시간 계산 능력만을 가지고 있으며, 길이 계산, 필드 검사 및 XOR과 같은 단순 계산이 포함됩니다. 온라인 DPI는 AES, AEAD 및 해싱과 같은 빠른 실시간 암호화 함수를 가지고 있지만, 이러한 함수를 대부분의 흐름 또는 모든 흐름에 적용하는 것은 너무 비용이 많이 듭니다. 이러한 암호화 연산의 적용은 이전에 오프라인 분석에 의해 식별된 IP/포트 조합의 흐름에만 적용됩니다. 온라인 DPI는 DH 또는 elligator2와 같은 높은 오버헤드 암호화 함수를 수행할 수 없습니다. 온라인 DPI는 I2P를 감지하기 위해 특별히 설계되지 않았지만, 이 목적을 위한 제한된 분류 규칙을 가질 수 있습니다.
온라인 DPI에 의한 프로토콜 식별을 방지하는 것이 목표입니다.
온라인 DPI 또는 “직접” DPI의 개념은 다음을 포함합니다.
대상에 의해 전송되거나 수신되는 모든 데이터를 검사하는 능력.
관찰된 데이터에 작업을 수행하는 능력, 예를 들어 블록 암호 또는 해시 함수를 적용하는 것.
이전에 전송된 메시지와 비교하는 능력.
패킷을 수정, 지연 또는 분할하는 능력.
그러나 온라인 DPI는 다음과 같은 제한을 가집니다.
IP 주소를 라우터 해시로 매핑할 수 없습니다. 이는 실시간 네트워크 데이터베이스 액세스가 있는 경우에는 간단하지만, I2P를 대상으로 하는 DPI 시스템을 위해 특별히 설계된 경우에는 그렇지 않을 수 있습니다.
프로토콜을 감지하기 위해 타이밍 정보를 사용할 수 없습니다.
일반적으로 온라인 DPI 툴박스는 I2P 감지를 위한 특별한 도구를 포함하지 않습니다. 이는 기계 학습 시스템이나 고도로 구성 가능한 DPI 툴을 배제하지 않지만, 다른 요구 사항을 충족하는 경우에만如此합니다.
Noise 프로토콜 프레임워크
이 제안은 Noise 프로토콜 프레임워크(NOISE )를 기반으로 합니다(2017-10-04 개정 33). Noise는 SSU 프로토콜의 기초가 되는 Station-To-Station 프로토콜과 유사한 속성을 가지고 있습니다. Noise 용어로, 앨리스는 초기자이고, 밥은 응답자입니다.
NTCP2는 Noise_XK_25519_ChaChaPoly_SHA256 Noise 프로토콜을 기반으로 합니다. (초기 키 파생 함수의 실제 식별자는 I2P 확장으로 “Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256"를 나타냄).
이 Noise 프로토콜은 다음과 같은 원시 함수를 사용합니다.
핸드셰이크 패턴: XK 앨리스가 밥에게 자신의 키를 전송합니다(X). 앨리스는 이미 밥의 정적 키를 알고 있습니다(K).
DH 함수: X25519 X25519 DH는 32바이트 키 길이를 사용하며 RFC-7748 에 지정된 대로입니다.
암호 함수: ChaChaPoly AEAD_CHACHA20_POLY1305는 RFC-7539 섹션 2.8에 지정된 대로입니다. 12바이트 논스, 첫 4바이트는 0으로 설정됩니다.
해시 함수: SHA256 표준 32바이트 해시, 이미 I2P에서 광범위하게 사용됩니다.
프레임워크 추가
이 제안은 Noise_XK_25519_ChaChaPoly_SHA256에 다음과 같은 향상을 정의합니다. 이는 일반적으로 NOISE 섹션 13의 지침을 따릅니다.
평문 임시 키는 알려진 키와 IV를 사용하는 AES 암호화로 오브스커션됩니다. 이는 elligator2보다 빠릅니다.
랜덤한 평문 패딩이 메시지 1과 2에 추가됩니다. 평문 패딩은 핸드셰이크 해시(MixHash) 계산에 포함됩니다. 메시지 2 및 메시지 3 부분 1의 KDF를 참조하십시오. 랜덤한 AEAD 패딩이 메시지 3 및 데이터 단계 메시지에 추가됩니다.
TCP를 위한 Noise와 마찬가지로 obfs4와 같이 2바이트 프레임 길이 필드가 추가됩니다. 데이터 단계 메시지에서만 사용됩니다. 메시지 1 및 2 AEAD 프레임은 고정 길이입니다. 메시지 3 부분 1 AEAD 프레임은 고정 길이입니다. 메시지 3 부분 2 AEAD 프레임 길이는 메시지 1에서 지정됩니다.
2바이트 프레임 길이 필드는 obfs4와 마찬가지로 SipHash-2-4로 오브스커션됩니다.
메시지 1, 2, 3 및 데이터 단계의 페이로드 형식이 정의됩니다. 이는 Noise에서 정의되지 않습니다.
I2P를 위한 새로운 암호학적 원시 함수
기존 I2P 라우터 구현에는 다음과 같은 표준 암호학적 원시 함수에 대한 구현이 필요합니다. 이들은 현재 I2P 프로토콜에 필요하지 않습니다.
X25519 키 생성 및 DH
AEAD_ChaCha20_Poly1305(이하 ChaChaPoly로 약칭)
SipHash-2-4
처리 오버헤드 추정
핸드셰이크 메시지의 크기:
- 64 바이트 + 패딩(NTCP는 288 바이트)
- 64 바이트 + 패딩(NTCP는 304 바이트)
- 약 64 바이트 + 앨리스 라우터 정보 + 패딩 평균 라우터 정보 크기는 약 750 바이트 총 평균 814 바이트(패딩 전) (NTCP는 448 바이트)
- NTCP2에서는 필요하지 않음(NTCP는 48 바이트)
패딩 전 총 크기: NTCP2: 942 바이트 NTCP: 1088 바이트 앨리스가 데이터베이스 저장 메시지(自己的 라우터 정보)를 보내기 위해 밥에게 연결하는 경우, 이 메시지는 필요하지 않으므로 약 800 바이트를 절약할 수 있습니다.
핸드셰이크를 완료하고 데이터 단계를 시작하는 데 각 당사자가 수행해야 하는 암호화 연산은 다음과 같습니다.
- AES: 2
- SHA256: 7(앨리스), 6(밥)(모든 연결에 대해 미리 계산된 1개의 앨리스 및 2개의 밥을 제외하고)
- HMAC-SHA256: 19
- ChaChaPoly: 4
- X25519 키 생성: 1
- X25519 DH: 3
- 서명 검증: 1(밥)(앨리스는 RI 생성 시 이미 서명함) 아마도 Ed25519(RI 서명 유형에 따라 다름)
데이터 단계의 각 메시지에 대해 각 당사자가 수행해야 하는 암호화 연산은 다음과 같습니다.
- SipHash: 1
- ChaChaPoly: 1
메시지
모든 NTCP2 메시지는 65537 바이트 이하의 길이를 가집니다. 메시지 형식은 Noise 메시지를 기반으로 하며, 프레임 및 구별 가능성에 대한 수정이 포함됩니다. 표준 Noise 라이브러리를 사용하는 구현은 받은 메시지를 Noise 메시지 형식으로/from 변환하기 위해 전처리해야 할 수 있습니다. 모든 암호화된 필드는 AEAD 암호문입니다.
설립 순서는 다음과 같습니다.
앨리스 밥
SessionRequest ------------------->
<------------------- SessionCreated
SessionConfirmed ----------------->
Noise 용어로, 설립 및 데이터 순서는 다음과 같습니다. (페이로드 보안 속성):
XK(s, rs): 인증 기밀성
<- s
...
-> e, es 0 2
<- e, ee 2 1
-> s, se 2 5
<- 2 5
세션이 설정되면 앨리스와 밥은 데이터 메시지를 교환할 수 있습니다.
모든 메시지 유형(SessionRequest, SessionCreated, SessionConfirmed, Data 및 TimeSync)은 이 섹션에서 지정됩니다.
일부 표기법:
- RH_A = 앨리스의 라우터 해시(32 바이트)
- RH_B = 밥의 라우터 해시(32 바이트)
인증된 암호화
핸드셰이크 단계와 데이터 단계를 위한 3개의 별도 인증된 암호화 인스턴스(CipherStates)가 있습니다. 각각은 KDF에서 자신의 키를 가집니다.
암호화된/인증된 데이터는 다음과 같이 표시됩니다.
+----+----+----+----+----+----+----+----+
| |
+ +
| 암호화된 및 인증된 데이터 |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
ChaCha20/Poly1305
암호화된 및 인증된 데이터 형식.
암호화/복호화 함수의 입력:
k :: 32 바이트 암호 키, KDF에서 생성됨
논스 :: 카운터 기반 논스, 12 바이트.
0에서 시작하여 각 메시지마다 증가합니다.
첫 4바이트는 항상 0입니다.
마지막 8바이트는 카운터이며, 리틀 엔디안으로 인코딩됩니다.
최대 값은 2**64 - 2입니다.
이 값에 도달하면 연결을 종료하고 다시 시작해야 합니다.
값 2**64 - 1은 절대 전송되어서는 안 됩니다.
연관 데이터 :: 핸드셰이크 단계에서:
연관 데이터, 32 바이트.
이전 데이터의 SHA256 해시.
데이터 단계에서:
0 바이트
데이터 :: 평문 데이터, 0 또는 더 많은 바이트
암호화 함수의 출력, 복호화 함수의 입력:
+----+----+----+----+----+----+----+----+
|Obfs Len | |
+----+----+ +
| ChaCha20 암호화된 데이터 |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
| Poly1305 메시지 인증 코드 |
+ (MAC) +
| 16 바이트 |
+----+----+----+----+----+----+----+----+
Obfs Len :: (암호화된 데이터 + MAC) 이후의 길이, 16 - 65535
SipHash를 사용한 오브스커션(아래 참조)
메시지 1 또는 2, 또는 메시지 3 부분 1에서 사용되지 않음
메시지 3 부분 1에서 사용되지 않음(길이가 메시지 1에서 지정됨)
암호화된 데이터 :: 평문 데이터와 동일한 크기, 0 - 65519 바이트
MAC :: Poly1305 메시지 인증 코드, 16 바이트
ChaCha20에 대해 여기서 설명한 내용은 RFC-7539 와 동일하며, TLS RFC-7905 에서도 유사하게 사용됩니다.
참고
ChaCha20은 스트림 암호이므로 평문은 패딩할 필요가 없습니다. 추가 키 스트림 바이트는 폐기됩니다.
암호 키(256 비트)는 SHA256 KDF를 통해 동의됩니다. 각 메시지의 KDF 세부 정보는 아래의 별도 섹션에 있습니다.
메시지 1, 2 및 메시지 3의 첫 번째 부분의 ChaChaPoly 프레임은 알려진 크기입니다. 메시지 3의 두 번째 부분부터 프레임은 가변 크기입니다. 메시지 3 부분 1의 프레임 크기는 메시지 1에서 지정됩니다. 데이터 단계에서 프레임에는 SipHash로 오브스커션된 2바이트 길이가 앞에 추가됩니다.
패딩은 메시지 1 및 2의 경우 인증된 데이터 프레임 외부에 있습니다. 패딩은 다음 메시지의 KDF에서 사용되므로 임의로 수정하면 감지됩니다. 메시지 3부터 패딩은 인증된 데이터 프레임 내부에 있습니다.
AEAD 오류 처리
메시지 1, 2 및 메시지 3의 첫 번째 및 두 번째 부분의 AEAD 메시지 크기는 미리 알려져 있습니다. AEAD 인증 실패 시 수신자는 추가 메시지 처리를 중지하고 응답 없이 연결을 종료해야 합니다. 이는 비정상적인 종료(TCP RST)여야 합니다.
탐지 저항을 위해 메시지 1에서 AEAD 실패 후, 밥은 임의의 시간 제한(범위 TBD)을 설정한 후 임의의 바이트 수(TBD 범위)를 읽은 후 소켓을 종료해야 합니다. 밥은 반복적인 실패에 대한 IP 주소의 블랙리스트를 유지해야 합니다.
데이터 단계에서 AEAD 메시지 크기는 SipHash로 “암호화"됩니다. 복호화 오라클을 생성하지 않도록 주의해야 합니다. 데이터 단계의 AEAD 인증 실패 시 수신자는 임의의 시간 제한(TBD 범위)을 설정한 후 임의의 바이트 수(TBD 범위)를 읽은 후, 종료 이유 코드가 포함된 페이로드와 함께 연결을 종료해야 합니다.
데이터 단계에서 유효하지 않은 길이 필드 값을 위해 동일한 오류 동작을 취합니다.
키 파생 함수 (KDF) (핸드셰이크 메시지 1)
KDF는 DH 결과에서 핸드셰이크 단계의 암호 키 k를 생성합니다. RFC-2104 에서 정의한 대로 HMAC-SHA256(key, data)를 사용합니다. 이것은 Noise 사양에서 InitializeSymmetric(), MixHash() 및 MixKey() 함수와 정확히 동일합니다.
1) SessionRequest
앨리스가 밥에게 전송합니다.
Noise 내용: 앨리스의 임시 키 X Noise 페이로드: 16바이트 옵션 블록 비-Noise 페이로드: 랜덤 패딩
키 파생 함수 (KDF) (핸드셰이크 메시지 2 및 메시지 3 부분 1)
// 메시지 1 KDF에서 저장된 h를 취합니다
// MixHash(암호화된 페이로드)
h = SHA256(h || 메시지 1의 32바이트 암호화된 페이로드)
// MixHash(패딩)
// 패딩 길이가 0이 아닌 경우에만
h = SHA256(h || 메시지 1의 랜덤 패딩)
이것은 "e" 메시지 패턴입니다:
밥은 자신의 임시 DH 키 쌍 e를 생성합니다.
// h는 메시지 1 KDF에서
// 밥의 임시 키 Y
// MixHash(e.pubkey)
// || 아래는 연결을 의미함
h = SHA256(h || e.pubkey);
// h는 메시지 2의 AEAD에 대한 연관 데이터로 사용됩니다
// 메시지 3 KDF를 위해 h를 유지합니다
이것은 "e" 메시지 패턴의 끝입니다.
이것은 "ee" 메시지 패턴입니다:
// DH(e, re)
정의 input_key_material = 32바이트 DH 결과, 앨리스의 임시 키와 밥의 임시 키
설정 input_key_material = X25519 DH 결과
// 앨리스의 임시 키를 메모리에서 지움, 더 이상 필요하지 않음
// 앨리스:
e(공개 및 개인) = (모두 0)
// 밥:
re = (모두 0)
// MixKey(DH())
정의 temp_key = 32 바이트
정의 HMAC-SHA256(key, data) [RFC-2104](https://tools.ietf.org/html/rfc2104)에서
// 체인 키와 DH 결과에서 임시 키를 생성합니다
// ck는 메시지 1 KDF의 체인 키
temp_key = HMAC-SHA256(ck, input_key_material)
// DH 결과를 메모리에서 지움, 더 이상 필요하지 않음
input_key_material = (모두 0)
// 출력 1
// 임시 키에서 새로운 체인 키를 설정합니다
// byte() 아래는 단일 바이트를 의미함
ck = HMAC-SHA256(temp_key, byte(0x01)).
// 출력 2
// 암호 키 k를 생성합니다
정의 k = 32 바이트
// || 아래는 연결을 의미함
// byte() 아래는 단일 바이트를 의미함
k = HMAC-SHA256(temp_key, ck || byte(0x02)).
// temp_key를 메모리에서 지움, 더 이상 필요하지 않음
temp_key = (모두 0)
// 메시지 3 KDF를 위해 체인 키 ck를 유지합니다
이것은 "ee" 메시지 패턴의 끝입니다.
2) SessionCreated
밥이 앨리스에게 전송합니다.
Noise 내용: 밥의 임시 키 Y Noise 페이로드: 16바이트 옵션 블록 비-Noise 페이로드: 랜덤 패딩
키 파생 함수 (KDF) (핸드셰이크 메시지 3 부분 2)
이것은 "se" 메시지 패턴입니다:
// DH(s, re) == DH(e, rs)
정의 input_key_material = 32바이트 DH 결과, 앨리스의 정적 키와 밥의 임시 키
설정 input_key_material = X25519 DH 결과
// 밥의 임시 키를 메모리에서 지움, 더 이상 필요하지 않음
// 앨리스:
re = (모두 0)
// 밥:
e(공개 및 개인) = (모두 0)
// MixKey(DH())
정의 temp_key = 32 바이트
정의 HMAC-SHA256(key, data) [RFC-2104](https://tools.ietf.org/html/rfc2104)에서
// 체인 키와 DH 결과에서 임시 키를 생성합니다
// ck는 메시지 1 KDF의 체인 키
temp_key = HMAC-SHA256(ck, input_key_material)
// DH 결과를 메모리에서 지움, 더 이상 필요하지 않음
input_key_material = (모두 0)
// 출력 1
// 임시 키에서 새로운 체인 키를 설정합니다
// byte() 아래는 단일 바이트를 의미함
ck = HMAC-SHA256(temp_key, byte(0x01)).
// 출력 2
// 암호 키 k를 생성합니다
정의 k = 32 바이트
// || 아래는 연결을 의미함
// byte() 아래는 단일 바이트를 의미함
k = HMAC-SHA256(temp_key, ck || byte(0x02)).
// 메시지 3 부분 1의 h는 메시지 3 부분 2의 AEAD에 대한 연관 데이터로 사용됩니다
// EncryptAndHash(페이로드)
// EncryptWithAd(h, 페이로드)
// AEAD_ChaCha20_Poly1305(key, nonce, associatedData, data)
// n은 0
ciphertext = AEAD_ChaCha20_Poly1305(k, n++, h, 페이로드)
// MixHash(ciphertext)
// || 아래는 연결을 의미함
h = SHA256(h || ciphertext);
// 데이터 단계 KDF를 위해 체인 키 ck를 유지합니다
// 데이터 단계 추가 대칭 키(SipHash) KDF를 위해 h를 유지합니다
이것은 "se" 메시지 패턴의 끝입니다.
// temp_key를 메모리에서 지움, 더 이상 필요하지 않음
temp_key = (모두 0)
3) SessionConfirmed
앨리스가 밥에게 전송합니다.
Noise 내용: 앨리스의 정적 키 Noise 페이로드: 앨리스의 RouterInfo 및 랜덤 패딩 비-Noise 페이로드: 없음
키 파생 함수 (KDF) (데이터 단계)
데이터 단계에서는 0 길이의 연관 데이터 입력을 사용합니다.
KDF는 체인 키 ck에서 두 개의 암호 키 k_ab 및 k_ba를 생성합니다. RFC-2104 에서 정의한 대로 HMAC-SHA256(key, data)를 사용합니다. 이것은 Noise 사양에서 Split() 함수와 정확히 동일합니다.
4) 데이터 단계
Noise 페이로드: 아래에서 정의한 대로, 랜덤 패딩 포함 비-Noise 페이로드: 없음
SipHash 오브스커션된 길이
참조: SipHash
Raw 내용
+----+----+----+----+----+----+----+----+
|obf size | |
+----+----+ +
| |
+ ChaChaPoly 프레임 |
| 암호화된 및 인증된 |
+ key는 데이터 단계 KDF에서 정의된 k_ab 및 k_ba
| n은 0에서 시작하여 각 프레임마다 증가합니다
| 연관 데이터는 없음 |
+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
obf size :: 2바이트 길이, SipHash로 오브스커션됨
디오브스커션 후: 16 - 65535
길이 필드 포함한 최소 크기는 18바이트입니다.
길이 필드 포함한 최대 크기는 65537바이트입니다.
오브스커션된 길이는 2바이트입니다.
최대 ChaChaPoly 프레임은 65535바이트입니다.
### 비암호화된 데이터
암호화된 프레임에는 0개 이상의 블록이 있습니다.
각 블록에는 1바이트 식별자, 2바이트 길이 및 0개 이상의 데이터 바이트가 있습니다.
### 블록 순서 규칙
핸드셰이크 메시지 3 부분 2에서, 순서는 다음과 같아야 합니다.
RouterInfo, 옵션이 있으면 옵션, 패딩이 있으면 패딩.
### DateTime
특수한 경우로 시간 동기화를 위한 것입니다.
### 옵션
업데이트된 옵션을 전달합니다.
옵션에는 최소 및 최대 패딩이 포함됩니다.
### RouterInfo
앨리스의 RouterInfo를 밥에게 전달합니다.
핸드셰이크 메시지 3 부분 2에서 사용됩니다.
### I2NP 메시지
단일 I2NP 메시지에 수정된 헤더가 있습니다.
I2NP 메시지는 블록이나 ChaChaPoly 프레임을 통해 절대 분할되지 않습니다.
### 종료
Noise는 명시적인 종료 메시지를 권장합니다.
원래 NTCP에는 종료 메시지가 없습니다.
연결을 종료합니다.
이것은 프레임의 마지막 비-패딩 블록이어야 합니다.
### 패딩
이것은 AEAD 프레임 내부의 패딩을 위한 것입니다.
메시지 1 및 2의 패딩은 AEAD 프레임 외부에 있습니다.
메시지 3 및 데이터 단계의 모든 패딩은 AEAD 프레임 내부에 있습니다.
### 기타 블록 유형
구현은 메시지 3 부분 2를 제외하고는 미래의 호환성을 위해 알 수 없는 블록 유형을 무시해야 합니다.
### 미래 작업
- 패딩 길이는 메시지당 결정되거나, 랜덤한 지연이 추가되거나, 패딩 분포에 대한 추정치를 사용하여 결정될 수 있습니다.
이러한 대책은 DPI를 저항하기 위해 포함됩니다.
### 5) 종료
연결은 정상 또는 비정상적인 TCP 소켓 종료를 통해 종료될 수 있습니다.
또는 Noise가 권장하는 대로 명시적인 종료 메시지를 통해 종료될 수 있습니다.
명시적인 종료 메시지는 데이터 단계에서 정의됩니다.
## 게시된 RouterInfo
### 게시된 주소
게시된 RouterAddress(RouterInfo의 일부)는 프로토콜 식별자로 "NTCP" 또는 "NTCP2"를 가집니다.
## 버전 감지
"NTCP"로 게시된 경우 라우터는 들어오는 연결에 대한 프로토콜 버전을 자동으로 감지해야 합니다.
## 변형, 폴백 및 일반 문제
- 앨리스와 밥이 모두 NTCP2를 지원하는 경우, 앨리스는 NTCP2로 연결해야 합니다.
- 앨리스가 NTCP2를 사용하여 밥에게 연결하는 데 어떤 이유로든 실패하면 연결이 실패합니다.
앨리스는 NTCP 1로 다시 시도해서는 안 됩니다.
## 부록 A: 패딩 方案
이 섹션은 공격자가 패딩되지 않은 메시지의 길이 분포를 발견할 수 있는 방법에 대해 논의합니다.
패딩되지 않은 바이트 수를 설명하는 랜덤 변수 N을 가정하고, 패딩 바이트 수를 설명하는 랜덤 변수 P를 가정합니다.
메시지의 총 크기는 N + P입니다.
## 부록 B: 랜덤 지연
타이밍 기반 DPI 저항(메시지 간 타이밍/지연은 구현에 따라 다를 수 있으며 메시지 내 지연은 임의로 도입될 수 있음).
인공 지연(Obfs4에서 IAT 또는 인터-어라이벌 타임이라고 함)은 프로토콜 자체와 독립적입니다.
## 참고문헌
* [IACR-1150](https://eprint.iacr.org/2015/1150)
* [NetDB](/docs/overview/network-database/)
* [NOISE](https://noiseprotocol.org/noise.html)
* [NTCP](/docs/ntcp/)
* [Prop104](/proposals/104-tls-transport/)
* [Prop109](/proposals/109-pt-transport/)
* [RFC-2104](https://tools.ietf.org/html/rfc2104)
* [RFC-3526](https://tools.ietf.org/html/rfc3526)
* [RFC-6151](https://tools.ietf.org/html/rfc6151)
* [RFC-7539](https://tools.ietf.org/html/rfc7539)
* [RFC-7748](https://tools.ietf.org/html/rfc7748)
* [RFC-7905](https://tools.ietf.org/html/rfc7905)
* [RouterAddress](/docs/specs/common-structures/#routeraddress)
* [RouterIdentity](/docs/specs/common-structures/#routeridentity)
* [SIDH] De Feo, Luca; Jao, Plut., Towards quantum-resistant cryptosystems from supersingular elliptic curve isogenies
* [SigningPublicKey](/docs/specs/common-structures/#signingpublickey)
* [SipHash](https://www.131002.net/siphash/)
* [SPEC](/docs/specs/ntcp2/)
* [SSU](/docs/specs/ssu2/)
* [STS] Diffie, W.; van Oorschot P. C.; Wiener M. J., Authentication and Authenticated Key Exchanges
* [Ticket1112](https://trac.i2p2.i2p/ticket/1112)
* [Ticket1849](https://trac.i2p2.i2p/ticket/1849)
* ["Faster and Timing-Attack Resistant AES-GCM" by Emilia Käsper and Peter Schwabe](/docs/research/kasper2009-fast-aesgcm.pdf)
* ["Nonce-Disrespecting Adversaries: Practical Forgery Attacks on GCM in TLS" by H. Böck, A. Zauner, S. Devlin, J. Somorovsky, P. Jovanovic](https://www.blackhat.com/docs/us-16/materials/us-16-Devlin-Nonce-Disrespecting-Adversaries-Practical-Forgery-Attacks-On-GCM-In-TLS.pdf)
* ["CAESAR submission: Ketje" by Guido Bertoni, Joan Daemen, Michaël Peeters, Gilles Van Assche, Ronny Van Keer](https://eprint.iacr.org/2014/613.pdf)
* ["ChaCha20 and Poly1305 for IETF protocols" by Adam Langley](https://www.imperialviolet.org/2013/10/07/chacha20.html)
* [RFC 7539](https://tools.ietf.org/html/rfc7539)