다음을 통해 공유


ASP.NET Core의 컨텍스트 헤더

배경 및 이론

데이터 보호 시스템에서 "키"는 인증된 암호화 서비스를 제공할 수 있는 개체를 의미합니다. 각 키는 고유 ID(GUID)로 식별되며 알고리즘 정보 및 엔트로픽 자료와 함께 전달됩니다. 각 키는 고유한 엔트로피를 전달하지만 시스템은 이를 적용할 수 없으며 키 링에서 기존 키의 알고리즘 정보를 수정하여 키 링을 수동으로 변경할 수 있는 개발자를 고려해야 합니다. 이러한 경우를 고려하여 보안 요구 사항을 달성하기 위해 데이터 보호 시스템에는 여러 암호화 알고리즘에서 단일 엔트로피 값을 안전하게 사용할 수 있는 암호화 민첩성 개념이 있습니다.

암호화 민첩성을 지원하는 대부분의 시스템은 페이로드 내에 알고리즘에 대한 몇 가지 식별 정보를 포함하여 이 작업을 수행합니다. 알고리즘의 OID는 일반적으로 적합한 후보입니다. 그러나 한 가지 문제는 동일한 알고리즘을 지정하는 여러 가지 방법이 있다는 것입니다. "AES"(CNG) 및 관리되는 Aes, AesManaged, AesCryptoServiceProvider, AesCng 및 RijndaelManaged(지정된 특정 매개 변수) 클래스는 모두 실제로 동일하며 이러한 모든 클래스를 올바른 OID에 매핑해야 합니다. 개발자가 사용자 지정 알고리즘(또는 다른 AES 구현)을 제공하려는 경우 OID를 알려야 합니다. 이 추가 등록 단계는 시스템 구성을 특히 어렵게 만듭니다.

한 걸음 물러서서 우리는 잘못된 방향으로 문제에 접근하고 있다고 결정했습니다. OID는 알고리즘이 무엇인지 알려주지만 실제로는 신경 쓰지 않습니다. 두 가지 알고리즘에서 단일 엔트로픽 값을 안전하게 사용해야 하는 경우 알고리즘이 실제로 무엇인지 알 필요가 없습니다. 우리가 실제로 관심있는 것은 그들이 어떻게 행동하는지입니다. 모든 적절한 대칭 블록 암호 알고리즘은 강력한 의사난수 순열(PRP)입니다. 입력값(키, 체인 모드, IV, 평문)을 고정하고, 암호문 출력은 주어졌을 때 동일한 입력을 가진 다른 대칭 블록 암호 알고리즘과 압도적인 확률로 구별됩니다. 마찬가지로, 모든 괜찮은 키 해시 함수는 강력한 의사난수 함수(PRF)이며, 고정된 입력 집합을 감안할 때 출력은 다른 키 해시 함수의 출력과 현저하게 구별됩니다.

강력한 PRP 및 PRF의 이 개념을 사용하여 컨텍스트 헤더를 빌드합니다. 이 컨텍스트 헤더는 기본적으로 지정된 작업에 사용되는 알고리즘에 대해 안정적인 지문 역할을 하며 데이터 보호 시스템에 필요한 암호화 민첩성을 제공합니다. 이 헤더는 재현 가능하며 나중에 하위 키 파생 프로세스의 일부로 사용됩니다. 기본 알고리즘의 작업 모드에 따라 컨텍스트 헤더를 빌드하는 방법에는 두 가지가 있습니다.

CBC 모드 암호화 + HMAC 인증

컨텍스트 헤더는 다음 구성 요소로 구성됩니다.

  • [16비트] 값 00 00은 "CBC 암호화 + HMAC 인증"을 의미하는 표식입니다.

  • [32비트] 대칭 블록 암호 알고리즘의 키 길이(바이트, big-endian)입니다.

  • [32비트] 대칭 블록 암호 알고리즘의 블록 크기(바이트, big-endian)입니다.

  • [32비트] HMAC 알고리즘의 키 길이(바이트 단위, 빅 엔디언 형식)입니다. (현재 키 크기는 항상 다이제스트 크기와 일치합니다.)

  • [32비트] HMAC 알고리즘의 다이제스트 크기(바이트, 빅 엔디안)입니다.

  • EncCBC(K_E, IV, "")- 빈 문자열 입력이 지정된 대칭 블록 암호 알고리즘의 출력이며 여기서 IV는 모두 0인 벡터입니다. K_E의 구성은 아래에 설명되어 있습니다.

  • MAC(K_H, "")- 빈 문자열 입력이 지정된 HMAC 알고리즘의 출력입니다. K_H의 구성은 아래에 설명되어 있습니다.

