프리미티브 및 인터페이스

다음으로 Tink에서 사용되는 언어의 두 가지 중요한 요소인 기본인터페이스를 정의합니다.

기본 역할

프리미티브는 특정 작업을 안전하게 실행하는 모든 알고리즘에 해당하는 수학적 객체입니다. 예를 들어 AEAD 프리미티브는 Tink에서 Aead에 필요한 보안 속성을 충족하는 모든 암호화 알고리즘으로 구성됩니다.

프리미티브는 프로그래밍 언어 또는 이에 액세스하는 특정 방법에 구속되지 않는다는 점을 강조합니다. 대신 원시 특성을 순수한 수학적 객체로 생각해야 합니다. 예를 들어 AEAD라고 하면 기본적으로는 암호화를 수행하는 함수와 복호화를 실행하는 함수 쌍으로 구성됩니다.

인터페이스

인터페이스는 사용자에게 프리미티브에 대한 액세스를 제공하는 방법입니다. 예를 들어, 향후 Tink는 Mac 인터페이스뿐만 아니라 메모리에 직접 로드되지 않은 데이터의 MAC을 계산할 수 있는 StreamingMac 인터페이스도 제공할 것으로 예상됩니다.

여기서는 인터페이스와 프리미티브를 명시적으로 구분합니다. 이렇게 하면 두 인터페이스가 액세스 권한을 부여하는 수학적 객체가 동일함을 명확하게 알 수 있습니다.

공식 정의

대부분의 독자는 위의 직관적인 설명만으로도 충분할 것입니다. 하지만 Google에서는 이러한 개념에 대한 공식적인 정의를 제공하는 것이 중요할 수도 있다고 생각합니다.

암호화 함수

암호화 함수의 개념은 프리미티브의 개념만큼 중요하지 않지만 원시 함수를 공식적으로 정의하기 위해서는 이를 도입해야 합니다.

암호화 함수

암호화 함수

\[ f: {\bf K} \times {\bf R} \times {\bf I} \to {\bf O}\]

집합 \({\bf K}\) (키 공간), 집합 \({\bf R} = \{0,1\}^{\infty}\)(무한 비트 문자열 집합으로 가정되는 무작위성), 집합 \({\bf I}\) (입력 공간)에서 집합 \({\bf O}\) (출력 공간)으로 옮겨집니다.

특정 임의성 매개변수를 추가한 이유는 나중에 명확하게 알 수 있습니다.

예를 들어 이러한 개념을 AES-GCM에 어떻게 매핑할 수 있는지 한 가지 가능성을 보여드리겠습니다. 유효한 키 크기 \(s_k\), nonce 크기 \(s_n\), 태그 크기\(s_t\)의 경우 AES-GCM은 두 가지 암호화 함수로 구성됩니다. 하나는 암호화용이고 다른 하나는 복호화용입니다. 둘 다 동일한 키 공간 \({\bf K} = \{0,1\}^{s_k}\)을 갖게 됩니다.

암호화 함수 \(\mathrm{Enc}\)의 경우 난수의 처음 \(s_n\) 비트가 nonce를 선택하는 데 사용됩니다.

\({\bf B} = \{0,1\}^8\) 는 한 바이트를 나타냅니다. 암호화 함수의 입력 공간은 임의의 길이의 바이트 문자열 \({\bf I} = {\bf B}^{*} \times {\bf B}^{*}\) 쌍 쌍입니다. 쌍의 첫 번째 요소는 메시지가 되고, 두 번째 요소는 연결된 데이터입니다. AES-GCM 표준에는 입력 길이의 상한이 있지만, Google은 임의 길이를 허용하는 것을 선호하며, 그 대신 출력 공간에 특수한 오류 기호 \(\bot\) 를 추가합니다. 그러면 출력 공간은 \({\bf O} = {\bf B}^* \cup \{\bot\}\)이 됩니다. 여기서는 성공한 계산의 결과를 표준에 지정된 연결 \((\mathrm{IV} \| \mathrm{ciphertext} \| \mathrm{tag})\) 로 임의로 정의하고, 일부 입력이 너무 긴 경우\(\bot\)를 출력합니다. 따라서 고정 키의 경우 암호화 함수는 \(\mathrm{Enc}_k : {\bf R} \times {\bf B}^* \times {\bf B}^* \rightarrow {\bf B}^* \cup \{\bot\}\)유형이 됩니다.

복호화 함수의 경우 \(\mathrm{Dec}\) 키 공간은 동일합니다. 그와 동시에 입력 공간도 동일합니다( \({\bf I} ={\bf B}^* \times {\bf B}^*\)). 하지만 이제 첫 번째 요소는 암호화 함수의 출력이고 두 번째 요소는 여전히 연결된 데이터입니다.

출력 공간도 동일합니다 \({\bf O} = {\bf B}^* \cup \{\bot\}\) (또 다른 우연의 일치). 일반적으로 \(\bot\) 는 인증 오류를 나타내므로 해석은 약간 다릅니다. 하지만 일부 입력이 너무 긴 경우 출력으로 표시되기도 합니다.

