./research / verifiable-audit-layer

AI를 위한 검증 가능한 감사 계층.

모델 추론과 에이전트 실행을 위한 변조 감지형 감사 계층: 정규 직렬화, 도메인 분리 해싱, DSSE 서명, 실행별 Merkle DAG, 그리고 어떤 실행도 삭제되지 않았음을 증명하는 실행 간 Merkle Mountain Range. 모든 원시 요소는 실제 대안들과의 정면 벤치마크에서 선택했으며 원자료도 커밋했습니다. 이 노트가 곧 그 설계와 그 뒤의 실험입니다.

감사암호학벤치마크shipped

위협 모델

우리는 저장소를 장악하고 사후에 기록을 다시 쓸 수 있는 적을 가정합니다. 그것을 생산한 운영자 자신을 포함합니다. 목표는 봉인된 실행에 대한 어떤 편집도 감지 가능하고, 기록이 연 단위로 측정되는 보존 기간 동안 검증 가능하게 유지되며, 검증이 어떤 사적 입력도 노출하지 않는 것입니다. 두 속성을 처음부터 끝까지 구분합니다. 단일 실행의 *무결성(integrity)*과 실행 집합의 *완전성(completeness)*입니다. 실행별 영수증은 전자를 주고 후자에 대해서는 아무 말도 하지 않으므로, 둘은 따로 설계됩니다.

아래의 모든 선택은 같은 방식으로 이뤄졌습니다. 어떤 원시 요소가 최선이라고 주장하지 않습니다. 같은 기계에서 믿을 만한 대안들과 비교하고 원자료를 커밋하므로, 여기의 어떤 수치든 한 명령으로 재현됩니다. 시간은 워밍업을 버린 뒤 여러 실행 중 가장 빠른 값이며, 불안정한 측정이 감춰지지 않고 표시되도록 평균과 표준편차를 보존합니다. 수치는 CPython 3.14의 단일 AMD64 호스트에서 나왔고 절댓값이 아니라 비율로서 의미가 있습니다.

실험과 결과

각 이정표는 단일 측정이 아니라 실제 대안들과의 정면 시험이었습니다. 개요는 아래이며, 각각의 상세 결과는 이어지는 절에 있습니다.

이정표 비교 대상 결과
정규형 소박한 JSON, CBOR JCS, 바이트 동일, 약 3x 비용
해싱 SHA-256, BLAKE3, keccak-256 keccak 네이티브 17x, 같은 바이트
네이티브 코어 pip 백엔드 vs Rust 봉인 6x, 루트 바이트 동일
서명 ECDSA, BLS, ML-DSA Ed25519, 64 B, 결정적
포스트양자 ML-DSA 44 / 65 / 87 단계적, 검증 대등, 38x 크기
실행별 추적 8가지 위조 공격, 오버헤드 전부 포착, 약 121 us / 이벤트
실행 간 로그 소박한 Merkle 재구축 MMR, 평탄한 추가, 483x

정규 직렬화

캡슐은 우리의 Python 코어, TypeScript 클라이언트, 그리고 감사자의 자체 도구에서 같은 바이트로 해싱되어야 하며, 그러지 않으면 유효한 기록이 검증에 실패합니다. 우리는 RFC 8785(JSON Canonicalization Scheme)를 씁니다. 이는 숫자 서식, UTF-16 코드 단위에 따른 키 순서, 비유한 값의 거부를 고정합니다. 소박하게 키를 정렬한 JSON, 그리고 CBOR와 비교해 시험했습니다.

접근 Python vs Node 비용
소박한 정렬 JSON 유니코드와 숫자에서 갈림 기준선
RFC 8785 JCS 바이트 동일 직렬화 시 약 3x
CBOR 이진, 읽으려면 디코더 필요 간결

