해싱 및 메시지 인증

암호화 해시는 임의 크기의 데이터를 짧고 고정된 크기의 다이제스트로 변환합니다. 동일한 입력은 항상 동일한 다이제스트를 만들고, 단 한 비트라도 다른 입력은 완전히 다른 다이제스트를 만들며, 원하는 다이제스트를 만들어내는 입력을 실질적으로 찾아낼 방법은 없습니다. 메시지 인증 코드(MAC)는 여기에 비밀 키를 더해, 키를 가지지 않은 사람이 데이터를 변조하지 않았음도 함께 증명합니다.

 

이 페이지의 모든 함수는 TBytes를 받고 반환하며, sgcCrypto_SHA2, sgcCrypto_Keccak, sgcCrypto_Blake2b, sgcCrypto_Blake2s, sgcCrypto_SipHash, sgcCrypto_HMAC, sgcCrypto_CMAC, sgcCrypto_Poly1305에 들어 있습니다.

 

SHA-2

 

TLS 인증서, 코드 서명, 그리고 오늘날 사용되는 대부분의 프로토콜 뒤에 있는 해시 계열입니다. 특별히 다른 크기가 필요하지 않다면 SHA-256을 사용하십시오.

 


function sgcSHA1(const aData: TBytes): TBytes;
function sgcSHA224(const aData: TBytes): TBytes;
function sgcSHA256(const aData: TBytes): TBytes;
function sgcSHA384(const aData: TBytes): TBytes;
function sgcSHA512(const aData: TBytes): TBytes;

 

SHA-3, SHAKE, cSHAKE, KMAC

 

SHA-3은 SHA-2와 다른 구조(Keccak)를 기반으로 하기 때문에, 한 계열의 약점이 다른 계열로 이어지지 않습니다. 장기적인 안전성이 필요한 프로토콜이 둘 다 명시하는 경우가 많은 이유입니다. SHAKE128과 SHAKE256은 확장 가능한 출력 함수로, 고정된 다이제스트 크기 대신 필요한 만큼의 바이트를 요청할 수 있으며, 같은 입력에서 나온 짧은 출력은 항상 더 긴 출력의 앞부분과 일치합니다. ML-KEM, ML-DSA, SLH-DSA(포스트 양자 암호화 참조)는 모두 내부적으로 SHAKE를 기반으로 합니다. KMAC은 cSHAKE를 기반으로 한 SHA-3 고유의 메시지 인증 코드입니다.

 


function sgcSHA3_224(const aData: TBytes): TBytes;
function sgcSHA3_256(const aData: TBytes): TBytes;
function sgcSHA3_384(const aData: TBytes): TBytes;
function sgcSHA3_512(const aData: TBytes): TBytes;
function sgcSHAKE128(const aData: TBytes; aLen: Integer): TBytes;
function sgcSHAKE256(const aData: TBytes; aLen: Integer): TBytes;
function sgcKMAC128(const aKey, aData: TBytes; aLen: Integer; const aCustom: TBytes): TBytes;
function sgcKMAC256(const aKey, aData: TBytes; aLen: Integer; const aCustom: TBytes): TBytes;

 

BLAKE2b, BLAKE2s

 

BLAKE2는 SHA-2 및 SHA-3와 동일한 보안 여유를 제공하면서도 소프트웨어 상에서 더 빠르며, HMAC 구조 없이 선택적인 키를 직접 받을 수 있습니다. BLAKE2b는 최대 512비트 다이제스트를 지원하는 64비트 플랫폼을 대상으로 하고, BLAKE2s는 최대 256비트 다이제스트를 지원하는 32비트 및 임베디드 플랫폼을 대상으로 합니다. 더 짧은 다이제스트는 전체 다이제스트를 잘라낸 것이 아니며, 길이 자체가 해시에 함께 섞여 들어가므로, 크기를 바꾼다고 해서 출력이 일치하리라 기대할 수 없습니다.

 


function sgcBlake2b(const aData: TBytes; aDigestLen: Integer = 64): TBytes;
function sgcBlake2b_Keyed(const aKey, aData: TBytes; aDigestLen: Integer = 64): TBytes;
function sgcBlake2s(const aData: TBytes; aDigestLen: Integer = 32): TBytes;
function sgcBlake2s_Keyed(const aKey, aData: TBytes; aDigestLen: Integer = 32): TBytes;

 

SipHash

 

SipHash-2-4는 해시 테이블 조회를 위해 설계된 빠르고 키가 있는 해시입니다. 이 함수의 역할은 공격자가 애플리케이션에 의도적으로 고른 입력을 넣어 모두 같은 버킷에 몰리게 함으로써 O(1) 조회를 O(n)으로 바꾸는, 해시 플러딩이라 불리는 서비스 거부 기법을 막는 것입니다. 정확히 16바이트의 키를 받아 8바이트 태그를 생성하며, 범용 MAC이 아니므로 메시지 인증에 사용해서는 안 됩니다.

 