이상적으로는 모두 0으로 된 벡터를 K_EK_H 로 전달할 수 있습니다. 그러나 기본 알고리즘이 모든 연산(특히 DES 및 3DES)을 수행하기 전에 약한 키의 존재를 확인하는 상황을 방지하려고 합니다. 이 경우 모든 0 벡터와 같은 단순하거나 반복 가능한 패턴을 사용하는 것을 배제합니다.

대신 NIST SP800-108 KDF를 카운터 모드( NIST SP800-108, Sec. 5.1 참조)에서 길이가 0인 키, 레이블 및 컨텍스트와 HMACSHA512를 기본 PRF로 사용하여 적용합니다. 우리는 | K_E | + | K_H | 바이트의 출력을 생성한 다음, 결과를 K_EK_H로 분해합니다. 수학적으로 다음과 같이 표시됩니다.

( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = "")

예: AES-192-CBC + HMACSHA256

예를 들어 대칭 블록 암호 알고리즘이 AES-192-CBC이고 유효성 검사 알고리즘이 HMACSHA256 경우를 고려합니다. 시스템은 다음 단계를 사용하여 컨텍스트 헤더를 생성합니다.

먼저, 지정된 알고리즘에 따라 ( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = "")을 설정하고, | K_E | = 192 bits| K_H | = 256 bits를 적용합니다. K_E = 5BB6..21DD K_H = A04A..00A9 이는 아래 예제와 같습니다.

5B B6 C9 83 13 78 22 1D 8E 10 73 CA CF 65 8E B0
61 62 42 71 CB 83 21 DD A0 4A 05 00 5B AB C0 A2
49 6F A5 61 E3 E2 49 87 AA 63 55 CD 74 0A DA C4
B7 92 3D BF 59 90 00 A9

다음으로, 위에서 주어진 IV = 0*K_E에 따라 AES-192-CBC를 계산하여 Enc_CBC (K_E, IV, "")를 구합니다.

result := F474B1872B3B53E4721DE19C0841DB6F

다음으로, 위와 같은 K_H를 사용하여 HMACSHA256을 계산합니다.

result := D4791184B996092EE1202F36E8608FA8FBD98ABDFF5402F264B1D7211536220C

그러면 아래의 전체 컨텍스트 헤더가 생성됩니다.

00 00 00 00 00 18 00 00 00 10 00 00 00 20 00 00
00 20 F4 74 B1 87 2B 3B 53 E4 72 1D E1 9C 08 41
DB 6F D4 79 11 84 B9 96 09 2E E1 20 2F 36 E8 60
8F A8 FB D9 8A BD FF 54 02 F2 64 B1 D7 21 15 36
22 0C

이 컨텍스트 헤더는 인증된 암호화 알고리즘 쌍(AES-192-CBC 암호화 + HMACSHA256 유효성 검사)의 지문입니다. 위에서 설명한 대로 구성 요소는 다음과 같습니다.

  • 표식 (00 00)

  • 블록 암호 키 길이 (00 00 00 18)

  • 블록 암호 블록 크기 (00 00 00 10)

  • HMAC 키 길이 (00 00 00 20)

  • HMAC 다이제스트 크기 (00 00 00 20)

  • 블록 암호 PRP 출력 (F4 74 - DB 6F)

  • HMAC PRF 출력 (D4 79 - end).

비고

CBC 모드 암호화 + HMAC 인증 컨텍스트 헤더는 알고리즘 구현이 Windows CNG에서 제공되는지 또는 관리되는 SymmetricAlgorithm 및 KeyedHashAlgorithm 형식에 의해 제공되는지에 관계없이 동일한 방식으로 빌드됩니다. 이렇게 하면 여러 운영 체제에서 실행되는 애플리케이션이 알고리즘의 구현이 OS 간에 다르더라도 동일한 컨텍스트 헤더를 안정적으로 생성할 수 있습니다. (실제로 KeyedHashAlgorithm은 적절한 HMAC일 필요는 없습니다. 키 해시 알고리즘 유형일 수 있습니다.)

예: 3DES-192-CBC + HMACSHA1

먼저, 지정된 알고리즘에 따라 ( K_E || K_H ) = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = "")을 설정하고, | K_E | = 192 bits| K_H | = 160 bits를 적용합니다. K_E = A219..E2BB K_H = DC4A..B464 이는 아래 예제와 같습니다.

