1P by GN⁺ 13일전 | ★ favorite | 댓글 1개
  • DuckDB 1.4 버전부터 저장 데이터 암호화(Data-at-Rest Encryption) 기능이 추가되어, 데이터베이스 파일 전체를 AES 기반 표준 암호화로 보호 가능
  • 지원 알고리듬은 AES-GCM-256AES-CTR-256, 이 중 GCM은 데이터 무결성 검증을 위한 인증 태그(tag) 를 포함
  • 암호화는 데이터베이스 파일, WAL(Write-Ahead Log), 임시 파일 모두에 적용되며, 키 관리와 메모리 보호를 위한 보안 캐시 구조를 포함
  • OpenSSLMbed TLS 두 가지 구현이 제공되며, OpenSSL 사용 시 하드웨어 가속으로 성능 저하가 거의 없음
  • 암호화된 DuckDB 파일은 보안성과 이식성을 동시에 확보하며, 클라우드나 CDN 환경에서도 안전한 데이터 배포 가능

암호화 개요

  • DuckDB 1.4부터 데이터베이스 파일 전체를 투명하게 암호화(Transparent Encryption) 가능
    • 저장 시 AES-GCM-256 또는 AES-CTR-256 암호화 사용
    • AES-GCM은 무결성 검증을 위한 태그를 계산하며, AES-CTR은 더 빠르지만 인증 기능이 없음
  • AES는 대칭키 암호화 알고리듬으로, 동일한 키로 암호화와 복호화를 수행
  • IV(Initialization Vector)와 nonce를 사용해 동일 평문이 다른 암호문으로 변환되도록 보장
  • NIST 표준 요건은 아직 완전히 충족하지 않음

DuckDB 내부 구현 구조

  • 데이터베이스 파일의 메인 헤더는 평문으로 유지되며, 암호화 여부를 나타내는 플래그와 암호화 메타데이터 저장
    • 메타데이터에는 데이터베이스 식별자(salt), 암호화 알고리듬 정보, 암호화된 canary 포함
  • 키 파생 함수(KDF) 를 통해 사용자 입력 키를 32바이트 보안 키로 변환
    • 파생된 키는 보안 캐시에 저장되어 디스크로 스왑되지 않음
    • 원본 키는 메모리에서 즉시 삭제
  • 데이터 블록은 기본 256KB 단위로 저장되며, 암호화 시 블록 헤더에 nonce/IV태그가 추가되어 40바이트로 확장
    • 체크섬은 암호화되어 저장

WAL(Write-Ahead Log) 암호화

  • WAL은 트랜잭션 복구용 로그 파일로, DuckDB에서는 항목 단위로 암호화 수행
    • 각 항목에 nonce와 태그를 추가하여 AES-GCM 방식으로 보호
    • 암호화된 WAL 항목은 길이(평문) → nonce → 암호화된 체크섬 및 데이터 → 태그 순으로 구성
  • 암호화 키가 지정된 데이터베이스에서는 WAL 암호화가 자동 활성화

임시 파일 암호화

  • 정렬, 조인, 윈도 함수 등 대용량 연산 시 생성되는 임시 파일도 자동 암호화
    • 암호화된 데이터베이스를 연결하거나 SET temp_file_encryption = true 설정 시 활성화
    • DuckDB가 내부적으로 임시 키를 생성하며, 충돌 시 복호화 불가
  • 임시 파일은 .tmp 또는 .block 확장자를 가지며, 크기 정보가 헤더에 포함
    • 체크섬은 계산 비용 절감을 위해 생략

암호화 사용 방법

  • 세 가지 방식 지원:
    1. 기존 데이터베이스 암호화
    2. 새 암호화 데이터베이스 생성
    3. 기존 암호화 데이터베이스 재암호화
  • 예시 명령:
    ATTACH 'encrypted.duckdb' AS encrypted (ENCRYPTION_KEY 'asdf');
    COPY FROM DATABASE unencrypted TO encrypted;
    
  • 암호화 여부는 FROM duckdb_databases(); 명령으로 확인 가능
  • 기본 암호화 알고리듬은 AES-GCM, 필요 시 AES-CTR로 지정 가능
  • 암호화된 데이터는 엔트로피(Entropy) 가 높아 무작위 데이터처럼 보임

구현 및 성능

  • DuckDB는 외부 의존성을 최소화하기 위해 Mbed TLSOpenSSL 두 가지 암호화 구현을 포함
    • Mbed TLS는 하드웨어 가속 비활성화로 성능이 낮고, 난수 생성기 취약점 발견으로 쓰기 기능 비활성화(1.4.1 이후)
    • OpenSSL은 하드웨어 가속 및 안전한 난수 생성기를 사용, httpfs 확장 로드 시 자동 전환
  • 성능 테스트 결과:
    • 비암호화 SUMMARIZE 쿼리: 5.4초
    • Mbed TLS 암호화: 6.2초
    • OpenSSL 암호화: 5.4초 (성능 저하 없음)
  • TPC-H Power/Throughput 테스트에서도 암호화 사용 시 성능 차이 미미
    • Power@Size: 624,296 → 571,985
    • Throughput@Size: 450,409 → 145,353 (디스크 I/O 증가 시 약간 감소)

