🔏 ProofCam 봉인 서버 — 데모 대시보드

법정 증거급 음성 진위 제품. 무결성 본체 = 암호 봉인(해시+서명+시각+블록체인), 핑거프린트는 보조.

4
봉인된 항목
HTTPS
proofcam.deshow.co.kr
/docs (OpenAPI) /health

현재 봉인된 항목 저장소에서 실시간 — 새로고침하면 갱신

seal_id모드/버전번들타임스탬프원본지문
02de8d6f9c9f4a70…client-hybrid / vseal-manifest/0.22
23aeffc3cb2a4e29…client-hybrid / vseal-manifest/0.21
40701a9afffc4389…server-excerpt / vseal-manifest/0.2
↳ 발췌 ← 23aeffc3… [0–10000ms]
848bf5ca730c4e6b…client-hybrid / vseal-manifest/0.21

한 녹음 = 같은 seal_id로 번들·타임스탬프·원본·지문이 묶임. 원본/지문은 best-effort(없을 수 있음).

기능 맵 무엇을 / 어느 엔드포인트가 / 어디 구현

기능엔드포인트구현 위치상태
봉인 생성 (서버 모드)POST /sealapp/seal.py · sealcore.py · tsa.py✅ 완료
검증 (C1~C4 재현 + 키신원 C5 + 발췌 C6)POST /verifyapp/seal.py:verify_seal · cert.py (C5) · excerpt_service.py (C6)✅ 완료
단일구조 봉인 수신 (sealed WAV 1개)POST /seal/intakemain.py · containers · sealcore · original_store · fingerprint✅ 완료
시각 도장 (temporary→confirmed)POST /seal/{id}/timestampapp/seal.py · tsa.py✅ 완료
원본 아카이브 + 지문 색인 (backfill)POST /seal/{id}/originalapp/original_store.py · fingerprint.py✅ 완료
변형본/짜깁기 식별POST /identifyapp/identify.py · wire.py (AudioDfs)✅ 완료
세그먼트 대조 검증 (지각적)POST /verify/segmentapp/segcompare.py (numpy/scipy FFT)✅ 완료
출처 찾기 (일반 클립 → 어느 봉인 어디)POST /locateapp/locate.py (지문 + 세그먼트 대조)✅ 완료
발췌본 생성 (Merkle 출처 증명, C6)POST /seal/{id}/excerptmain.py · excerpt_service · merkle.py · seal.create_derived_seal✅ 완료
발췌본 역방향 조회 (원본→발췌들)GET /seal/{id}/excerptsseal.find_excerpts✅ 완료
봉인 파일 다운로드 (자기완결 WAV)GET /seal/{id}/downloadapp/original_store.py✅ 완료
디바이스 cert 발급 (§13.15 키 신원)POST /device/cert · GET /cert/rootapp/cert.py · signer.py (KMS root)✅ 완료
서버 키 custody (KMS Ed25519, HSM)(SEAL_SIGNING_BACKEND=kms)app/signer.py · seal.py · cert.py✅ 완료
S3 원본 아카이브 (라이브)(SEAL_ORIGINAL_BACKEND=s3)app/original_store.py:S3OriginalStore✅ 완료
번들 조회GET /seal/{id}app/main.py · sealstore.py✅ 완료
블록체인 앵커링 (OTS)(opt-in SEAL_OTS_ENABLED)app/anchor.py⚪ 구현됨·꺼짐
다중 TSA (K-of-N)(SEAL_TSAS 설정)app/tsa.py✅ 완료
실 WORM (MinIO/S3 Object Lock)(SEAL_STORE_BACKEND=minio)app/sealstore.py✅ 완료
감사 해시체인(SEAL_AUDIT_DIR)app/audit.py✅ 완료
키 회전·폐기·keyring 자체서명CLIapp/keyring*.py✅ 완료

유관 레포 / 코드베이스 제품을 이루는 곳

레포/모듈역할언어GitLab설명
sound-fingerprint🖥️ 봉인 서버 (이 repo)Python / FastAPIproofcam/sound-fingerprint권위 보관·시각 도장·지문 색인·검증 본체. 데모 https://proofcam.deshow.co.kr.
proofcam-android :seal📱 봉인 라이브러리 (순수 JVM)Kotlinproofcam/proofcam-androidcanonical/manifest/signer/WAV/번들/SealClient/SealVerifier. 서버와 같은 SPEC.
proofcam-android :app📱 봉인 dev 앱 (폰)Kotlin / Androidproofcam/proofcam-android녹음→봉인→업로드. AudioRecorder·MainActivity·SealUploader.
proofcam-android :verifier📱 검증 전용 앱Kotlin / Androidproofcam/proofcam-android서명키·네트워크 권한 없음 — 트러스트 분리. 오프라인 C1~C3.
audiodfs-linux🔊 핑거프린트 엔진 (리눅스 포팅)C++ 바이너리(git 아님, 로컬)서버가 shell out: extract/filtering_server/client. 모바일 포팅 안 함.
own_skills/ · benchmark/🔒 보조 자산(gitignore, 커밋 금지)AudioDfs 원본 소스(ETRI 매입) · 엔진 비교 산출물.
[📱 :app 폰 앱] ──녹음→Keystore키 서명(:seal)──HTTPS──▶ [🖥️ 서버 proofcam.deshow.co.kr]
      │  TEE Ed25519 + §13.15 cert                    │ intake→timestamp(KMS서명)→S3 원본
      │  로컬 저장(sealed WAV)                          ├─▶ [🔊 audiodfs-linux] 지문 추출/검색
      ▼                                               ▼
