키 세트

Tink는 키 세트를 사용하여 키 순환을 사용 설정합니다. 공식적으로 키 세트는 하나의 키가 기본 키로 지정된 (예를 들어 새 일반 텍스트에 서명하고 암호화하는 데 사용되는 키) 비어 있지 않은 키 목록1입니다. 또한 키 세트의 키에는 고유 ID2와 키 상태가 부여되므로 키 세트에서 키를 삭제하지 않고도 키를 사용 중지할 수 있습니다.

키셋은 사용자가 KeysetHandle 클래스를 통해 키에 액세스할 수 있는 기본 방법입니다. 이를 통해 모든 사용자가 한 번에 여러 키를 처리하는 코드를 갖게 됩니다. 암호화 대부분의 사용자에게 여러 키를 처리하는 것은 필수사항입니다. 키를 변경할 수 있어야 하며 (예: 이전 키가 유출될 수 있음) 코드가 실행되는 머신과 모든 암호 텍스트에 전역적으로 즉시 적용할 수 있는 원자적 '다음 키로 전환'은 거의 없습니다. 따라서 사용자는 한 키에서 다음 키로 변경될 때 작동하는 코드를 작성해야 합니다.

예: AEAD

AEAD 기본 요소의 여러 키가 포함된 AEAD 키 세트를 고려해 보세요. 앞서 설명한 것처럼 각 키는 \(\mathrm{Enc}\) 및 \(\mathrm{Dec}\)이라는 두 함수를 고유하게 지정합니다. 이제 키 세트에서는 \(\mathrm{Enc}\) 및 \(\mathrm{Dec}\) 이라는 두 가지 새로운 함수도 지정합니다. \(\mathrm{Enc}\) 는 키 세트의 기본 키 함수인 \(\mathrm{Enc}\) 와 동일하며 \(\mathrm{Dec}\) 함수는 모든 키로 복호화를 시도하며 특정 순서로 키를 통과합니다 (Tink에서 이 성능을 개선하는 방법은 아래 참고).

키 세트는 전체 키입니다. 사용된 함수 \(\mathrm{Enc}\) 및\(\mathrm{Dec}\) 에 대한 전체 설명입니다. 즉, 사용자는 KeysetHandle를 입력으로 사용하는 클래스를 작성하여 클래스가 제대로 작동하려면 객체 \(\mathrm{Enc}\) 와 \(\mathrm{Dec}\) 에 대한 완전한 설명이 필요하다는 아이디어를 표현할 수 있습니다. 이를 통해 사용자는 이 클래스를 사용하려면 암호화 기본 요소의 설명을 제공해야 한다는 것을 전달하는 API를 작성할 수 있습니다.

키 순환

먼저 KMS에서 키 세트를 가져온 다음 이 키 세트에서 AEAD 객체를 만들고 마지막으로 이 객체를 사용하여 암호문을 암호화하고 복호화하는 프로그램을 작성하는 Tink 사용자를 생각해 보세요.

이러한 사용자는 키 순환을 위해 자동으로 준비되며, 현재 선택이 더 이상 표준을 충족하지 않는 경우 알고리즘을 전환합니다.

하지만 이러한 키 순환을 구현할 때는 다소 주의해야 합니다. 먼저 KMS는 키 세트에 새 키를 추가해야 합니다 (하지만 아직 기본 키로 설정하지는 않음). 그런 다음 이 키 세트를 사용하는 모든 바이너리에 최신 키가 있도록 새 키 세트를 모든 바이너리에 출시해야 합니다. 그런 다음에만 새 키를 기본 키로 설정해야 하며 결과 키 세트가 키 세트를 사용하여 모든 바이너리에 다시 배포됩니다.

암호문의 주요 식별자

AEAD 키 세트의 예를 다시 살펴보겠습니다. 단순히 실행하면 암호화된 텍스트를 복호화하려면 Tink가 키 세트의 모든 키로 복호화를 시도해야 합니다. 키 세트를 암호화하는 데 사용된 키를 알 수 없기 때문입니다. 이로 인해 성능 오버헤드가 커질 수 있습니다.

따라서 Tink는 ID에서 파생된 5바이트 문자열을 암호문에 접두사로 추가할 수 있습니다. 위의 '전체 키' 철학에 따라 이 접두사는 키의 일부이며 이 키로 파생된 모든 암호문에는 이 접두사가 있어야 합니다. 사용자가 키를 만들 때 키가 이러한 접두사를 사용해야 하는지 아니면 접두사 없는 암호문 형식을 사용해야 하는지 선택할 수 있습니다.

키가 키 세트에 있으면 Tink는 키가 키 세트에 있는 ID에서 이 태그를 계산합니다. ID가 키 세트 내에서 고유2하다는 사실은 태그가 고유하다는 것을 의미합니다. 따라서 태그된 키만 사용하면 단일 키로 복호화하는 것과 비교하여 성능 손실이 없습니다. Tink는 복호화할 때 키 중 하나만 시도하면 됩니다.

하지만 태그는 키의 일부이므로 키가 특정 ID를 갖는 경우에만 키셋에 있을 수 있습니다. 이는 다양한 언어로 키 객체의 구현을 설명할 때 몇 가지 영향을 미칩니다.

ID가 필요하지만 출력 접두사가 없는 키

일부 키에는 특정 ID가 있어야 하지만 출력에 접두사를 추가하지 않습니다. 예를 들어 NO_PREFIX_WITH_PREHASH_ID 변형이 있는 서명 키 (출력 접두사 유형 WITH_ID_REQUIREMENT로 저장됨)는 접두사 없이 서명을 생성합니다. Prehash 기본 요소를 사용하여 이러한 키를 사용하면 Tink는 prehash 값에 키 ID를 작성하므로 원격 서명자가 서명할 키를 알 수 있습니다.

접두사를 사용하는 키와 마찬가지로 이러한 키는 해당 ID 하나의 키 세트에만 있을 수 있습니다. 사전 해시 값의 키 ID는 출력 접두사와 마찬가지로 일반 메타데이터입니다. 서명은 이를 바인딩하지 않으며 검증자는 이를 볼 수 없습니다. 바이트 수준 레이아웃은 Tink 와이어 형식을 참고하세요.


  1. Tink의 일부에서는 여전히 키 세트를 세트로 취급합니다. 하지만 이 설정은 변경해야 합니다. 일반적으로 순서가 중요하기 때문입니다. 예를 들어 Aead를 사용한 키 순환의 일반적인 수명 주기를 생각해 보세요. 먼저 새 키가 키 세트에 추가됩니다. 이 키는 아직 기본 키로 설정되지 않았지만 활성 상태입니다. 이 새로운 키 세트는 모든 바이너리에 출시됩니다. 모든 바이너리가 새 키를 알게 되면 키가 기본 키가 됩니다 (이 시점에서만 이 키를 사용하는 것이 안전함). 이 2단계에서 키 순환은 마지막으로 추가된 키를 알아야 합니다. ↩

  2. Google 내부 라이브러리와의 호환성을 위해 Tink에서는 ID가 반복되는 키셋을 사용할 수 있습니다. 이 지원은 향후 삭제될 예정입니다. ↩