참고 사항
네트워크 배포 및 테스트 진행 중입니다. 소규모 수정이 있을 수 있습니다. 공식 사양은 SPEC 을 참조하세요.
다음 기능들은 0.9.46 버전 기준으로 구현되지 않았습니다:
- MessageNumbers, Options, Termination 블록
- 프로토콜 계층 응답
- 제로 정적 키
- 멀티캐스트
개요
이 문서는 I2P 시작 이후 처음으로 ElGamal/AES+SessionTags Elg-AES 를 대체하기 위한 새로운 종단 간 암호화 방식을 제안합니다.
다음과 같은 기존 작업을 기반으로 합니다:
- 공통 구조 사양 Common Structures
- LS2 포함 I2NP 사양
- ElGamal/AES+Session Tags Elg-AES
- http://zzz.i2p/topics/1768 새로운 비대칭 암호화 개요
- 저수준 암호화 개요 CRYPTO-ELG
- ECIES http://zzz.i2p/topics/2418
- NTCP2 Proposal 111
- 123 새로운 netDB 항목
- 142 새로운 암호화 템플릿
- Noise 프로토콜
- Signal 더블 래칫 알고리즘
목표는 종단 간, 목적지 간 통신을 위한 새로운 암호화를 지원하는 것입니다.
설계는 Signal의 더블 래칫을 포함하는 Noise 핸드셰이크 및 데이터 단계를 사용합니다.
이 제안서에서 Signal과 Noise에 대한 모든 참조는 배경 정보를 위한 것입니다. Signal 및 Noise 프로토콜에 대한 지식은 이 제안서를 이해하거나 구현하는 데 필요하지 않습니다.
현재 ElGamal 사용 사례
리뷰 차원에서, ElGamal 256바이트 공개 키는 다음 데이터 구조에서 찾을 수 있습니다. 공통 구조 사양을 참조하세요.
라우터 ID에 이는 라우터의 암호화 키입니다.
목적지에 목적지의 공개 키는 이전의 i2cp-to-i2cp 암호화에 사용되었으며, 0.6 버전에서 비활성화되었습니다. 현재는 LeaseSet 암호화를 위한 IV로만 사용되며, 이는 더 이상 사용되지 않습니다. LeaseSet에 있는 공개 키가 대신 사용됩니다.
LeaseSet에 이는 목적지의 암호화 키입니다.
LS2에 이는 목적지의 암호화 키입니다.
키 인증서의 EncTypes
리뷰 차원에서, 서명 유형을 지원하기 위해 암호화 유형 지원을 추가했습니다. 암호화 유형 필드는 Destination과 RouterIdentity 모두에서 항상 0입니다. 이 값을 변경할지 여부는 아직 결정되지 않았습니다. 공통 구조 사양 Common Structures 을 참조하세요.
비대칭 암호화 사용 사례
리뷰 차원에서, 우리는 ElGamal을 다음 용도로 사용합니다:
터널 생성 메시지 (키는 RouterIdentity에 있음) 이 제안서에서 다루지 않습니다. 제안서 152 Proposal 152 참조.
라우터 간 netdb 및 기타 I2NP 메시지 암호화 (키는 RouterIdentity에 있음) 이 제안서에 의존합니다. 1)에 대한 제안서가 필요하거나 키를 RI 옵션에 넣어야 합니다.
클라이언트 종단 간 ElGamal+AES/SessionTag (키는 LeaseSet에 있음, 목적지 키는 사용되지 않음) 이 제안서에서 다룹니다.
NTCP1 및 SSU의 임시 DH 이 제안서에서 다루지 않습니다. NTCP2는 제안서 111 참조. SSU2에 대한 현재 제안서 없음.
목표
- 하위 호환성 유지
- LS2 (제안서 123)에 의존하고 이를 기반으로 함
- NTCP2 (제안서 111)에 추가된 새로운 암호화 또는 프리미티브 활용
- 지원을 위해 새로운 암호화 또는 프리미티브 필요 없음
- 암호화와 서명의 분리 유지; 현재 및 미래 모든 버전 지원
- 목적지를 위한 새로운 암호화 활성화
- 라우터를 위한 새로운 암호화 활성화 (단, 마늘 메시지에 한함) - 터널 생성은 별도 제안서
- 비트토런트 등 32바이트 이진 목적지 해시에 의존하는 기능 파손 방지
- 임시-정적 DH를 통한 0-RTT 메시지 전달 유지
- 이 프로토콜 계층에서 메시지 버퍼링/큐잉 요구 없음; 응답 대기 없이 양방향 무제한 메시지 전달 계속 지원
- 1 RTT 후 임시-임시 DH로 업그레이드
- 메시지 순서 외 처리 유지
- 256비트 보안 유지
- 전방향 보안 추가
- 인증 (AEAD) 추가
- ElGamal보다 훨씬 더 CPU 효율적
- Java jbigi에 의존하지 않고도 DH를 효율적으로 만들기
- DH 연산 최소화
- ElGamal (514바이트 ElGamal 블록)보다 훨씬 더 대역폭 효율적
- 동일 터널에서 새 암호화와 기존 암호화 동시 지원
- 수신자가 동일 터널에서 새 암호화와 기존 암호화를 효율적으로 구분 가능
- 다른 사용자는 새 암호화와 기존 암호화 또는 미래 암호화를 구분할 수 없음
- 새 세션과 기존 세션 길이 분류 제거 (패딩 지원)
- 새로운 I2NP 메시지 필요 없음
- AES 페이로드의 SHA-256 체크섬을 AEAD로 대체
- 전달 및 수신 세션을 바인딩하여 응답이 외부 통신이 아닌 프로토콜 내에서 발생 가능 이는 또한 응답이 즉시 전방향 보안을 가질 수 있게 합니다.
- CPU 오버헤드로 인해 현재는 수행하지 않는 특정 메시지 (RouterInfo 저장소)의 종단 간 암호화 활성화
- I2NP 마늘 메시지 또는 마늘 메시지 전달 지시 형식 변경하지 않음
- 마늘 클로브 세트 및 클로브 형식에서 사용되지 않거나 중복된 필드 제거
세션 태그의 다음과 같은 여러 문제 해결:
- 첫 응답 전까지 AES 사용 불가
- 태그 전달이 가정될 경우 신뢰성 부족 및 지연
- 특히 첫 전달 시 대역폭 비효율적
- 태그 저장을 위한 공간 비효율성 극심
- 태그 전달을 위한 대역폭 오버헤드 극심
- 매우 복잡하고 구현하기 어려움
- 다양한 사용 사례에 맞게 조정하기 어려움 (스트리밍 vs. 데이터그램, 서버 vs. 클라이언트, 고대역폭 vs. 저대역폭)
- 태그 전달로 인한 메모리 고갈 취약점
비목표 / 범위 외
- LS2 형식 변경 (제안서 123 완료됨)
- 새로운 DHT 회전 알고리즘 또는 공유 랜덤 생성
- 터널 생성을 위한 새로운 암호화. 제안서 152 Proposal 152 참조.
- 터널 계층 암호화를 위한 새로운 암호화. 제안서 153 Proposal 153 참조.
- I2NP DLM / DSM / DSRM 메시지의 암호화, 전송, 수신 방법. 변경 없음.
- LS1-to-LS2 또는 ElGamal/AES-to-이 제안서 간 통신 지원 없음. 이 제안서는 양방향 프로토콜입니다. 목적지는 동일한 터널을 사용하여 두 개의 LeaseSet을 게시하거나 LS2에 두 암호화 유형을 모두 넣어 하위 호환성을 처리할 수 있습니다.
- 위협 모델 변경
- 구현 세부 사항은 여기서 논의하지 않으며 각 프로젝트에 맡김.
- (낙관적) 멀티캐스트 지원을 위한 확장 또는 훅 추가
정당성
ElGamal/AES+SessionTag는 약 15년 동안 I2P의 유일한 종단 간 프로토콜이었으며, 기본적으로 프로토콜에 수정이 없었습니다. 현재 더 빠른 암호화 프리미티브가 존재합니다. 우리는 프로토콜의 보안을 강화해야 합니다. 또한 메모리 및 대역폭 오버헤드를 최소화하기 위해 경험적 전략과 우회 방법을 개발했지만, 이러한 전략은 취약하고 조정하기 어려우며 프로토콜을 더욱 취약하게 만들어 세션이 끊기기 쉽습니다.
약 동일한 기간 동안, ElGamal/AES+SessionTag 사양 및 관련 문서는 세션 태그 전달이 얼마나 대역폭을 많이 소모하는지 설명하며, 세션 태그 전달을 “동기화된 PRNG"으로 대체할 것을 제안했습니다. 동기화된 PRNG은 공통 시드에서 파생되어 양쪽 끝에서 동일한 태그를 결정론적으로 생성합니다. 동기화된 PRNG는 “래칫"이라고도 할 수 있습니다. 이 제안서(드디어)는 그 래칫 메커니즘을 명시하고 태그 전달을 제거합니다.
래칫(동기화된 PRNG)을 사용하여 세션 태그를 생성함으로써, 새 세션 메시지 및 필요 시 후속 메시지에서 세션 태그를 전송하는 오버헤드를 제거합니다. 일반적인 태그 세트 32개 기준으로 이는 1KB입니다. 이로 인해 전송 측의 세션 태그 저장도 제거되어 저장 요구 사항이 절반으로 줄어듭니다.
키 손상 위장 공격(KCI)을 방지하기 위해 Noise IK 패턴과 유사한 완전한 양방향 핸드셰이크가 필요합니다. NOISE 의 “Payload Security Properties” 표 참조. KCI에 대한 자세한 정보는 논문 https://www.usenix.org/system/files/conference/woot15/woot15-paper-hlauschek.pdf 참조
위협 모델
NTCP2 (제안서 111)과 비교해 위협 모델이 다소 다릅니다. MITM 노드는 OBEP 및 IBGW이며, 플러드필과 공모하여 현재 또는 과거 글로벌 NetDB를 완전히 볼 수 있다고 가정합니다.
목표는 이러한 MITM이 트래픽을 새 세션 및 기존 세션 메시지 또는 새 암호화와 기존 암호화로 분류하는 것을 방지하는 것입니다.
상세 제안
이 제안서는 ElGamal/AES+SessionTags를 대체하기 위한 새로운 종단 간 프로토콜을 정의합니다. 설계는 Noise 핸드셰이크 및 데이터 단계를 사용하며 Signal의 더블 래칫을 포함합니다.
암호화 설계 요약
다섯 가지 프로토콜 부분을 재설계해야 합니다:
- 새 세션 및 기존 세션 컨테이너 형식은 새로운 형식으로 대체됨
- ElGamal (256바이트 공개 키, 128바이트 개인 키)은 ECIES-X25519 (32바이트 공개 및 개인 키)로 대체됨
- AES는 AEAD_ChaCha20_Poly1305 (아래에서는 ChaChaPoly로 약칭)로 대체됨
- SessionTags는 본질적으로 암호화된 동기화된 PRNG인 래칫으로 대체됨
- ElGamal/AES+SessionTags 사양에서 정의된 AES 페이로드는 NTCP2와 유사한 블록 형식으로 대체됨
다섯 가지 변경 각각은 아래에 별도 섹션이 있습니다.
I2P를 위한 새로운 암호화 프리미티브
기존 I2P 라우터 구현은 다음 표준 암호화 프리미티브 구현이 필요하며, 현재 I2P 프로토콜에서는 필요하지 않습니다:
- ECIES (하지만 이는 본질적으로 X25519)
- Elligator2
아직 NTCP2 (Proposal 111 )를 구현하지 않은 기존 I2P 라우터 구현은 다음도 필요합니다:
- X25519 키 생성 및 DH
- AEAD_ChaCha20_Poly1305 (아래에서는 ChaChaPoly로 약칭)
- HKDF
암호화 유형
(LeaseSet2에서 사용) 암호화 유형은 4입니다. 이것은 리틀엔디안 32바이트 X25519 공개 키와 여기에 명시된 종단 간 프로토콜을 나타냅니다.
암호화 유형 0은 ElGamal입니다. 암호화 유형 1-3은 ECIES-ECDH-AES-SessionTag를 위해 예약되어 있으며, 제안서 145 Proposal 145 참조.
Noise 프로토콜 프레임워크
이 제안서는 Noise 프로토콜 프레임워크 NOISE (리비전 34, 2018-07-11)를 기반으로 요구 사항을 제공합니다. Noise는 SSU 프로토콜의 기반이 되는 Station-To-Station 프로토콜 STS 와 유사한 속성을 가집니다. Noise 용어에서, 앨리스는 시작자이고, 밥은 응답자입니다.
이 제안서는 Noise 프로토콜 Noise_IK_25519_ChaChaPoly_SHA256을 기반으로 합니다. (초기 키 파생 함수의 실제 식별자는 “Noise_IKelg2_25519_ChaChaPoly_SHA256"이며 I2P 확장을 나타냄 - 아래 KDF 1 섹션 참조) 이 Noise 프로토콜은 다음 프리미티브를 사용합니다:
대화형 핸드셰이크 패턴: IK 앨리스가 즉시 자신의 정적 키를 밥에게 전송함 (I) 앨리스는 이미 밥의 정적 키를 알고 있음 (K)
단방향 핸드셰이크 패턴: N 앨리스가 자신의 정적 키를 밥에게 전송하지 않음 (N)
DH 함수: X25519 RFC-7748 에서 명시된 바와 같이 32바이트 키 길이의 X25519 DH.
암호화 함수: ChaChaPoly RFC-7539 섹션 2.8에서 명시된 AEAD_CHACHA20_POLY1305. 12바이트 논스, 처음 4바이트는 0으로 설정. NTCP2 와 동일.
해시 함수: SHA256 I2P에서 이미 광범위하게 사용되는 표준 32바이트 해시.
프레임워크에 대한 추가 사항
이 제안서는 Noise_IK_25519_ChaChaPoly_SHA256에 다음과 같은 향상을 정의합니다. 일반적으로 NOISE 섹션 13의 지침을 따릅니다.
평문 임시 키는 Elligator2 로 인코딩됨.
응답은 평문 태그로 시작됨.
메시지 1, 2 및 데이터 단계에 대한 페이로드 형식이 정의됨. 물론, 이는 Noise에서 정의되지 않음.
모든 메시지는 I2NP 마늘 메시지 헤더를 포함합니다. 데이터 단계는 Noise 데이터 단계와 유사하지만 호환되지 않는 암호화를 사용합니다.
핸드셰이크 패턴
핸드셰이크는 Noise 핸드셰이크 패턴을 사용합니다.
다음 문자 매핑이 사용됨:
- e = 일회용 임시 키
- s = 정적 키
- p = 메시지 페이로드
일회용 및 무제한 세션은 Noise N 패턴과 유사함.
<- s
...
e es p ->
바운드 세션은 Noise IK 패턴과 유사함.
<- s
...
e es s ss p ->
<- tag e ee se
<- p
p ->
세션
현재 ElGamal/AES+SessionTag 프로토콜은 단방향입니다. 이 계층에서 수신자는 메시지 출처를 알 수 없습니다. 송신 및 수신 세션은 연관되지 않습니다. 응답은 클로브 내의 DeliveryStatusMessage (마늘메시지로 래핑됨)를 사용하여 외부 통신으로 이루어집니다.
단방향 프로토콜에는 상당한 비효율성이 있습니다. 모든 응답도 비싼 ‘새 세션’ 메시지를 사용해야 합니다. 이로 인해 대역폭, CPU 및 메모리 사용량이 증가합니다.
단방향 프로토콜에는 보안 취약점도 있습니다. 모든 세션은 임시-정적 DH를 기반으로 합니다. 반대 경로가 없기 때문에 밥은 자신의 정적 키를 임시 키로 “래칫"할 방법이 없습니다. 메시지 출처를 알 수 없기 때문에 수신된 임시 키를 송신 메시지에 사용할 수 없으므로 초기 응답도 임시-정적 DH를 사용합니다.
이 제안서에서는 양방향 프로토콜을 생성하기 위한 두 가지 메커니즘을 정의합니다 - “페어링” 및 “바인딩”. 이 메커니즘은 효율성과 보안을 향상시킵니다.
세션 컨텍스트
ElGamal/AES+SessionTags와 마찬가지로 모든 수신 및 송신 세션은 주어진 컨텍스트에 있어야 하며, 이는 라우터 컨텍스트 또는 특정 로컬 목적지의 컨텍스트일 수 있습니다. Java I2P에서 이 컨텍스트는 세션 키 관리자(Session Key Manager)라고 합니다.
세션은 컨텍스트 간에 공유되어서는 안 되며, 이는 다양한 로컬 목적지 간 또는 로컬 목적지와 라우터 간 상관관계를 허용하기 때문입니다.
주어진 목적지가 ElGamal/AES+SessionTags와 이 제안서를 모두 지원하는 경우, 두 유형의 세션이 컨텍스트를 공유할 수 있습니다. 아래 섹션 1c) 참조.
수신 및 송신 세션 페어링
발신자(앨리스)에서 송신 세션이 생성될 때, 새 수신 세션이 생성되어 송신 세션과 페어링되며, 응답이 예상되지 않는 경우(예: 원시 데이터그램)를 제외합니다.
새 송신 세션이 생성될 때마다 항상 새 수신 세션이 생성되어 페어링되며, 응답이 요청되지 않는 경우(예: 원시 데이터그램)를 제외합니다.
응답이 요청되고 원격 목적지 또는 라우터에 바인딩되는 경우, 그 새 송신 세션은 해당 목적지 또는 라우터에 바인딩되며, 해당 목적지 또는 라우터에 대한 이전 송신 세션을 대체합니다.
수신 및 송신 세션을 페어링함으로써 DH 키를 래칫할 수 있는 양방향 프로토콜을 제공합니다.
세션 및 목적지 바인딩
주어진 목적지 또는 라우터에 대한 송신 세션은 하나만 있습니다. 주어진 목적지 또는 라우터에서 여러 현재 수신 세션이 있을 수 있습니다. 일반적으로 새 수신 세션이 생성되고 해당 세션에서 트래픽이 수신되면 (이것이 ACK 역할을 함), 다른 세션은 상대적으로 빠르게 만료되도록 표시되며, 약 1분 정도 내에 만료됩니다. 이전에 보낸 메시지(PN) 값이 확인되고, 이전 수신 세션에서 수신되지 않은 메시지가 (윈도우 크기 내에서) 없는 경우, 이전 세션은 즉시 삭제될 수 있습니다.
발신자(앨리스)에서 송신 세션이 생성되면, 그것은 원격 목적지(밥)에 바인딩되며, 페어링된 수신 세션도 원격 목적지에 바인딩됩니다. 세션이 래칫됨에 따라 원격 목적지에 계속 바인딩됩니다.
수신자(밥)에서 수신 세션이 생성되면, 앨리스의 선택에 따라 원격 목적지(앨리스)에 바인딩될 수 있습니다. 앨리스가 새 세션 메시지에 바인딩 정보(자신의 정적 키)를 포함하면, 세션은 해당 목적지에 바인딩되며, 송신 세션이 생성되어 동일한 목적지에 바인딩됩니다. 세션이 래칫됨에 따라 원격 목적지에 계속 바인딩됩니다.
바인딩 및 페어링의 이점
일반적인 스트리밍 사례에서 앨리스와 밥은 다음과 같이 프로토콜을 사용할 것으로 예상됩니다:
- 앨리스는 새 송신 세션을 새 수신 세션과 페어링하며, 둘 다 원격 목적지(밥)에 바인딩됨.
- 앨리스는 바인딩 정보 및 서명, 응답 요청을 포함하여 밥에게 새 세션 메시지를 보냄.
- 밥은 새 수신 세션을 새 송신 세션과 페어링하며, 둘 다 원격 목적지(앨리스)에 바인딩됨.
- 밥은 페어링된 세션에서 앨리스에게 응답(ack)을 보내며, 새 DH 키로 래칫함.
- 앨리스는 밥의 새 키로 새 송신 세션으로 래칫하며, 기존 수신 세션과 페어링함.
수신 세션을 원격 목적지에 바인딩하고 수신 세션을 동일한 목적지에 바인딩된 송신 세션과 페어링함으로써 두 가지 주요 이점을 얻습니다:
밥에서 앨리스로의 초기 응답은 임시-임시 DH를 사용함
앨리스가 밥의 응답을 수신하고 래칫한 후, 앨리스에서 밥으로의 이후 모든 메시지는 임시-임시 DH를 사용함.
메시지 ACK
ElGamal/AES+SessionTags에서 LeaseSet이 마늘 클로브로 번들링되거나 태그가 전달될 때, 송신 라우터는 ACK를 요청합니다. 이는 별도의 마늘 클로브로 DeliveryStatus Message를 포함합니다. 추가 보안을 위해 DeliveryStatus Message는 마늘 메시지로 래핑됩니다. 이 메커니즘은 프로토콜 관점에서 외부 통신입니다.
새 프로토콜에서는 수신 및 송신 세션이 페어링되므로, ACK를 내부 통신으로 처리할 수 있습니다. 별도의 클로브는 필요하지 않습니다.
명시적 ACK는 단순히 I2NP 블록이 없는 기존 세션 메시지입니다. 그러나 대부분의 경우 스트리밍 또는 애플리케이션 계층이 응답할 시간을 주기 위해 명시적 ACK를 보내기 전에 짧은 시간(아마도 수백 밀리초) 동안 기다리는 것이 바람직할 수 있습니다.
구현은 또한 I2NP 블록이 처리된 후까지 ACK 전송을 연기해야 합니다. 마늘 메시지에 LeaseSet이 있는 Database Store Message가 포함될 수 있기 때문입니다. ACK를 라우팅하기 위해 최신 LeaseSet이 필요하며, 바인딩 정적 키를 검증하기 위해 LeaseSet에 포함된 원격 목적지가 필요합니다.
세션 타임아웃
송신 세션은 항상 수신 세션보다 먼저 만료되어야 합니다. 송신 세션이 만료되고 새 세션이 생성되면, 새 페어링된 수신 세션도 생성됩니다. 이전 수신 세션이 있는 경우, 만료되도록 허용됩니다.
멀티캐스트
TBD
정의
사용되는 암호화 빌딩 블록에 해당하는 다음 함수를 정의합니다.
ZEROLEN 0길이 바이트 배열
CSRNG(n) 암호학적으로 안전한 난수 생성기에서 나온 n바이트 출력.
H(p, d) 개인화 문자열 p와 데이터 d를 입력으로 받아 32바이트 출력을 생성하는 SHA-256 해시 함수. NOISE 에서 정의됨. 아래에서 ||는 연결을 의미함.
다음과 같이 SHA-256 사용::
H(p, d) := SHA-256(p || d)
MixHash(d) 이전 해시 h와 새 데이터 d를 입력으로 받아 32바이트 출력을 생성하는 SHA-256 해시 함수. 아래에서 ||는 연결을 의미함.
다음과 같이 SHA-256 사용::
MixHash(d) := h = SHA-256(h || d)
STREAM RFC-7539 에서 명시된 ChaCha20/Poly1305 AEAD. S_KEY_LEN = 32 및 S_IV_LEN = 12.
ENCRYPT(k, n, plaintext, ad)
키 k와 논스 n을 사용하여 평문을 암호화하며, 키 k에 대해 고유해야 함.
관련 데이터 ad는 선택 사항.
평문 크기 + 16바이트 HMAC 크기의 암호문을 반환.
키가 비밀인 경우 전체 암호문은 무작위와 구분 불가능해야 함.
DECRYPT(k, n, ciphertext, ad)
키 k와 논스 n을 사용하여 암호문을 복호화.
관련 데이터 ad는 선택 사항.
평문을 반환.
DH X25519 공개 키 협정 시스템. 32바이트 개인 키, 32바이트 공개 키, 32바이트 출력 생성. 다음 함수를 가짐:
GENERATE_PRIVATE()
새 개인 키 생성.
DERIVE_PUBLIC(privkey)
주어진 개인 키에 해당하는 공개 키 반환.
GENERATE_PRIVATE_ELG2()
Elligator2 인코딩에 적합한 공개 키를 생성하는 새 개인 키 생성.
임의 생성된 개인 키의 절반은 적합하지 않아 폐기되어야 함.
ENCODE_ELG2(pubkey)
주어진 공개 키에 해당하는 Elligator2 인코딩된 공개 키 반환(역매핑).
인코딩된 키는 리틀엔디안.
인코딩된 키는 256비트 무작위 데이터와 구분 불가능해야 함.
사양은 아래 Elligator2 섹션 참조.
DECODE_ELG2(pubkey)
주어진 Elligator2 인코딩된 공개 키에 해당하는 공개 키 반환.
사양은 아래 Elligator2 섹션 참조.
DH(privkey, pubkey)
주어진 개인 및 공개 키에서 공유 비밀 생성.
HKDF(salt, ikm, info, n) 좋은 엔트로피를 가진(균일한 무작위 문자열일 필요는 없음) 입력 키 자료 ikm, 32바이트 길이의 salt, 컨텍스트 특정 ‘info’ 값과 함께 사용하는 암호학적 키 파생 함수이며, 키 자료로 사용하기에 적합한 n바이트 출력을 생성함.
[RFC-5869](https://tools.ietf.org/html/rfc5869)에서 명시된 바와 같이 HMAC 해시 함수 SHA-256을 사용하여 HKDF 사용,
[RFC-2104](https://tools.ietf.org/html/rfc2104)에서 명시됨. 이는 SALT_LEN이 최대 32바이트임을 의미함.
MixKey(d) 이전 chainKey와 새 데이터 d를 사용하여 HKDF()를 사용하고, 새 chainKey와 k를 설정함. NOISE 에서 정의됨.
다음과 같이 HKDF 사용::
MixKey(d) := output = HKDF(chainKey, d, "", 64)
chainKey = output[0:31]
k = output[32:63]
1) 메시지 형식
현재 메시지 형식 검토
I2NP 에서 명시된 마늘 메시지는 다음과 같습니다. 중간 홉이 새 암호화와 기존 암호화를 구분하지 못하도록 하는 설계 목표가 있으므로, 이 형식은 변경되어서는 안 되며, 길이 필드가 중복되더라도 마찬가지입니다. 형식은 전체 16바이트 헤더와 함께 표시되지만, 실제 헤더는 사용된 전송에 따라 다른 형식일 수 있습니다.
복호화된 데이터에는 일련의 마늘 클로브와 추가 데이터(클로브 세트라고도 함)가 포함됩니다.
자세한 내용과 전체 사양은 I2NP 참조.
+----+----+----+----+----+----+----+----+
|type| msg_id | expiration
+----+----+----+----+----+----+----+----+
| size |chks|
+----+----+----+----+----+----+----+----+
| length | |
+----+----+----+----+ +
| encrypted data |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
암호화된 데이터 형식 검토
15년 이상 사용된 현재 메시지 형식은 ElGamal/AES+SessionTags입니다. ElGamal/AES+SessionTags에서 두 가지 메시지 형식이 있습니다:
- 새 세션:
- 514바이트 ElGamal 블록
- AES 블록 (최소 128바이트, 16의 배수)
- 기존 세션:
- 32바이트 세션 태그
- AES 블록 (최소 128바이트, 16의 배수)
128까지의 최소 패딩은 Java I2P에서 구현되었지만 수신 시 강제되지 않습니다.
이 메시지들은 I2NP 마늘 메시지에 캡슐화되며, 길이 필드가 있으므로 길이를 알 수 있습니다.
16의 배수가 아닌 길이로 패딩이 정의되지 않았기 때문에, 새 세션은 항상 (mod 16 == 2)이고, 기존 세션은 항상 (mod 16 == 0)입니다. 이를 수정해야 합니다.
수신자는 먼저 처음 32바이트를 세션 태그로 조회합니다. 찾으면 AES 블록을 복호화합니다. 찾지 못하고 데이터가 최소 (514+16) 이상 길면 ElGamal 블록을 복호화하려 시도하며, 성공하면 AES 블록을 복호화합니다.
새 세션 태그 및 Signal과의 비교
Signal 더블 래칫에서 헤더는 다음을 포함합니다:
- DH: 현재 래칫 공개 키
- PN: 이전 체인 메시지 길이
- N: 메시지 번호
Signal의 “송신 체인"은 본질적으로 우리의 태그 세트와 유사합니다. 세션 태그를 사용함으로써 대부분을 제거할 수 있습니다.
새 세션에서, 우리는 평문 헤더에 공개 키만 넣습니다.
기존 세션에서, 우리는 헤더로 세션 태그를 사용합니다. 세션 태그는 현재 래칫 공개 키와 메시지 번호와 연관됩니다.
새 세션과 기존 세션 모두에서 PN과 N은 암호화된 본문에 있습니다.
Signal에서, 모든 것이 끊임없이 래칫됩니다. 새 DH 공개 키는 수신자가 래칫하고 새 공개 키를 다시 보내야 하며, 이는 수신된 공개 키의 ack 역할도 합니다. 이것은 우리에게 너무 많은 DH 연산을 요구합니다. 따라서 수신된 키의 ack와 새 공개 키 전송을 분리합니다. 새 DH 공개 키에서 생성된 세션 태그를 사용하는 모든 메시지가 ack를 구성합니다. 재키할 때만 새 공개 키를 전송합니다.
DH가 래칫되어야 하는 메시지 최대 수는 65535입니다.
세션 키를 전달할 때, 우리는 세션 태그를 전달하는 대신 키에서 “태그 세트"를 파생시킵니다. 태그 세트는 최대 65536개의 태그를 가질 수 있습니다. 그러나 수신자는 모든 가능한 태그를 한 번에 생성하는 대신 “미리 보기” 전략을 구현해야 합니다. 마지막으로 수신된 좋은 태그 이후 최대 N개의 태그만 생성합니다. N은 최대 128이지만 32 또는 그 이하가 더 나은 선택일 수 있습니다.
1a) 새 세션 형식
새 세션 일회용 공개 키 (32바이트) 암호화된 데이터 및 MAC (나머지 바이트)
새 세션 메시지는 발신자의 정적 공개 키를 포함하거나 포함하지 않을 수 있습니다. 포함되면 역방향 세션은 해당 키에 바인딩됩니다. 응답이 예상되는 경우(예: 스트리밍 및 응답 가능한 데이터그램) 포함되어야 합니다. 원시 데이터그램의 경우 포함되어서는 안 됩니다.
새 세션 메시지는 일방향 Noise NOISE 패턴 “N"과 유사합니다 (정적 키가 전송되지 않는 경우), 또는 양방향 패턴 “IK"와 유사합니다 (정적 키가 전송되는 경우).
1b) 새 세션 형식 (바인딩 포함)
길이는 96 + 페이로드 길이입니다. 암호화된 형식:
+----+----+----+----+----+----+----+----+
| |
+ +
| 새 세션 임시 공개 키 |
+ 32바이트 +
| Elligator2로 인코딩 |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ 정적 키 +
| ChaCha20 암호화된 데이터 |
+ 32바이트 +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 메시지 인증 코드 |
+ (MAC) 정적 키 섹션용 +
| 16바이트 |
+----+----+----+----+----+----+----+----+
| |
+ 페이로드 섹션 +
| ChaCha20 암호화된 데이터 |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 메시지 인증 코드 |
+ (MAC) 페이로드 섹션용 +
| 16바이트 |
+----+----+----+----+----+----+----+----+
공개 키 :: 32바이트, 리틀엔디안, Elligator2, 평문
정적 키 암호화된 데이터 :: 32바이트
페이로드 섹션 암호화된 데이터 :: 16바이트를 제외한 나머지 데이터
MAC :: Poly1305 메시지 인증 코드, 16바이트
새 세션 임시 키
임시 키는 32바이트이며, Elligator2로 인코딩됨. 이 키는 재사용되지 않으며, 각 메시지(재전송 포함)에서 새 키가 생성됨.
정적 키
복호화되면 앨리스의 X25519 정적 키, 32바이트.
페이로드
암호화된 길이는 나머지 데이터입니다. 복호화된 길이는 암호화된 길이보다 16바이트 적음. 페이로드는 DateTime 블록을 포함해야 하며 일반적으로 하나 이상의 마늘 클로브 블록을 포함합니다. 형식 및 추가 요구 사항은 아래 페이로드 섹션 참조.
1c) 새 세션 형식 (바인딩 없음)
응답이 필요하지 않으면 정적 키를 전송하지 않음.
길이는 96 + 페이로드 길이입니다. 암호화된 형식:
+----+----+----+----+----+----+----+----+
| |
+ +
| 새 세션 임시 공개 키 |
+ 32바이트 +
| Elligator2로 인코딩 |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ 플래그 섹션 +
| ChaCha20 암호화된 데이터 |
+ 32바이트 +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 메시지 인증 코드 |
+ (MAC) 위 섹션용 +
| 16바이트 |
+----+----+----+----+----+----+----+----+
| |
+ 페이로드 섹션 +
| ChaCha20 암호화된 데이터 |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 메시지 인증 코드 |
+ (MAC) 페이로드 섹션용 +
| 16바이트 |
+----+----+----+----+----+----+----+----+
공개 키 :: 32바이트, 리틀엔디안, Elligator2, 평문
플래그 섹션 암호화된 데이터 :: 32바이트
페이로드 섹션 암호화된 데이터 :: 16바이트를 제외한 나머지 데이터
MAC :: Poly1305 메시지 인증 코드, 16바이트
새 세션 임시 키
앨리스의 임시 키. 임시 키는 32바이트이며, Elligator2로 인코딩됨, 리틀엔디안. 이 키는 재사용되지 않으며, 각 메시지(재전송 포함)에서 새 키가 생성됨.
플래그 섹션 복호화된 데이터
플래그 섹션에는 아무것도 없습니다. 항상 32바이트이며, 바인딩이 있는 새 세션 메시지의 정적 키와 길이가 동일해야 하기 때문입니다. 밥은 32바이트가 모두 0인지 테스트하여 정적 키인지 플래그 섹션인지 결정합니다.
TODO 여기에 필요한 플래그?
페이로드
암호화된 길이는 나머지 데이터입니다. 복호화된 길이는 암호화된 길이보다 16바이트 적음. 페이로드는 DateTime 블록을 포함해야 하며 일반적으로 하나 이상의 마늘 클로브 블록을 포함합니다. 형식 및 추가 요구 사항은 아래 페이로드 섹션 참조.
1d) 일회용 형식 (바인딩 또는 세션 없음)
단일 메시지만 전송될 것으로 예상되는 경우, 세션 설정 또는 정적 키가 필요하지 않음.
길이는 96 + 페이로드 길이입니다. 암호화된 형식:
+----+----+----+----+----+----+----+----+
| |
+ +
| 임시 공개 키 |
+ 32바이트 +
| Elligator2로 인코딩 |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ 플래그 섹션 +
| ChaCha20 암호화된 데이터 |
+ 32바이트 +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 메시지 인증 코드 |
+ (MAC) 위 섹션용 +
| 16바이트 |
+----+----+----+----+----+----+----+----+
| |
+ 페이로드 섹션 +
| ChaCha20 암호화된 데이터 |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 메시지 인증 코드 |
+ (MAC) 페이로드 섹션용 +
| 16바이트 |
+----+----+----+----+----+----+----+----+
공개 키 :: 32바이트, 리틀엔디안, Elligator2, 평문
플래그 섹션 암호화된 데이터 :: 32바이트
페이로드 섹션 암호화된 데이터 :: 16바이트를 제외한 나머지 데이터
MAC :: Poly1305 메시지 인증 코드, 16바이트
새 세션 일회용 키
일회용 키는 32바이트이며, Elligator2로 인코딩됨, 리틀엔디안. 이 키는 재사용되지 않으며, 각 메시지(재전송 포함)에서 새 키가 생성됨.
플래그 섹션 복호화된 데이터
플래그 섹션에는 아무것도 없습니다. 항상 32바이트이며, 바인딩이 있는 새 세션 메시지의 정적 키와 길이가 동일해야 하기 때문입니다. 밥은 32바이트가 모두 0인지 테스트하여 정적 키인지 플래그 섹션인지 결정합니다.
TODO 여기에 필요한 플래그?
+----+----+----+----+----+----+----+----+
| |
+ +
| |
+ 모두 0 +
| 32바이트 |
+ +
| |
+----+----+----+----+----+----+----+----+
zeros:: 모두 0, 32바이트.
페이로드
암호화된 길이는 나머지 데이터입니다. 복호화된 길이는 암호화된 길이보다 16바이트 적음. 페이로드는 DateTime 블록을 포함해야 하며 일반적으로 하나 이상의 마늘 클로브 블록을 포함합니다. 형식 및 추가 요구 사항은 아래 페이로드 섹션 참조.
1f) 새 세션 메시지 KDF
초기 ChainKey를 위한 KDF
이것은 IK에 대한 표준 NOISE 이며 수정된 프로토콜 이름을 가짐. 바운드 세션의 IK 패턴과 무제한 세션의 N 패턴 모두에 동일한 초기화기를 사용한다는 점에 유의하세요.
프로토콜 이름은 두 가지 이유로 수정되었습니다. 첫째, 임시 키가 Elligator2로 인코딩되었음을 나타내기 위해, 둘째, 두 번째 메시지 전에 태그 값을 혼합하기 위해 MixHash()가 호출되었음을 나타내기 위해.
이것은 "e" 메시지 패턴입니다:
// 프로토콜 이름 정의.
Set protocol_name = "Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"
(40바이트, US-ASCII 인코딩, NULL 종료 없음).
// 32바이트 해시 h 정의.
h = SHA256(protocol_name);
32바이트 체이닝 키 ck 정의. h 데이터를 ck에 복사.
Set chainKey = h
// MixHash(null prologue)
h = SHA256(h);
// 여기까지, 앨리스가 모든 발신 연결에 대해 미리 계산할 수 있음
플래그/정적 키 섹션 암호화된 내용을 위한 KDF
이것은 "e" 메시지 패턴입니다:
// 밥의 X25519 정적 키
// bpk는 leaseset에 게시됨
bsk = GENERATE_PRIVATE()
bpk = DERIVE_PUBLIC(bsk)
// 밥 정적 공개 키
// MixHash(bpk)
// || 아래에서 연결을 의미함
h = SHA256(h || bpk);
// 여기까지, 밥이 모든 수신 연결에 대해 미리 계산할 수 있음
// 앨리스의 X25519 임시 키
aesk = GENERATE_PRIVATE_ELG2()
aepk = DERIVE_PUBLIC(aesk)
// 앨리스 임시 공개 키
// MixHash(aepk)
// || 아래에서 연결을 의미함
h = SHA256(h || aepk);
// h는 새 세션 메시지의 AEAD에서 관련 데이터로 사용됨
// 새 세션 응답 KDF를 위해 해시 h 유지
// eapk는 새 세션 메시지 시작 부분에서 평문으로 전송됨
elg2_aepk = ENCODE_ELG2(aepk)
// 밥이 디코딩한 것
aepk = DECODE_ELG2(elg2_aepk)
"e" 메시지 패턴 종료.
이것은 "es" 메시지 패턴입니다:
// Noise es
sharedSecret = DH(aesk, bpk) = DH(bsk, aepk)
// MixKey(DH())
//[chainKey, k] = MixKey(sharedSecret)
// ChaChaPoly 암호화/복호화 매개변수
keydata = HKDF(chainKey, sharedSecret, "", 64)
chainKey = keydata[0:31]
// AEAD 매개변수
k = keydata[32:63]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, flags/static key section, ad)
"es" 메시지 패턴 종료.
이것은 "s" 메시지 패턴입니다:
// MixHash(ciphertext)
// 페이로드 섹션 KDF를 위해 저장
h = SHA256(h || ciphertext)
// 앨리스의 X25519 정적 키
ask = GENERATE_PRIVATE()
apk = DERIVE_PUBLIC(ask)
"s" 메시지 패턴 종료.
페이로드 섹션 KDF (앨리스 정적 키 포함)
이것은 "ss" 메시지 패턴입니다:
// Noise ss
sharedSecret = DH(ask, bpk) = DH(bsk, apk)
// MixKey(DH())
//[chainKey, k] = MixKey(sharedSecret)
// ChaChaPoly 암호화/복호화 매개변수
// 정적 키 섹션의 chainKey
Set sharedSecret = X25519 DH 결과
keydata = HKDF(chainKey, sharedSecret, "", 64)
chainKey = keydata[0:31]
// AEAD 매개변수
k = keydata[32:63]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, payload, ad)
"ss" 메시지 패턴 종료.
// MixHash(ciphertext)
// 새 세션 응답 KDF를 위해 저장
h = SHA256(h || ciphertext)
페이로드 섹션 KDF (앨리스 정적 키 없음)
이것은 Noise “N” 패턴이지만 바운드 세션과 동일한 “IK” 초기화기를 사용합니다.
정적 키가 복호화되고 검사될 때까지 새 세션 메시지가 앨리스의 정적 키를 포함하는지 여부를 식별할 수 없습니다. 따라서 수신자는 모든 새 세션 메시지에 대해 “IK” 상태 머신을 사용해야 합니다. 정적 키가 모두 0이면 “ss” 메시지 패턴을 건너뛰어야 합니다.
chainKey = 플래그/정적 키 섹션에서
k = 플래그/정적 키 섹션에서
n = 1
ad = 플래그/정적 키 섹션에서 h
ciphertext = ENCRYPT(k, n, payload, ad)
1g) 새 세션 응답 형식
단일 새 세션 메시지에 대해 하나 이상의 새 세션 응답이 전송될 수 있습니다. 각 응답은 세션의 태그 세트에서 생성된 평문 태그로 시작됩니다.
새 세션 응답은 두 부분으로 구성됩니다. 첫 번째 부분은 태그가 접두사로 붙은 Noise IK 핸드셰이크 완료입니다. 첫 번째 부분의 길이는 56바이트입니다. 두 번째 부분은 데이터 단계 페이로드입니다. 두 번째 부분의 길이는 16 + 페이로드 길이입니다.
총 길이는 72 + 페이로드 길이입니다. 암호화된 형식:
+----+----+----+----+----+----+----+----+
| 세션 태그 8바이트 |
+----+----+----+----+----+----+----+----+
| |
+ 임시 공개 키 +
| |
+ 32바이트 +
| Elligator2로 인코딩 |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 메시지 인증 코드 |
+ (MAC) 키 섹션용 (데이터 없음) +
| 16바이트 |
+----+----+----+----+----+----+----+----+
| |
+ 페이로드 섹션 +
| ChaCha20 암호화된 데이터 |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 메시지 인증 코드 |
+ (MAC) 페이로드 섹션용 +
| 16바이트 |
+----+----+----+----+----+----+----+----+
태그 :: 8바이트, 평문
공개 키 :: 32바이트, 리틀엔디안, Elligator2, 평문
MAC :: Poly1305 메시지 인증 코드, 16바이트
참고: ChaCha20 평문 데이터는 비어 있음 (ZEROLEN)
페이로드 섹션 암호화된 데이터 :: 16바이트를 제외한 나머지 데이터
MAC :: Poly1305 메시지 인증 코드, 16바이트
세션 태그
태그는 아래 DH 초기화 KDF에서 초기화된 세션 태그 KDF에서 생성됩니다. 이것은 응답을 세션과 연결시킵니다. DH 초기화의 세션 키는 사용되지 않습니다.
새 세션 응답 임시 키
밥의 임시 키. 임시 키는 32바이트이며, Elligator2로 인코딩됨, 리틀엔디안. 이 키는 재사용되지 않으며, 각 메시지(재전송 포함)에서 새 키가 생성됨.
페이로드
암호화된 길이는 나머지 데이터입니다. 복호화된 길이는 암호화된 길이보다 16바이트 적음. 페이로드는 일반적으로 하나 이상의 마늘 클로브 블록을 포함합니다. 형식 및 추가 요구 사항은 아래 페이로드 섹션 참조.
응답 태그 세트를 위한 KDF
하나 이상의 태그는 아래 KDF를 사용하여 초기화된 태그 세트에서 생성되며, 이 KDF는 새 세션 메시지의 chainKey를 사용합니다.
// 태그 세트 생성
tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32)
tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey)
응답 키 섹션 암호화된 내용을 위한 KDF
// 새 세션 메시지의 키
// 앨리스의 X25519 키
// apk와 aepk는 원래 새 세션 메시지에서 전송됨
// ask = 앨리스 개인 정적 키
// apk = 앨리스 공개 정적 키
// aesk = 앨리스 임시 개인 키
// aepk = 앨리스 임시 공개 키
// 밥의 X25519 정적 키
// bsk = 밥 개인 정적 키
// bpk = 밥 공개 정적 키
// 태그 생성
tagsetEntry = tagset_nsr.GET_NEXT_ENTRY()
tag = tagsetEntry.SESSION_TAG
// MixHash(tag)
h = SHA256(h || tag)
이것은 "e" 메시지 패턴입니다:
// 밥의 X25519 임시 키
besk = GENERATE_PRIVATE_ELG2()
bepk = DERIVE_PUBLIC(besk)
// 밥의 임시 공개 키
// MixHash(bepk)
// || 아래에서 연결을 의미함
h = SHA256(h || bepk);
// elg2_bepk는 새 세션 메시지 시작 부분에서 평문으로 전송됨
elg2_bepk = ENCODE_ELG2(bepk)
// 밥이 디코딩한 것
bepk = DECODE_ELG2(elg2_bepk)
"e" 메시지 패턴 종료.
이것은 "ee" 메시지 패턴입니다:
// MixKey(DH())
//[chainKey, k] = MixKey(sharedSecret)
// ChaChaPoly 암호화/복호화 매개변수
// 원래 새 세션 페이로드 섹션의 chainKey
sharedSecret = DH(aesk, bepk) = DH(besk, aepk)
keydata = HKDF(chainKey, sharedSecret, "", 32)
chainKey = keydata[0:31]
"ee" 메시지 패턴 종료.
이것은 "se" 메시지 패턴입니다:
// MixKey(DH())
//[chainKey, k] = MixKey(sharedSecret)
sharedSecret = DH(ask, bepk) = DH(besk, apk)
keydata = HKDF(chainKey, sharedSecret, "", 64)
chainKey = keydata[0:31]
// AEAD 매개변수
k = keydata[32:63]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
"se" 메시지 패턴 종료.
// MixHash(ciphertext)
h = SHA256(h || ciphertext)
chainKey는 아래 래칫에서 사용됨.
페이로드 섹션 암호화된 내용을 위한 KDF
이것은 첫 번째 기존 세션 메시지와 유사하지만, 별도의 태그 없이, post-split입니다. 또한 NSR 메시지에 페이로드를 바인딩하기 위해 위에서 해시를 사용합니다.
// split()
keydata = HKDF(chainKey, ZEROLEN, "", 64)
k_ab = keydata[0:31]
k_ba = keydata[32:63]
tagset_ab = DH_INITIALIZE(chainKey, k_ab)
tagset_ba = DH_INITIALIZE(chainKey, k_ba)
// 새 세션 응답 페이로드를 위한 AEAD 매개변수
k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
n = 0
ad = h
ciphertext = ENCRYPT(k, n, payload, ad)
참고 사항
응답 크기에 따라 하나의 응답에 대해 여러 NSR 메시지가 전송될 수 있으며, 각각 고유한 임시 키를 가집니다.
앨리스와 밥은 모든 NS 및 NSR 메시지에 대해 새 임시 키를 사용해야 합니다.
앨리스는 기존 세션(ES) 메시지를 보내기 전에 밥의 NSR 메시지 중 하나를 수신해야 하며, 밥은 ES 메시지를 보내기 전에 앨리스로부터 ES 메시지를 수신해야 합니다.
밥의 NSR 페이로드 섹션에서 chainKey 및 k는
초기 ES DH 래칫(양방향, DH 래칫 KDF 참조)의 입력으로 사용됩니다.
밥은 앨리스로부터 수신한 ES 메시지에 대한 기존 세션만 유지해야 합니다. (여러 NSR에 대한) 다른 생성된 수신 및 송신 세션은 주어진 세션에 대한 앨리스의 첫 번째 ES 메시지를 수신한 후 즉시 파괴되어야 합니다.
1h) 기존 세션 형식
세션 태그 (8바이트) 암호화된 데이터 및 MAC (아래 섹션 3 참조)
형식
암호화됨:
+----+----+----+----+----+----+----+----+
| 세션 태그 |
+----+----+----+----+----+----+----+----+
| |
+ 페이로드 섹션 +
| ChaCha20 암호화된 데이터 |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 메시지 인증 코드 |
+ (MAC) +
| 16바이트 |
+----+----+----+----+----+----+----+----+
세션 태그 :: 8바이트, 평문
페이로드 섹션 암호화된 데이터 :: 16바이트를 제외한 나머지 데이터
MAC :: Poly1305 메시지 인증 코드, 16바이트
페이로드
암호화된 길이는 나머지 데이터입니다. 복호화된 길이는 암호화된 길이보다 16바이트 적음. 형식 및 요구 사항은 아래 페이로드 섹션 참조.
KDF
아래 AEAD 섹션 참조.
// 기존 세션 페이로드를 위한 AEAD 매개변수
k = 이 세션 태그와 연관된 32바이트 세션 키
n = 현재 체인의 메시지 번호 N, 연관된 세션 태그에서 검색됨.
ad = 8바이트 세션 태그
ciphertext = ENCRYPT(k, n, payload, ad)
2) ECIES-X25519
형식: 32바이트 공개 및 개인 키, 리틀엔디안.
정당성: NTCP2 에서 사용됨.
2a) Elligator2
표준 Noise 핸드셰이크에서, 각 방향의 초기 핸드셰이크 메시지는 평문으로 전송되는 임시 키로 시작합니다. 유효한 X25519 키는 무작위와 구분 가능하므로, 중간자 공격자는 이 메시지를 기존 세션 메시지(무작위 세션 태그로 시작)와 구분할 수 있습니다. NTCP2 (Proposal 111 )에서는 외부 통신 정적 키를 사용하는 저오버헤드 XOR 함수를 사용하여 키를 위장했습니다. 그러나 여기서 위협 모델은 다릅니다. 우리는 어떤 MITM도 트래픽의 목적지를 확인하거나 초기 핸드셰이크 메시지와 기존 세션 메시지를 구분하는 것을 허용하고 싶지 않습니다.
따라서 Elligator2 는 새 세션 및 새 세션 응답 메시지의 임시 키를 변환하여 균일한 무작위 문자열과 구분 불가능하게 만드는 데 사용됩니다.
형식
32바이트 공개 및 개인 키. 인코딩된 키는 리틀엔디안.
Elligator2 에서 정의된 바와 같이, 인코딩된 키는 254개의 무작위 비트와 구분 불가능합니다. 우리는 256개의 무작위 비트(32바이트)를 요구합니다. 따라서 인코딩 및 디코딩은 다음과 같이 정의됩니다:
인코딩:
ENCODE_ELG2() 정의
// Elligator2 사양에서 정의된 대로 인코딩
encodedKey = encode(pubkey)
// 상위 비트에 2개의 무작위 비트 OR
randomByte = CSRNG(1)
encodedKey[31] |= (randomByte & 0xc0)
디코딩:
DECODE_ELG2() 정의
// 상위 비트에서 2개의 무작위 비트 마스킹
encodedKey[31] &= 0x3f
// Elligator2 사양에서 정의된 대로 디코딩
pubkey = decode(encodedKey)
정당성
OBEP 및 IBGW가 트래픽을 분류하지 못하도록 하기 위해 필요함.
참고 사항
Elligator2는 평균적으로 키 생성 시간을 두 배로 늘리며