결론

  • DuckDB의 저장 데이터 암호화 기능으로 데이터베이스 파일 전체를 안전하게 보호 가능
  • WAL과 임시 파일까지 암호화되어 클라우드 환경에서도 데이터 유출 위험 감소
  • OpenSSL 기반 구현 시 성능 손실 거의 없음, 실무 환경에서도 효율적 사용 가능
  • 암호화된 DuckDB 파일은 CDN 등 외부 배포에도 적합하며, 다중 테이블 저장 등 기존 기능 유지
  • DuckDB 팀은 향후 사용자 피드백을 통해 기능 개선 예정
Hacker News 의견
  • AES-GCM의 nonce 재사용 민감도는 구현 시 까다로운 부분임
    문서에서는 이를 인지하고 있지만 해결 방법을 공유하지 않았음
    헤더에 12바이트 대신 16바이트 nonce가 포함되어 있고, 어떤 바이트가 랜덤인지 명시되지 않아 혼란스러움. 혹시 내가 놓친 부분이 있는지 궁금함

    • 정적 키를 사용하고, 12바이트 랜덤 nonce를 생성하며, 임시 버퍼에는 세션별 키를 사용하지 않는 구조임
  • DuckDB 팀의 성과에 계속 놀라고 있음
    예전에 OpenSSL로 DuckDB 파일을 암호화하는 단순한 솔루션을 만들었는데, 첫 쿼리 시 2배의 실행 시간이 걸리고 메모리도 많이 사용했음
    반면 DuckDB는 페이지 단위 암호화와 CPU의 AES 가속을 활용해 읽기/쓰기 비용이 거의 없는 수준임

    • 왜 그냥 LUKS를 쓰지 않는지 궁금함
      커널 레벨에서 가속을 활용하고, 상위 애플리케이션에는 투명하게 동작함
      여러 앱이 각기 다른 ACL과 키를 써야 하는 경우가 아니라면 DB 자체 암호화는 불필요함
    • 솔직히 말해 DuckDB의 작업이 “놀라운” 수준은 아니라고 생각함
      단순한 전체 파일 암호화 방식과 비교하면 당연히 좋아 보이지만, 이는 기본적인 수준의 구현
      우리 스스로도 이런 수준의 품질을 목표로 해야 함
    • 결국 파이프라이닝 덕분임
      저장소 입출력에 비하면 암호화 비용은 거의 무료에 가까움
  • MotherDuck 외에 다중 사용자용 클라우드 기반 DuckDB를 잘 운영하는 모델이 있는지 궁금함
    일반 DB처럼 여러 사용자가 동시에 접근하면서 DuckDB의 장점을 그대로 활용할 수 있는 구조를 찾고 있음

    • 순수 DuckDB만 쓴다면 Arrow Flight 서버를 앞단에 두거나 httpserver 확장을 사용할 수 있음
      .duckdb 파일을 어디에 저장하느냐(S3 vs EFS)에 따라 성능 차이가 큼
      하지만 DuckLake가 더 나은 멀티플레이어 옵션으로 보임
      우리는 DuckLake를 제품에 사용 중이며, 성능 저하를 줄이기 위해 분석용 테이블은 GCP Filestore 같은 빠른 스토리지에 저장함
      하나의 DuckLake 카탈로그 안에서도 여러 스토리지 방식을 혼합할 수 있어 유연함
    • 요즘 “Postgres 안의 DuckDB”라는 글을 자주 보는데, 아마 그게 원하는 형태일 것 같음
    • GizmoSQL도 참고할 만함
  • DuckDB는 지금까지 써본 AI 도구들보다 더 유용했음
    LLM을 좋아하지만, 실제 업무 효율에서는 DuckDB가 훨씬 큰 도움을 줌

  • 키의 인덱싱 처리 방식이 궁금함
    검색 시 키를 암호화한 상태로 찾는지, 아니면 블록마다 복호화를 수행하는지 알고 싶음

  • “SQLite 암호화 확장은 2000달러 유료 애드온”이라는 말이 있지만,
    SQLiteMultipleCiphers는 오래전부터 무료로 제공되고 있음
    또한 Turso Database는 기본적으로 암호화를 지원함

    • 실제로 Python이나 Go에서 이런 변형된 SQLite를 플러그인과 함께 빌드해 사용하는 방법이 궁금함
      언어별로 링크 과정이 까다로워 보임
    • SQLCipher도 있음
      2009년부터 개발되어 안정적으로 동작하는 솔루션임