1P by GN⁺ | ★ favorite | 댓글 1개
  • XAES-256-GCM은 고수준 암호화 API에서 논스 관리를 덜 위험하게 만들기 위해 256비트 키와 192비트 논스를 쓰는 새 AEAD 명세임
  • 큰 논스는 메시지마다 운영체제 CSPRNG에서 새 값을 자동 생성하는 방식을 가능하게 하며, 2⁸⁰개 메시지에서 충돌 위험 2⁻³² 수준을 목표로 함
  • 내부적으로는 입력 키와 큰 논스에서 파생 키와 96비트 논스를 만든 뒤, 표준 AES-256-GCM을 그대로 사용하는 확장 논스 구성임
  • Go 참조 구현은 crypto/ciphercrypto/aes만으로 100줄 미만에 들어가며, 메시지당 AES-256 호출 3회 중 일부는 사전 계산 가능함
  • FIPS 140 준수와 라이브러리 호환성을 중시해, XChaCha20Poly1305·AES-GCM-SIV와 함께 논스 없는 AEAD API 후보로 쓰일 수 있음

고수준 API를 위한 큰 논스 AEAD

  • XAES-256-GCM추가 인증 데이터가 있는 인증 암호화(AEAD) 알고리듬으로, 256비트 키와 192비트 논스를 사용함
  • 설계 목표는 세 가지로 압축됨
    • 사실상 무제한에 가까운 메시지 수에서도 무작위 생성이 안전한 큰 논스 지원
    • 완전하고 직접적인 FIPS 140 준수
    • 일반적인 암호화 라이브러리 위에서 쉬운 구현
  • 큰 논스 덕분에 사용자가 birthday bound 계산을 직접 하지 않아도, 메시지마다 운영체제 CSPRNG에서 새 논스를 읽는 API를 만들 수 있음
  • 준수성과 호환성을 우선해, 다른 큰 논스 AEAD를 쓰기 어려운 환경에서도 AEAD가 필요한 곳에 적용 가능함

AES-256-GCM을 그대로 활용하는 확장 논스 구성

  • XAES-256-GCM은 XChaCha20Poly1305처럼 기존 AEAD 위에 올리는 확장 논스 구성
  • 입력 키와 192비트 논스에서 내부 AES-256-GCM용 파생 키와 파생 논스를 계산함
    • 입력 키와 논스는 각각 K, N
    • 파생 AES-256-GCM 키와 논스는 Kₓ, Nₓ
  • AES-256ₖ 호출과 논스 앞부분으로 Kₓ를 만들고, 입력 논스의 뒤 96비트를 Nₓ로 사용함
  • 메시지당 AES-256ₖ 호출은 3회 필요함
    • 이 중 하나는 주어진 키에 대해 사전 계산 가능함
    • 나머지 두 호출은 같은 키 스케줄을 재사용할 수 있음

구현은 짧고 표준 구성 요소로 기술 가능

  • Go 참조 구현은 사전 계산 최적화와 대부분의 보일러플레이트를 포함해 100줄 미만임
  • Go 구현은 표준 라이브러리의 crypto/ciphercrypto/aes만 사용함
  • XAES-256-GCM은 표준 NIST SP 800-108r1 KDF와 표준 NIST AES-256-GCM AEAD로도 기술 가능함
    • KDF는 counter-based KDF
    • PRF는 CMAC-AES256
    • 입력 키는 Kin
    • 라벨은 ASCII 문자 X, 즉 0x58
    • 컨텍스트는 입력 논스의 첫 96비트
    • 카운터 크기는 16비트
    • 선택적 L 필드는 생략
    • 출력은 256비트 파생 키
  • 파생 키와 입력 논스의 마지막 96비트가 AES-256-GCM에 들어감
  • 매개변수 선택 덕분에 KDF와 CMAC 추상화를 걷어내면, 단순히 카운터에 AES-256을 호출하는 방식보다 약간만 느리고 복잡함
  • 같은 매개변수는 고수준 OpenSSL API에서도 지원됨

서드파티 구현과 테스트 벡터

/11 포기와 대안

  • 이전 구상에는 XAES-256-GCM/11이라는 이름이 있었지만, 최종 명세에서는 /11을 포기함
  • /11은 성능 최적화였으며, AES-GCM을 쓰는 이유 중 하나가 FIPS 140 준수이기 때문에 라운드 수를 바꾸면 준수성이 사라짐
  • FIPS 140 준수가 목표가 아니라면 대안은 여러 가지임
    • AES-GCM-SIV
    • AES 코어 기반의 현대적 AEAD 구성
  • 명세의 Alternatives 섹션은 각 대안을 XAES-256-GCM과 비교함