[📱 :verifier 앱] ◀──오프라인 검증(C1~C5)── /state/ (번들·원본→S3·지문·감사)

proofcam 관련은 위 3곳뿐. ~/IdeaProjects의 deshow*·exocobio*·its-* 등은 무관.

신뢰의 뿌리 대부분 실제 — Play Integrity만 prod 대기

항목지금되어야 할 것 / 비고상태
시각 증인 (TSA)✅ freeTSA RFC3161 (실연동, 라이브)(완료) 인증서 핀 검증 포함✅ 완료
블록체인 영구 증인✅ OpenTimestamps tentative (제출됨)upgrade 자동화 → Bitcoin block confirmed (~1h+)✅ 완료
전송 보안✅ HTTPS (proofcam.deshow.co.kr, Let's Encrypt·자동갱신)(완료) prod 도메인/인증서는 별도로 파면 됨✅ 완료
서명 키 custody✅ AWS KMS Ed25519 (HSM) — §13.15 root + 서버 봉인키(완료) 개인키가 HSM 밖으로 안 나옴. '오프라인 루트'는 prod 옵션✅ 완료
디바이스 키 신원 (C5)✅ cert 발급 라이브(KMS root) + 안드 Keystore Ed25519(작성)안드 빌드하면 봉인이 identity-bound (현 봉인=self-signed)✅ 완료
기기/앱 증명 (attestation)deferred (약한 모드)Play Integrity / App Attest — Google 프로젝트 필요, prod 단계🔴 dev 대체물

✅ 시각(TSA·OTS)·전송(HTTPS)·키 custody(KMS HSM)·디바이스 신원(§13.15)까지 실제로 동작. 남은 건 Play Integrity(기기 attestation) — Google 프로젝트가 필요해 prod 단계에. 봉인 자체는 self-signed(현)→안드 빌드 시 identity-bound.

범위 밖 (의도적으로 안 함)

다음 할 일

항목내용분류
장시간 녹음 스트리밍 (Inc-1~4)44.1kHz·3-4시간(1.27GB) — 녹음기 파일스트리밍(Inc-1 작성됨, 빌드대기)·봉인 파이프라인 스트림화·서버 인테이크 스트리밍·재개 청크 업로드+오프라인 큐(간헐 인터넷에도 안 잃음)🔴 안드+서버
디바이스 §13.15 빌드 검증Keystore Ed25519 영속키 + cert 발급/embed 작성됨(미빌드). 빌드해 봉인이 C5 identity-bound 뜨는지 확인. Keystore Ed25519 KeyGenSpec digest는 기기/KeyMint별 조정 가능성🟡 안드 빌드
검증기 시간 정밀도 표시/verify의 time 객체(신뢰상한 vs 자가신고 캡처 + 정밀도 tier)를 검증기 '언제'에 3층 표시 — 오해 방지🟡 안드
타임스탬프 파일 백필RFC3161 토큰을 WAV에 박아 C4까지 자기완결(서버 없이도 confirmed 유지, §13.14)안드+서버
OTS upgrade 자동화tentative→Bitcoin block confirmed 자동 업그레이드 스케줄러(~1h+)서버
서버 키 prod 강화 (옵션)오프라인 루트(KMS root는 평소 미사용) · CloudHSM · 키 회전·CRL🔵 prod
Play Integrity (외부)기기/앱 attestation 실호출 — Google Cloud 프로젝트 + Play Console 등록 + 실기기. prod/전용서버 이식 단계에⚫ 외부
운영 잡일filtering_server 핫리로드 · H4/H5(verify CLI·temporary 만료) · 데모 후 IAM 키 rotate운영/병행

저장 위치 현재 서버 설정 기준

데이터경로파일
번들 (WORM)/state/seal_store{id}.seal.json + .anchors.jsonl
원본 음성 (삭제가능)/state/originals{id}.wav
지문 색인/state/fpidx{id}.dfs
감사로그(꺼짐)YYYY-MM.jsonl

용어집 번들·TSA·attestation… 한곳에

봉인 (Seal)녹음을 '이 순간 이 내용 그대로'라고 잠그는 행위/결과. 해시+서명+시각도장을 한 묶음으로 만든 것.
번들 (Bundle)봉인의 증거 묶음(JSON). 매니페스트 + 서명 + 공개키가 들어있음. 오디오 자체는 없고 '해시'만. = store/{id}.seal.json
매니페스트 (Manifest)봉인 대상의 명세. 오디오 해시(payload_sha256)·포맷·기기·당사자 진술·캡처시각 등. 이걸 서명한다.
페이로드 (Payload)오디오의 '실제 소리' 부분. WAV의 fmt+data. 헤더 메타는 제외 — 재포장해도 안 변하는 본질.
해시 (Hash, SHA-256)데이터의 지문 같은 고정길이 값. 한 바이트만 바뀌어도 완전히 달라짐 → 변조 탐지.
서명 (Signature, Ed25519)개인키로 매니페스트에 도장. 공개키로 누구나 '이 키 주인이 서명했고 안 바뀜'을 검증. = 위조 불가 날인.
키 (Key pair)개인키(서명용, 비밀) + 공개키(검증용, 공개) 한 쌍. 서버키=AWS KMS(HSM 안, §13.15 root+봉인키), 디바이스키=Android Keystore Ed25519(TEE/StrongBox). 둘 다 개인키가 보안하드웨어 밖으로 안 나옴.
TSA (시각 인증기관)Time Stamping Authority. '이 해시가 이 시각 이전에 존재했다'를 서명해주는 독립 제3자. 표준=RFC3161.
RFC3161TSA 타임스탬프 토큰의 국제 표준 포맷. 봉인에 '신뢰된 시각 증인'을 붙이는 방법.
앵커 (Anchor)봉인 밖에 따로 붙는 시각/블록체인 증거. RFC3161 토큰이나 OTS 증명. = store/{id}.anchors.jsonl
OTS (OpenTimestamps)비트코인 블록체인에 해시를 박아 '영구 시각 증인'을 만드는 방식. TSA보다 더 분산·영구적.
attestation (기기 증명)'이 봉인이 진짜 안드로이드 기기·미변조 앱에서 나왔다'는 OS 차원 증명. Play Integrity / App Attest. 지금은 deferred(약한 모드).
nonce재사용·위조 막으려 매니페스트에서 뽑은 1회성 값(해시). attestation 토큰을 이 봉인에 묶는 데 씀(§13.4).
hybrid 봉인폰이 오프라인에서 먼저 서명(temporary) → 나중에 서버가 TSA 도장(confirmed). 완전 오프라인은 시각증인이 없어 불가.
seal_status봉인의 시각 확정 여부. temporary(시각증인 0) / confirmed(RFC3161 ≥1). 저장값 믿지 않고 증거 카운트로 도출.
verdict / C1~C6검증 검사. C1=이 오디오 맞나 · C2=매니페스트 일관 · C3=서명 유효 · C4=시각 증인 · C5=키 신원(§13.15 cert 체인이 root까지 결속=identity-bound, 없으면 self-signed) · C6=발췌 출처(Merkle). PASS / PASS-PENDING(시각만 빠짐) / FAIL.
발췌본 / C6 (Merkle)원본의 일부를 잘라 다시 봉인한 것(POST /seal/{id}/excerpt). 원본 봉인 시 PCM을 Merkle 커밋(container.merkle), 발췌본은 range proof를 들고 다님 → C6=이 발췌가 정말 원본 [t1,t2]임을 서버 신뢰 없이 증명. 10초 경계 스냅. 핑거프린트와 상보.
인라인 봉인 (Inline)번들을 별도 파일이 아니라 WAV의 'seal' 청크에 박는 것. 파일 하나가 곧 자기완결 증거. = sealed WAV.
WORMWrite Once Read Many. 한 번 쓰면 못 고침. 봉인 번들 저장 방식(0o444 / Object Lock) — 사후 조작 차단.
핑거프린트 (.dfs)오디오의 잡음에 강한 음향 지문(AudioDfs). 재인코딩 사본·짜깁기 매칭용 보조 자료. 봉인 본체 아님.
identify / splice변형본·짜깁기 식별. splice=이어붙인 경계 / gap=공백 이상. 확률적 보조 라벨(법정 본체는 verify).
keyring공개키 배포·회전·폐기 관리 아티팩트. key_id로 봉인↔검증 매칭. root key가 keyring 자체를 서명.
custody (보관 사슬)증거를 누가 언제부터 보관했나의 사슬. 원본을 중립 보관소에 두면 '녹음자≠보관자'로 신뢰↑.
payload_sha256매니페스트 안의 오디오 해시 필드. 검증 C1이 '제출된 오디오의 해시 == 이 값'인지 대조.