위의 형식화가 표준을 공식화하는 유일한 옵션이 아닙니다. 예를 들어 무작위성에서 nonce를 읽는 대신 입력의 일부로 간주할 수 있습니다 (그 결과 원시값이 매우 다름). 또는 연결 대신 nonce, 암호문, 태그를 포함하는 삼중으로 출력을 정의할 수 있습니다. 또는 키 공간을 어느 정도 임의로\({\bf K} = \{0,1\}^{128} \cup \{0,1\}^{256}\)로 제한할 수 있습니다.

암호화 알고리즘:

(대칭) 암호화 알고리즘은 튜플입니다.

\[(f_1, ... f_k)\]

동일한 키 공간을 갖는 암호화 함수입니다. 암호화 알고리즘의 유형은 \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\)튜플입니다.

예를 들어, 유효한 키, nonce, 태그 크기의 삼중 \((s_k, s_n, s_t)\) 에 관해 AES-GCM\({}_{s_k, s_n, s_t}\) 은 위에 설명한 두 함수 \(\mathrm{Enc}\) 및 \(\mathrm{Dec}\) 를 갖는 암호화 알고리즘입니다.

프리미티브 및 인터페이스

다음으로 암호화 프리미티브를 정의합니다.

기본 역할
기본 요소는 암호화 알고리즘의 집합으로, 모든 알고리즘이 동일한 유형 \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\)을 가지며 알고리즘의 키 공간이 쌍으로 분리됩니다.

예를 들어 Tink의 \(\mathrm{AEAD}\) 프리미티브를 생각해 보세요. 여러 알고리즘이 있으며 그중 키 크기 128 및 256비트의 AES-GCM, nonce 크기 96비트, 일부 키 크기가 있는 AES-EAX, XChaCha20Poly1305입니다. 독립된 키 공간이 있지만 모두 동일한 암호화 기능\(\mathrm{Enc}\) 및 \(\mathrm{Dec}\)를 제공합니다. (이 공식 논의에서 AES-GCM의 다양한 키 크기를 축소하는 목적은 아니나, 당연히 그렇게 할 수 있습니다.)

프리미티브 정의

일반적으로 프리미티브는 암호화 함수의 속성을 정의한 후 프리미티브를 이러한 모든 알고리즘으로 간주하는 것입니다.

예를 들어 AEAD의 경우 \(\mathrm{Dec}_k(\mathrm{Enc}_k(m, a), a) = m\) 이 '항상' 충족된다고 합니다 (예: 일반 텍스트 \(m\) 가 너무 긴 경우 제외). 또한 보안 속성도 있습니다. 예를 들어 임의의 키의 경우 암호화가 의미론적으로 안전합니다.

그러면 AEAD 프리미티브는 단순히 이러한 속성을 충족하는 모든 암호화 알고리즘의 집합입니다. 즉, 실제로 특정 프리미티브를 정의할 때 속성을 기반으로 정의합니다. 정의에서 알 수 있듯이 Google은 알고리즘 목록을 제공하지 않습니다.

인터페이스

Tink의 인터페이스는 입력 공간에서 출력 공간의 요소를 계산할 수 있다는 점에서 프리미티브에 대한 액세스를 제공합니다. 예를 들어 다음과 같이 Java의 AEAD 인터페이스를 생각해 보세요.

public interface Aead {
  byte[] encrypt(byte[] plaintext, byte[] associated_data) throws GeneralSecurityException;
  byte[] decrypt(byte[] ciphertext, byte[] associated_data) throws GeneralSecurityException;
}

임의성에 대한 액세스 권한은 부여하지 않습니다. 대신 사용자가 입력 공간 요소를 제공할 수 있습니다. 무작위성에 대한 액세스를 허용하지 않는 것은 당연한 것입니다.1

종종 Tink는 단일 프리미티브에 여러 인터페이스를 제공합니다. 요구사항이 다를 수 있으므로 이는 매우 유용할 수 있습니다. 하지만 이렇게 하는 데는 대가가 따릅니다. 일반적으로 제공하는 인터페이스가 많을수록 상호 운용성이 낮아집니다. 예를 들어 누군가가 내부적으로 암호화하기 위해 Aead 객체를 전달해야 하는 Tink 기반의 라이브러리를 작성한다고 가정해 보겠습니다. Tink가 \(\mathrm{AEAD}\) 프리미티브에 너무 많은 다른 인터페이스를 제공하면 사용자는 사용자가 선택한 키와 동시에 라이브러리에 대해 작동하는 인스턴스를 준비하지 못할 수 있습니다. 따라서 인터페이스를 추가하면 장단점이 있습니다.


  1. AEAD 암호화는 선택된 암호문 공격에 대해 안전한 특성을 지니며, 이는 nonce의 재사용이 없는 경우에만 보장됩니다. Tink의 Aead 인터페이스는 nonce 재사용을 방지하도록 설계되었습니다. 사용자는 암호화를 위한 입력으로 nonce를 제공할 수 없는 대신 각 암호화 작업에 대해 새로운 nonce가 무작위로 생성됩니다.