Tink 와이어 형식

이 페이지에서는 키 및 기본 출력에 관한 Tink의 와이어 형식을 설명합니다. 이 문서는 Tink에 추가 언어를 추가하려는 암호화 전문가와 와이어 호환 모드를 원하는 기타 상위 수준 암호화 라이브러리 유지관리자를 대상으로 합니다. 일반 시청자를 대상으로 하지 않습니다.

키 세트 직렬화

Tink는 Google protobuf를 사용하여 키 세트를 직렬화합니다.

  • 바이너리 직렬화 키 세트는 tink.proto에 정의된 직렬화된 키 세트 프로토입니다. 키의 KeyData 값 속성은 해당 키 유형의 직렬화된 프로토입니다.
  • JSON 직렬화 키 세트는 JSON 형식으로 직렬화된 키 세트 프로토입니다. KeyData 값은 여전히 바이너리 직렬화된 프로토입니다.
  • 암호화된 키 세트는 tink.proto에 정의된 직렬화된 EncryptedKeyset 프로토입니다. 암호화된 바이너리 직렬화 키 세트와 선택적으로 암호화되지 않은 KeysetInfo 메타데이터가 포함되어 있습니다.

Tink 출력 접두사

대부분의 Tink 기본 요소는 다음으로 구성된 5바이트 출력 접두사를 지원합니다.

  • 1바이트 버전: 0x01
  • 4바이트 키 힌트: 사용된 키의 키 ID입니다.

일부 기존 키는 버전 바이트 0x00도 지원할 수 있습니다.

이 접두사는 인증되지 않았으며 보안 목적으로 사용할 수 없습니다. Tink는 이를 복호화 또는 확인 속도를 높이기 위한 힌트로 사용합니다.

AEAD

일반적으로 Tink는 AEAD 암호문을 다음과 같이 형식화합니다.

prefix || IV || ciphertext || tag

해당 RFC에 달리 명시되지 않는 한 prefix는 비어 있거나 5바이트 Tink 출력 접두사입니다.

AES-CTR-HMAC

AES-CTR-HMAC의 경우 Tink는 다음과 같이 연결된 데이터 (AD)로 MAC을 계산합니다.

AD || IV || ciphertext || bitlen(AD)

여기서 bitlen(AD)는 AD의 길이(비트)이며 64비트 빅 엔디안 부호 없는 정수로 표현됩니다. 이 HMAC 스키마는 Mcgrew의 AES-CBC-HMAC 초안을 따릅니다.

결정적 AEAD

Tink는 AES-SIV에 RFC 5297을 구현하여 합성 초기화 벡터 (SIV)를 암호문의 시작 부분에 배치합니다. 원시 유형은 5바이트 Tink 출력 접두사를 추가할 수 있습니다.

RFC 5297은 연결된 데이터 목록을 지원하지만 Tink는 정확히 하나의 연결된 데이터만 지원합니다. 이는 RFC 5297의 요소가 하나인 목록에 해당합니다. 빈 연결 데이터는 빈 목록이 아닌 빈 요소가 하나 있는 목록입니다.

스트리밍 AEAD

AES-CTR HMACAES-GCM-HKDF를 참고하세요.

봉투 암호화

봉투 암호화는 Tink의 AEAD 기본 요소를 사용하여 데이터 암호화 키 DEK로 데이터를 암호화합니다. 암호화는 다음과 같이 작동합니다.

  • 지정된 키 템플릿 (또는 키 매개변수)을 사용하여 새 DEK가 생성됩니다.
  • DEK이 바이트 문자열로 직렬화됩니다. 키 유형 proto의 프로토콜 버퍼 직렬화의 직렬화 형식입니다. 예를 들어 이는 키 유형 AES GCM의 DEK에 대해 aes_gcm.proto에 정의된 직렬화된 AesGcmKey 프로토콜 버퍼 메시지입니다. 프로토콜 버퍼를 직렬화하는 방법은 프로토콜 버퍼 직렬화를 참고하세요.
  • 직렬화된 DEK는 외부 제공업체 (예: GCP)에 의해 encrypted DEK로 암호화됩니다.
  • DEK는 연결된 데이터가 포함된 일반 텍스트를 ciphertext로 암호화하는 데 사용됩니다. 따라서 ciphertext의 형식은 DEK에 해당하는 AEAD 기본 요소와 정확히 동일합니다.

봉투 암호화의 출력 형식은 다음과 같습니다.

encrypted DEK length || encrypted DEK || ciphertext

encrypted DEK length는 4바이트이며 encrypted DEK의 길이를 32비트 빅 엔디안 정수로 저장합니다.

MAC

Tink는 해당 RFC를 따릅니다. 원시 요소는 태그에 5바이트 Tink 출력 접두사를 추가할 수 있습니다.

PRF 세트

Tink는 해당 RFC를 따릅니다. PRF의 경우 키 유형은 출력 길이를 포함하지 않으므로 동일한 알고리즘의 MAC 키 유형과 다릅니다. PRF 설정 키는 Tink 출력 접두사를 추가하지 않습니다. 이렇게 하면 출력이 실제로 PRF가 됩니다.

하이브리드 암호화

Tink 하이브리드 암호화의 일반적인 와이어 형식은 다음과 같습니다.

prefix || encapsulated_key || encrypted_data

prefix는 비어 있거나 5바이트 Tink 출력 접두사입니다. 각 키 유형에는 파싱할 바이트 수와 encapsulated_key에서 이러한 바이트를 파싱하는 방법에 관한 정보가 포함되어 있습니다.