Go와 논스 없는 AEAD API에서의 위치

  • XAES-256-GCM은 안전하고, 지루하며, 준수 가능하고, 상호운용 가능한 AEAD를 목표로 함
  • 주요 사용처는 Go에 추가하고 싶은 종류의 고수준 API
  • XAES-256-GCM은 XChaCha20Poly1305와 AES-GCM-SIV를 보완하며, 가상의 논스 없는 AEAD API 구현 후보로 설계됨
  • Go 표준 라이브러리에 Go 전용 구성을 추가하는 것을 선호하지 않기 때문에, 다른 암호화 라이브러리 유지관리자의 의견이 필요함

댓글과 토론

Hacker News 의견들
  • 설계가 아주 영리함: CMAC 기반이라 하위 수준 기본 요소가 없어도 AES-CBC로 키를 파생할 수 있음
    AES-CBC 관점에서는 L = AES-CBC-256ₖ(iv = 0¹²⁸, plaintext = 0¹²⁸)[:16]로 시작해 K1을 만들고, M1, M2를 암호화해 Kₓ를 얻은 뒤 Nₓ = N[12:]를 쓰는 식으로 볼 수 있음
    AES-CBC-256은 암호문의 첫 128비트 블록만 반환하고 패딩 블록은 버린다고 보면 되며, 패딩을 끌 수 없더라도 하위 수준 구현보다 같은 키로 AES 호출이 3번 더 드는 정도라 나쁘지 않음
    이 특성을 이용한 WebCrypto API 기반 JS 구현은 https://github.com/dchest/xaes에 있으며, AES-CBC용 CryptoKey를 그대로 받아 extractable=false로 IndexedDB에 저장하는 기능 같은 CryptoKey 특성도 지원함

    • 이 분야에서는 표준 표기처럼 보이지만, 솔직히 암호학 표기법은 싫음
      저 의사코드에서 숫자의 절반은 바이트 수를, 나머지 절반은 비트 수를 세는 것 같고, 알고리즘을 이미 모르면 어느 쪽인지 거의 알 수 없음
      예를 들어 N[:12]는 12바이트처럼 보이지만 0¹²⁸은 16바이트이고, X는 실제 문자 'X', 즉 비트열 01011000인데 L은 비트열 01001100이 아니라 변수임
      수학자들은 컴퓨터과학 쪽 사람들만큼 모호하지 않은 표기를 좋아하지 않는 게 분명해 보임
    • 0¹²⁰10000111 같은 으스스해 보이는 상수는, CMAC이 쓰는 하위 블록 암호의 블록 크기 b에 대해 차수 b인 기약다항식 중 0이 아닌 항 개수가 최소인 것들 가운데 사전순으로 첫 번째인 다항식의 계수를 나타낸 비트열임
      숨겨진 의도 같은 건 없음
    • 암호 쪽 전문가는 아니지만, 요약하면 표준 AES-GCM AEAD는 서로 다른 메시지에 같은 논스를 두 번 쓰면 치명적으로 깨지고[1], 논스 크기도 많은 경우 무작위 논스를 안전하게 쓰기엔 작다는 얘기로 이해됨
      이 작업은 AES-GCM 호출마다 논스뿐 아니라 키도 바꾸는 방식으로 그 문제를 쉽게 피하게 해줌
      또한 AES-GCM이 있으면 대체로 사용 가능한 “평범한” AES만 쓰고, 아직 약점이 있을지 모르는 새로운 복잡한 구성은 피함
      메시지당 오버헤드는 “평범한” AES로 암복호화해야 하는 작은 버퍼 2개와 더 긴 192비트 논스 정도임
      [1]: https://frereit.de/aes_gcm/
  • 무작위 논스를 쓸 때 약 2^32개 메시지마다 키를 교체해야 하는 순정 AES-GCM의 함정을 없애는 것처럼 보임
    AES-GCM에서 논스 충돌은 치명적이고, 적어도 공격자가 임의 메시지에 서명할 수 있게 만듦
    무작위 논스를 꼭 써야 하는 건 아니지만 보통 권장되며, 카운터 기반 키 파생 함수와 순정 GCM이라는 두 기본 요소를 써서 FIPS 준수로 만드는 점이 꽤 영리함

    • 정확히는 이 방식이 애초에 무작위 논스를 안전하게 만들어줌
      표준 AES-GCM에서는 96비트가 무작위 충돌을 피하기에 충분하지 않으므로 결정적 논스 생성을 써야 함
      또한 논스를 어떻게 만들었든 카운터가 롤오버되어 다음 블록이 첫 블록과 같은 논스+카운터를 쓰게 되므로, 2^32 블록 이후에는 논스나 키를 바꿔야 함
  • 정말 굉장함. 몇 년 전 마지막으로 암호화 파일시스템을 만들 때 이게 있었으면 좋았겠음
    대규모 파일시스템 배포에서는 논스 충돌이 큰 걱정거리임
    2^32는 커 보이지만, PB급 배열에서 초당 100k IOPS로 쓰기를 하면서 의사난수 생성기의 무작위성에 기대면 충돌 가능성은 거의 보장된 수준임

    • CAESAR 경쟁[1]은 2019년에 끝났고, 논스 공간이 충분한 여러 AEAD가 결과로 나왔음
      [1] https://en.m.wikipedia.org/wiki/CAESAR_Competition
    • 그런데 왜 논스 충돌이 문제인지 궁금함
      두 블록이 같은 암호화 키를 공유한다는 뜻일 뿐 아닌가?
      어느 블록의 평문도 모른다면 그게 시스템 보안을 어떻게 약화시키는지 모르겠음
  • 보관용 파일 암호화 용도로 FIPS 준수 age 변형에 이게 쓰이면 좋겠음
    은행권 감사에서 age가 ChaCha를 쓴다는 이유로 이 용도에 퇴짜를 놨고, age의 X25519 공개키 부분은 괜찮다고 봤음. X25519는 비교적 최근 NIST 승인을 받은 것으로 알고 있었음
    Go 경험은 없지만 age 명세를 보면 바로 끼워 넣을 수 있을 것 같고, 시간이 나면 시도해볼 수도 있겠음
    이름은 “compliant actually good encryption”의 의미로 “cage”라고 부르면 될 듯함
    1: https://github.com/FiloSottile/age

    • “compliant actually good encryption”은 어쩌면 모순어법일 수도 있음
    • 확인해보니 Ed25519는 승인된 것 같지만(FIPS 186-5), X25519는 아직 아닌 것으로 보임
    • 참고로 Go 표준 라이브러리에는 아직 XAES 구현이 없고, C2SP의 참조 구현만 있음
    • bge, bureaucratic good encryption
  • 비암호학자로서 궁금한데, 왜 192비트 논스를 쓰고 256비트를 쓰지 않는지 모르겠음
    실용적인 애플리케이션에서 그 추가 비트들이 비용으로 여겨질 것 같지는 않음

    • 256비트를 넣을 공간이 없음. 192비트는 하위 논스 공간에서 오는 96비트와, 필요한 접두사와 함께 128비트 CMAC 블록에 들어가는 96비트로 구성됨
      CMAC 입력을 더 길게 만들 수도 있지만, 그러면 AES-256 블록 함수를 더 여러 번 실행해야 하고 CMAC 키 파생 함수에서 성가신 키 제어 문제도 마주치게 됨
      XChaCha20Poly1305가 192비트 논스를 쓰는 이유와도 비슷하며, 다른 주요 확장 논스 AEAD와 일관된다는 점도 약한 장점임
  • “2⁸⁰개 메시지에서 충돌 위험 2⁻³²”라고 했는데, AES 블록 크기가 128비트뿐이라는 사실 때문에 그 전에 문제가 생기지는 않나?

    • 블록에 대한 생일 한계(https://sweet32.info)를 말하는 거라면, 그건 단일 키로 암호화된 블록 수에 대한 제한임
      XAES는 메시지마다 큰 키를 파생하므로 흔히 생일 한계보다 나은 보장이라고 부르는 것을 달성함
    • 아님
      왜 문제가 된다고 생각하는지 더 자세한 맥락이 없으면 이보다 더 자세히 답하기는 어려움
  • “안전하고, 지루하고, 준수 가능하고, 상호운용 가능하다”
    내가 가장 좋아하는 종류의 기술임

  • 좋음. 실제로 NIST 기반 구성이 있다는 건 반가움
    다만 NIST 키 파생 함수의 장점인 레이블과 컨텍스트 같은 기능을 여러 개 포기하게 되는 점은 아쉬움
    AES 호출 수를 최소화하려고 희생한 건 이해하지만, 특히 수백 바이트보다 긴 메시지라면 AES 호출 몇 번을 아끼는 것보다 강한 암호학적 분리를 더 우선했을 것 같음
    마지막으로, 96비트보다 긴 무작위 GCM 논스는 확실히 오해를 많이 받고 있으며 96비트 논스보다 더 나은 보장을 제공함[1]
    물론 메시지마다 새 키를 파생할 수 있다면 그쪽이 확실히 더 낫음
    [1] https://neilmadden.blog/2024/05/23/galois-counter-mode-and-r...