키 세트

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를 작성할 수 있습니다. 이 클래스를 사용하려면 암호화 프리미티브에 대한 설명을 제공해야 합니다.

키 순환

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

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

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

암호문의 키 식별자

AEAD 키 세트의 예를 다시 생각해 보세요. 단순하게 암호화된 텍스트를 복호화하려면 Tink에서 키 세트의 모든 키로 복호화해야 합니다. 키 세트를 암호화하는 데 사용된 키를 알 수 없기 때문입니다. 이로 인해 막대한 성능 오버헤드가 발생할 수 있습니다.

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

키가 키 세트에 있으면 Tink는 키 세트에 있는 키의 ID로 이 태그를 계산합니다. 키 세트 내에서 ID가 고유2한다는 사실은 태그가 고유함을 의미합니다. 따라서 태그가 지정된 키만 사용하는 경우 단일 키로 복호화하는 경우에 비해 성능 저하가 없습니다. Tink는 복호화 시 키 중 하나만 사용해 보면 됩니다.

그러나 태그가 키의 일부이므로 이는 특정 ID가 하나인 경우에만 키가 키 세트에 있을 수 있음을 의미합니다. 이는 키 객체의 구현을 다양한 언어로 설명할 때 몇 가지 영향을 미칩니다.


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

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