소박한 JSON은 런타임 간에 유니코드 정렬과 숫자 서식에서 갈리며, 그래서 언어 간 검증을 조용히 깨뜨립니다. JCS는 둘 다에서 바이트 동일이며 직렬화 시간의 약 3x로, 해시당 한 번 지불되고 주변의 해싱과 네트워크 작업에 비하면 무시할 만합니다. 우리는 그 구현을 정확히 하나만 둡니다. 우리 네이티브 모듈이 자체 JSON 직렬화기를 가져왔을 때 그것을 제거했는데, 평범한 입력에서는 일치하고 적이 고를 수 있는 경계 사례에서 갈리는 두 번째 정규화기는 없느니만 못하기 때문입니다.

해싱과 네이티브 코어

잎은 BLAKE3로, Merkle 노드는 keccak-256으로 해싱하며, 둘 다 RFC 6962 도메인 분리(잎과 내부 노드에 서로 다른 접두사)를 써서, 내부 노드를 잎으로 제시하는 제2 원상 부류를 막습니다. keccak-256은 SHA3-256이 아닙니다. 둘은 치환을 공유하지만 패딩 바이트 하나에서 다르고, 온체인 검증자는 keccak을 말하므로, 조용한 치환은 모든 루트를 온체인에서 실패하게 만듭니다. 따라서 해싱 계층은 요청된 알고리즘을 계산하거나 오류를 던지며, 결코 닮은꼴을 내지 않고, 각 캡슐에 알고리즘을 기록하여 검증자가 로컬에 설치된 것에서 추론하는 대신 정확한 함수를 재현하게 합니다.

원시 요소, 64 B 입력 처리량 비고
SHA-256 (stdlib) 1.50M ops/s 기준선, 항상 존재
BLAKE3 (pip) 1.44M ops/s SHA-256과 대등
keccak-256 (pip) 99k ops/s 15x 느림, 병목
keccak-256 (Rust 코어) 1.69M ops/s pip보다 17x 빠름

keccak은 표준 라이브러리 구현이 없고, 그것이 네이티브 모듈을 지을 가치가 있게 했습니다. 격차는 이벤트 크기의 입력에서 가장 큰데, 거기서 pycryptodome의 비용이 해싱이 아니라 호출당 객체 할당이기 때문이며, 바로 감사 추적이 가장 많이 해싱하는 크기입니다. 처음부터 끝까지, 네이티브 코어는 1000 이벤트 실행의 봉인을 초당 78에서 491 봉인으로, 약 6x 끌어올립니다. 결정적으로, 가속기를 켜는 것이 결과를 바꿀 수는 없습니다. 같은 실행을 이 crate 유무로 봉인하면 비트 동일한 루트가 나오고, 적합성 스위트가 알고리즘 저자가 공표한 벡터에 대해 두 경로를 검사하며, CI는 안정 ABI(abi3) 휠 하나를 빌드하고 그 단일 산물을 3.10부터 3.14까지 모든 Python에서 검증합니다. 설치는 속도를 바꿀 뿐 그 밖에는 아무것도 바꾸지 않습니다.

십 년 가는 기록을 위한 서명

감사 기록의 서명은 기록이 다툴 수 있는 한 오래 버텨야 하며, AI 로깅 의무는 이제 십 년을 향해 갑니다. 기록이 아직 보존 창 안에 있을 때 방식이 깨지면, 적은 그것을 위조하고 날짜를 소급할 수 있어 아카이브 전체가 한꺼번에 무너집니다. 우리는 Ed25519를 ECDSA, BLS, NIST 포스트양자 계열 ML-DSA와 처리량과 크기에서 벤치마크했습니다.

방식 검증 (ops/s) 서명 크기
ECDSA P-256 16,887 ~72 B
ML-DSA-44 (포스트양자) 10,725 2,420 B
Ed25519 10,375 64 B
BLS12-381 참조 구현만 96 B, 집계