HPKE (하이브리드 공개 키 암호화)

Tink는 RFC 9180에 정의된 HPKE 표준을 따릅니다. HPKE 암호화 스위트에는 다음 세 가지 기본 요소가 포함됩니다.

  • 키 캡슐화 메커니즘 (KEM)
  • 키 파생 함수 (KDF)
  • 연관 데이터로 인증된 암호화 (AEAD)

HPKE 표준은 RFC 9180, 섹션 10에 일반 와이어 형식을 정의하지 않습니다. Tink의 HPKE 구현은 다음 encapsulated_keyencrypted_data 값을 사용합니다.

  • encapsulated_key
    • 발신자의 직렬화된 공개 키
    • RFC 9180, 섹션 4.1enc로 정의됨
    • 사용된 특정 HPKE KEM에 따라 결정되는 형식
  • encrypted_data
    • 암호문과 태그 (즉, ciphertext || tag(IV 제외)
    • RFC 9180, 섹션 4ct로 정의됨
    • 사용된 특정 HPKE AEAD에 따라 형식이 결정됨
X25519 디피-헬만 기반 KEM

X25519 DHKEM의 경우 값 enc은 전송자의 32바이트 Diffie-Hellman 공개 키입니다.

ECIES-AEAD-HKDF

Tink의 ECIES-AEAD-HKDF 구현에서 encapsulated_key는 키 캡슐화 메커니즘 (KEM)의 출력이고 encrypted_data는 데이터 캡슐화 메커니즘 (DEM)의 출력입니다.

KEM

키 유형에 따라 Tink는 RFC 8422/ANSI.X9-62.2005 인코딩 표준에 따라 압축된 타원 곡선 점과 압축되지 않은 타원 곡선 점을 사용합니다. 압축되지 않은 점의 경우 바이트 0x04 뒤에 xy 좌표가 고정 크기 정수로 옵니다. 압축된 좌표의 경우 바이트 0x02 또는 0x03x 좌표가 고정 크기 정수로 사용됩니다. X25519의 경우 RFC 7748 정의가 사용됩니다 (x 좌표가 고정 크기 정수임).

DEM

encrypted_data의 경우 Tink는 AEAD와 동일한 형식을 사용합니다. 여기에는 IV 지정이 포함됩니다.

키 파생

먼저 공유 지점의 x 좌표 x_ss가 계산됩니다. 그러면 AEAD의 키가 다음과 같이 설정됩니다.

HKDF(ikm = encapsulated_key || x_ss, salt = salt_of_key, info = context_info, length = dem_key_size)

여기서 encapsulated_key은 전체 KEM 출력을 바이트로 나타낸 것입니다.

디지털 서명

Tink는 해당 RFC를 따릅니다. 원시 요소는 생성된 태그에 5바이트 Tink 출력 접두사를 추가할 수 있습니다.

ECDSA

키의 EcdsaSignatureEncoding 필드에 따라 ECDSA 서명의 형식은 IEEE P1363 또는 ASN.1 DER입니다.

IEEE P1363 서명의 형식은 r || s입니다. 여기서 rs는 0으로 패딩되고 곡선의 순서와 바이트 크기가 동일합니다. 예를 들어 NIST P-256 곡선의 경우 rs은 32바이트로 0 패딩됩니다.

DER 서명은 ASN.1을 사용하여 인코딩됩니다.

ECDSA-Sig-Value :: = SEQUENCE { r INTEGER, s INTEGER }

특히 인코딩은 다음과 같습니다.

0x30 || totalLength || 0x02 || r's length || r || 0x02 || s's length || s

Tink는 DER 인코딩 ECDSA 서명만 허용하여 서명 확인 권장사항을 따릅니다 (대체 BER 인코딩 서명은 유효하지 않음).

이를 통해 암호화폐 시스템에 자주 영향을 미치는 서명 변경 공격을 방지할 수 있습니다.

외부 Mu ML-DSA 사전 해시 값

Prehash 기본 요소는 메시지를 prehash 값으로 변환하며, SignPrehash 기본 요소는 이 값을 서명합니다. RFC 9881에 설명된 대로 외부 Mu 모드의 ML-DSA의 경우 사전 해시 값은 다음 레이아웃으로 69바이트입니다.

0xff || key_id (4 bytes, big-endian) || mu (64 bytes)
  • mu는 ML-DSA 메시지 대표이며 SHAKE256(tr || 0x00 || 0x00 || message, 64)로 계산됩니다. 여기서 tr는 공개 키의 64바이트 해시이고, 첫 번째 0x00는 순수 ML-DSA의 FIPS 204 도메인 구분자이며, 두 번째 0x00는 (빈) 컨텍스트 문자열의 길이입니다. tr는 공개 키에서 파생되므로 mu는 해당 키에 암호화 방식으로 바인딩됩니다. 바인딩을 확인하려면 원래 메시지가 필요합니다.
  • 5바이트 접두사는 Tink 프레이밍이며 mu의 일부가 아닙니다. 미리 해시된 값을 하나의 특정 키와 연결하여 SignPrehash가 서명할 키를 알고 키가 없는 미리 해시된 값을 거부할 수 있습니다. 접두사는 일반 메타데이터이며 암호화 방식으로 바인딩되지 않습니다. 누구나 다시 쓸 수 있습니다.

서명은 정확히 69바이트가 아니거나 0xff로 시작하지 않거나 키 ID가 키 세트의 사용 설정된 키와 일치하지 않는 입력을 거부합니다.