키 세트

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가 하나만 있는 경우에만 키가 키 세트에 있을 수 있음을 의미합니다. 이는 여러 언어로 키 객체의 구현을 설명할 때 몇 가지 의미가 있습니다.


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

  2. Google 내부 라이브러리와의 호환성을 위해 Tink는 ID가 반복되는 키 세트를 허용합니다. 이 지원은 향후 삭제될 예정입니다.