function sgcSipHash24(const aKey, aData: TBytes): TBytes;

 

HMAC

 

HMAC은 위의 해시 중 어느 것이든 메시지 인증 코드로 바꿔줍니다. 기반이 되는 해시가 키를 직접 받지 않는 경우(SHA-1, SHA-2)에 표준적으로 선택하는 방법입니다.

 


function sgcHMAC_SHA1(const aKey, aData: TBytes): TBytes;
function sgcHMAC_SHA256(const aKey, aData: TBytes): TBytes;
function sgcHMAC_SHA384(const aKey, aData: TBytes): TBytes;
function sgcHMAC_SHA512(const aKey, aData: TBytes): TBytes;

var
  oTag: TBytes;
begin
  oTag := sgcHMAC_SHA256(TBytes(oKey), TBytes(oMessage));
end;

 

AES-CMAC

 

CMAC은 해시가 아니라 블록 암호로부터 MAC을 만듭니다. 프로토콜이 AES-CMAC을 이름으로 명시하는 경우(스마트카드 및 IoT 사양에서 흔함)에 사용하십시오. 그 외에는 HMAC-SHA256이 더 일반적인 기본값입니다.

 


function sgcAES_CMAC(const aKey, aData: TBytes): TBytes;
function sgcAES_CMAC_Verify(const aKey, aData, aTag: TBytes): Boolean;

 

Poly1305

 

Poly1305는 일회용 인증자입니다: 같은 키로 두 번 사용해서는 절대 안 됩니다. 실제로는 직접 호출되는 경우가 거의 없으며, 대칭 암호화 페이지에 있는 ChaCha20-Poly1305 및 XChaCha20-Poly1305 AEAD 암호의 인증 절반을 담당하며, 이들은 메시지마다 새로운 일회용 키를 유도합니다.

 


function sgcPoly1305(const aKey, aData: TBytes): TBytes;
function sgcPoly1305_Verify(const aKey, aData, aTag: TBytes): Boolean;

 

MAC이나 비밀번호 해시 비교하기

 

둘 중 하나라도 신뢰할 수 없는 출처에서 왔다면, 태그나 다이제스트 두 개를 단순한 =로 절대 비교하지 마십시오. 불일치를 발견하는 즉시 반환되는 바이트 단위 비교는 불일치가 앞쪽에서 발생할수록 측정 가능할 만큼 시간이 덜 걸리며, 이는 공격자가 한 번에 한 바이트씩 여러 번의 시도로 유효한 태그를 위조할 수 있는 신호가 됩니다. 대신 암호화 개요 페이지의 인코딩 및 유틸리티 항목에 있는 sgcCrypto_Encoding의 상수 시간 비교를 사용하십시오.

 


function sgcConstantTimeEquals(const aLeft, aRight: TBytes): Boolean;

 

RIPEMD-160

 

유럽 RIPE 프로젝트에서 나온 160비트 다이제스트로, sgcCrypto_Legacy에 들어 있지만 아래 절이 의미하는 것과 같은 의미의 레거시는 아닙니다. MD5와 SHA-1처럼 깨진 것은 아니지만, SHA-256보다 느리고 보안 여유도 더 적으므로, 기본 선택이 아니라 형식이 이를 구체적으로 명시하는 경우에 사용해야 합니다. Bitcoin과 그로부터 파생된 모든 체인이 SHA-256 위에 계층화하여 주소에 사용합니다. HMAC-RIPEMD160은 RFC 2286입니다.

 


function sgcRIPEMD160(const aData: TBytes): TBytes;
function sgcHMAC_RIPEMD160(const aKey, aData: TBytes): TBytes;

var
  oHash160: TBytes;
begin
  { the Bitcoin address digest: RIPEMD-160 over SHA-256 }
  oHash160 := sgcRIPEMD160(sgcSHA256(oPublicKey));
end;

 

레거시 해시

 

sgcCrypto_Legacy는 MD4, MD5, HMAC-MD5를 제공합니다. 세 가지 모두 보안 요소로서는 깨진 것으로 취급됩니다: MD4와 MD5 모두에 대해 실제 충돌 사례가 발표되었습니다. 이들은 오직 이름으로 명시하는 오래된 프로토콜 및 파일 형식(예를 들어 NTLM 인증)과의 상호 운용을 위해서만 존재합니다. 새로운 용도로는 선택하지 말고, 대신 SHA-256이나 BLAKE2b를 사용하십시오.

 


function sgcMD4(const aData: TBytes): TBytes;
function sgcMD5(const aData: TBytes): TBytes;
function sgcHMAC_MD5(const aKey, aData: TBytes): TBytes;