두 결과가 우리가 지녀 온 가정을 뒤집었고, 둘 다 기록에 남깁니다. Ed25519는 검증이 가장 빠르지 않습니다. ECDSA P-256이 최적화된 라이브러리 어셈블리에서 약 1.6x 빠르게 측정됐습니다. Ed25519가 기본으로 남는 것은 서명 크기와 결정성(RFC 8032) 덕분이며, 이는 서명이 아직 검증되는 동안 개인 키를 새게 하는 ECDSA nonce 재사용 고장을 없앱니다. 그리고 포스트양자 서명은 검증이 느리지 않습니다. ML-DSA-44가 Ed25519를 근소하게 앞섰고, 그 비용은 서명(약 13x 느림)과 크기(약 38x 바이트)에 있습니다. 추적은 한 번 서명되고 여러 해 검증되므로, 비싼 쪽이 곧 우리가 가장 적게 하는 쪽입니다. BLS는 숫자가 아니라 요구 사항으로 기각됐습니다. 집계는 많은 서명을 96 바이트로 접지만, 집계본은 전부-아니면-전무로 검증되고 모든 키와 메시지를 필요로 하며, 이는 한 결정의 한 가지를 나머지를 드러내지 않고 공개하는 것과 양립하지 않습니다.

중요한 재구성. 서명은 기밀이 아니므로 "지금 수확하고 나중에 복호"는 적용되지 않고, 진짜 위협은 보존 창 안의 소급 위조입니다. 루트를 공개 원장에 앵커링하면 기록이 언제 존재했는지를 서명 방식과 무관하게 증명하므로, 깨진 키는 기록을 누가 봉인했는지 증명할 능력을 앗아가지만 언제나 무엇을은 앗지 않습니다. 따라서 앵커링은 임계 경로에 있고 ML-DSA는 그 뒤에 단계적으로 놓이며, DSSE 봉투는 알고리즘 민첩하게 유지하고 알고리즘은 캡슐마다 기록합니다.

실행별 감사 추적

각 실행은 추가 전용이고 해시 사슬로 이어진 이벤트 열(LLM 호출, 도구 호출, 검색, 하위 에이전트 생성, 사람의 승인, 가드레일 결정)이며, 그 전체에 대한 Merkle 루트와 루트에 대한 DSSE 서명을 가집니다. 입력과 출력의 해시만 저장하고 페이로드는 결코 저장하지 않으므로, 추적은 기본적으로 프라이버시를 보존합니다. 검증자는 단지 유효인지 무효인지를 돌려주지 않고, 깨진 보장을 지목합니다.

연산 (102 이벤트 실행) 비용 스케일링
이벤트 하나 기록 ~121 us 평탄, 한 스텝의 0.01% 미만
봉인, 루트 구축 0.15 ms 이벤트에 선형
검증, 모든 잎 재계산 9.2 ms 선형, 봉인의 약 60x

기록은 모델 왕복이 지배하는 전형적 에이전트 스텝의 백분의 일 퍼센트 미만이므로, 오버헤드는 표본을 뜰 이유가 아니고 추적은 통계적이지 않고 완전하게 유지됩니다. 검증은 봉인보다 훨씬 무거운데, 봉인이 이미 있는 해시 위에 트리만 세우는 반면 검증은 각 잎을 내용에서 재계산하기 때문입니다. 그 비대칭은 감사 추적에 옳으며, 기록은 일정하고 검증은 드물고, 대량 재검증을 네이티브 코어와 병렬성이 다음으로 값하는 지점으로 표시합니다. 보장을 구체화하려고, 한 데모가 봉인된 실행을 여덟 가지로 공격하고 각각을 구체적 이유로 거부합니다.

공격 거부 사유
모델 출력을 다시 쓰기 잎 해시 불일치
이벤트를 삭제하거나 삽입 이벤트 수 불일치
이벤트 순서 바꾸기 사슬 끊김
실행을 자르기 사슬 머리 불일치
해시 알고리즘 강등 잎 해시 불일치
잘못된 키로 제시 서명이 검증되지 않음

실행 간 투명성 로그