A2 19 60 2F 83 A9 13 EA B0 61 3A 39 B8 A6 7E 22
61 D9 F8 6C 10 51 E2 BB DC 4A 00 D7 03 A2 48 3E
D1 F7 5A 34 EB 28 3E D7 D4 67 B4 64

다음으로, 위의 IV = 0*K_E를 사용하여 3DES-192-CBC용 Enc_CBC (K_E, IV, "")를 계산합니다.

result := ABB100F81E53E10E

다음으로, 위와 같이 지정된 K_H을 사용하여 MAC(K_H, "")을 HMACSHA1으로 계산하십시오.

result := 76EB189B35CF03461DDF877CD9F4B1B4D63A7555

그러면 아래와 같이 인증된 암호화 알고리즘 쌍(3DES-192-CBC 암호화 + HMACSHA1 유효성 검사)의 지문인 전체 컨텍스트 헤더가 생성됩니다.

00 00 00 00 00 18 00 00 00 08 00 00 00 14 00 00
00 14 AB B1 00 F8 1E 53 E1 0E 76 EB 18 9B 35 CF
03 46 1D DF 87 7C D9 F4 B1 B4 D6 3A 75 55

구성 요소는 다음과 같이 세분화됩니다.

  • 표식 (00 00)

  • 블록 암호 키 길이 (00 00 00 18)

  • 블록 암호 블록 크기 (00 00 00 08)

  • HMAC 키 길이 (00 00 00 14)

  • HMAC 다이제스트 크기 (00 00 00 14)

  • 블록 암호 PRP 출력 (AB B1 - E1 0E)

  • HMAC PRF 출력 (76 EB - end).

Galois/카운터 모드 암호화 + 인증

컨텍스트 헤더는 다음 구성 요소로 구성됩니다.

  • [16비트] 값 00 01은 "GCM 암호화 + 인증"을 의미하는 표식입니다.

  • [32비트] 대칭 블록 암호 알고리즘의 키 길이(바이트, big-endian)입니다.

  • [32비트] 인증된 암호화 작업 중에 사용되는 nonce 크기(바이트, big-endian)입니다. (시스템의 경우 이는 nonce 크기 = 96비트로 설정되어 있습니다.)

  • [32비트] 대칭 블록 암호 알고리즘의 블록 크기(바이트, big-endian)입니다. (GCM의 경우 블록 크기가 128비트로 고정됩니다.)

  • [32비트] 인증된 암호화 함수에 의해 생성된 인증 태그 크기(바이트, big-endian)입니다. (시스템의 경우 태그 크기 = 128비트로 고정됩니다.)

  • [128비트] 빈 문자열 입력이 지정된 대칭 블록 암호 알고리즘의 출력이고 nonce가 96비트 올-제로 벡터인 경우의 태그 Enc_GCM (K_E, nonce, "")입니다.

K_E 는 CBC 암호화 + HMAC 인증 시나리오와 동일한 메커니즘을 사용하여 파생됩니다. 그러나 여기에서는 K_H가 없기 때문에 기본적으로 | K_H | = 0 알고리즘이 아래 형식으로 단순화됩니다.

K_E = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = "")

예: AES-256-GCM

우선, K_E = SP800_108_CTR(prf = HMACSHA512, key = "", label = "", context = "")를 놓고, | K_E | = 256 bits인 경우.

K_E := 22BC6F1B171C08C4AE2F27444AF8FC8B3087A90006CAEA91FDCFB47C1B8733B8

다음으로, 위와 같이 주어진 nonce = 096K_E를 사용하여 Enc_GCM (K_E, nonce, "")의 AES-256-GCM 인증 태그를 계산합니다.

result := E7DCCE66DF855A323A6BB7BD7A59BE45

그러면 아래의 전체 컨텍스트 헤더가 생성됩니다.

00 01 00 00 00 20 00 00 00 0C 00 00 00 10 00 00
00 10 E7 DC CE 66 DF 85 5A 32 3A 6B B7 BD 7A 59
BE 45

구성 요소는 다음과 같이 세분화됩니다.

  • 표식 (00 01)

  • 블록 암호 키 길이 (00 00 00 20)

  • 크기: nonce (00 00 00 0C)

  • 블록 암호 블록 크기 (00 00 00 10)

  • 인증 태그 크기 (00 00 00 10)

  • 블록 암호 실행의 인증 태그입니다 (E7 DC - end).