유효한 실행별 캡슐은 실행 집합이 완전함을 증명하지 못합니다. 불편한 실행을 버리는 운영자는 개별적으로 완벽한 캡슐의 모음과 구멍 난 역사를 쥡니다. 우리는 이것을, 포함 증명(어떤 실행이 로그에 있음)과 일관성 증명(이전 크기의 로그가 지금 로그의 정확한 접두)을 지원하는 단일 추가 전용 캡슐 루트 로그로 막습니다. 일관성은 검열을 잡습니다. 어떤 실행을 지워 재구축한 로그는 내부적으로 형식이 옳고 살아남은 각 캡슐도 여전히 검증되지만, 앞서 공표된 루트에 대한 일관성 검사에 실패하고, 같은 검사가 날짜를 소급한 삽입을 거부합니다. 이는 변조 전에 커밋된 루트에 대해서만 작동하므로, 그 루트는 운영자가 수정할 수 없는 어딘가, 이를테면 공개 앵커에 있어야 합니다.

우리는 소박한 Merkle 트리가 아니라 Merkle Mountain Range를 씁니다. 추가는 노드를 더할 뿐 결코 하나도 다시 쓰지 않으므로, 로그가 일회 기록 또는 객체 스토리지에 살 수 있게 하고 로그가 자라도 옛 포함 증명을 유효하게 지키기 때문입니다. 그 속성은 단지 편리한 게 아니라 거의 최적입니다. ePrint 2025/234은 어떤 간결한 추가 전용 커밋먼트도 초선형 개수의 증인 갱신을 유발해야 함을 증명하며, 가까운 MMR 변종이 본질적으로 그 한계에 도달합니다.

로그 크기 MMR 구축 소박한 재구축
500 1.3 ms 158 ms (120x)
1,000 2.6 ms 618 ms (237x)
2,000 5.2 ms 2,491 ms (483x)

추가는 로그가 자라도 평탄하게 유지되고(100에서든 10,000 항목에서든 초당 약 390k 추가) 소박한 트리 재구축은 같은 범위에서 초당 8,176 루트에서 84 루트로 떨어집니다. 이차 대 준선형의 특징입니다. 스토리지는 항목당 2.00 저장 해시로 안정되고, 포함 증명은 100에서 100,000 항목 사이에 7에서 17 스텝으로만 자랍니다. 우리가 지는 곳. 우리의 일관성 증명은 O(log^2 n)이며, 달성 가능한 O(log n) 대신 옛 로그의 봉우리마다 한 경로를 나릅니다. 100,000 항목에서 몇 킬로바이트, 그리고 검토자가 읽어 검사할 수 있는 구성을 위한 의도된 맞바꿈입니다.

우리가 넘지 않는 한계

해싱은 변조 증거를 주지 변조 불가능성을 주지 않습니다. 실행을 재구축하고 그 루트를 재계산하는 적은 자기 일관적인 기록을 만듭니다. Merkle 루트는 이벤트가 루트와 맞음을 증명하지, 그 루트가 공표된 것임을 증명하지 않기 때문입니다. 서명이 그것을 잡고, 공개 앵커가 시각을 증명합니다. 투명성 로그는 크게 보아 같은 가정에 놓입니다. 삭제된 실행을, 삭제 전에 커밋된 루트에 대해서만 감지합니다. 우리는 이 경계를 제품과 그 데모에서 명시하고, 위조 데모가 우리가 멈추지 않는 공격을 계속 보여준다고 한 테스트가 단언하므로, 이 정직한 사례가 조용히 사라질 수 없습니다.

재현성

여기의 모든 수치는 한 명령으로 다시 도는 커밋된 벤치마크에서 나옵니다. 테스트들, 언어 간·구현 간 적합성 스위트, 그리고 네이티브 코어 유무로 Python 3.10에서 3.14까지 운동시키는 CI 매트릭스와 나란히. 방법론, 원 JSON, 결정 노트(각 선택이 지는 차원 포함)는 저장소에 있습니다. AI를 감사 가능하게 만드는 계층은 그 자신이 감사 가능해야 하기 때문입니다.