PhotoGram에 C2PA를 적용하는 설계를 처음 잡을 때는 이미지 처리 파이프라인의 문제로 생각했다.
Media Engine이 최종 이미지를 만들고, 그 결과물에 provenance를 붙이고, 서명한 뒤 외부로 내보내면 된다. 기술적으로만 보면 흐름은 꽤 자연스럽다.
그런데 creator attribution을 manifest에 넣는 순간 문제가 완전히 달라졌다.
사용자가 이미지를 업로드했다는 사실과 그 사용자가 이미지를 만들었다는 사실은 같지 않기 때문이다.
PhotoGram에 올라오는 콘텐츠를 몇 가지로만 나눠도 금방 드러난다.
- 직접 촬영한 사진
- 친구에게 허락받은 사진
- 라이선스를 받은 이미지
- 밈이나 재게시 콘텐츠
- public-domain 이미지
- 기존 creator provenance가 이미 있는 파일
이 모든 경우에 uploader 계정을 자동으로 creator라고 기록하고 플랫폼이 그 내용을 서명하면, provenance를 보호하는 시스템이 오히려 잘못된 attribution을 더 강하게 만들어버릴 수 있다.
그래서 C2PA를 붙이는 작업은 암호화 기능 하나를 추가하는 것으로 끝나지 않았다. PhotoGram이 무엇을 증명할 수 있고, 무엇은 사용자의 주장으로 남겨야 하는지부터 다시 정해야 했다.
PhotoGram이 실제로 증명할 수 있는 것
플랫폼이 확실하게 알고 있는 사실은 제한적이다.
PhotoGram은 어떤 계정이 asset을 제출했다는 것을 안다. Media Engine이 어떤 처리를 했는지도 알고, 어떤 publication rendition을 만들었는지도 안다. 마지막으로 어떤 metadata와 declaration 상태로 publication을 발행했는지도 기록할 수 있다.
이 범위는 플랫폼이 직접 관찰한 사실이다.
반면 다음은 같은 종류의 사실이 아니다.
- uploader가 실제 촬영자인가
- uploader가 법적 저작권자인가
- 제3자 이미지에 대한 라이선스가 유효한가
- 기존 provenance보다 새로운 creator claim이 더 신뢰할 수 있는가
이걸 platform signature 하나로 모두 확정할 수는 없다.
그래서 PhotoGram의 C2PA signer가 말하는 범위를 publication 쪽으로 제한했다.
이 asset은 PhotoGram을 통해 제출되었고, PhotoGram이 이 publication rendition을 만들었으며, 기록된 metadata/declaration 상태로 발행했다.
여기에 “이 uploader가 법적 저작권자다”라는 문장은 자동으로 들어가지 않는다.
이 구분을 하고 나니 C2PA와 rights declaration을 같은 설정으로 다루면 안 된다는 것도 명확해졌다.
C2PA는 게시 인프라고, 저작권 주장은 사용자 선택이다
PhotoGram에서 C2PA는 최종 publication asset의 provenance와 integrity를 위한 기반이다.
사용자가 매번 켜고 끄는 저작권 옵션으로 취급하지 않는다.
반면 creator/copyright declaration은 사용자가 자신의 게시물에 대해 어떤 권리 정보를 주장할지에 대한 product policy다.
둘은 같은 화면에 등장할 수 있어도 authority가 다르다.
이 때문에 일반 사용자에게 C2PA ON/OFF 토글을 제공하는 방향은 선택하지 않았다. publication integrity는 시스템이 일관되게 보장해야 하고, 사용자 preference는 그 안에 어떤 creator/right claim을 포함할지 결정하는 쪽으로 제한했다.
기본 게시도 복잡하게 만들고 싶지 않았다.
모든 사용자에게 매번 “당신이 저작권자인가?”, “라이선스가 있는가?”, “creator를 어떻게 표시할 것인가?”를 물으면 평범한 사진 게시 UX가 권리 설문지로 변한다.
그래서 system default는 GENERAL로 잡았다.
GENERAL에서는 uploader identity가 publication provenance에 남을 수 있지만, creator ownership이나 copyright ownership을 자동으로 주장하지 않는다.
평범한 사용자는 기존과 거의 같은 흐름으로 게시할 수 있다.
select media
→ edit
→ publish
publication integrity는 인프라에서 적용되고, 권리 주장은 별도 선택으로 남는다.
사진가처럼 자기 작업물을 자주 올리는 사용자는 어떻게 하나
반대쪽 사용자도 있다.
자기 사진이나 창작물을 거의 항상 올리는 사람에게 매번 같은 권리 설정을 반복시키는 것도 불필요하다.
그래서 account-level preference를 세 가지 정도의 단순한 모델로 정리했다.
GENERAL
OWN_WORK
ASK_EACH_TIME
OWN_WORK는 편의 기본값이다. creator attribution이나 copyright metadata를 기본 적용할 수 있다.
하지만 이름 그대로 “기본값”이지 법적 검증 결과는 아니다.
평소 자신의 사진을 올리는 creator account도 어느 날 밈이나 타인의 사진을 올릴 수 있다. 그래서 per-upload override가 account default보다 우선한다.
per-upload choice
↓
account default
↓
system default
이 순서가 필요한 이유는 creator profile과 실제 개별 asset의 authorship이 같은 정보가 아니기 때문이다.
계정이 누구인지 아는 것과 이 파일의 저작자가 누구인지 아는 것은 별개의 문제다.
기존 provenance가 있는 파일이 더 어려웠다
업로드된 파일 자체에 이미 trusted C2PA provenance가 있다면 상황은 더 조심스러워진다.
PhotoGram이 새로운 publication을 만든다는 이유로 기존 chain을 지워버리면 안 된다.
가능한 경우 기존 asset을 ingredient 또는 parent 관계로 남기고, 그 위에 PhotoGram publication provenance를 추가하는 방향을 잡았다.
Original asset
└─ existing provenance / creator information
↓
PhotoGram processing
↓
PhotoGram publication
├─ prior provenance relationship
├─ submitted-by account
├─ processing history
└─ publication signature
여기서 특히 피해야 하는 상황은 기존 provenance와 새 uploader claim이 충돌하는 경우다.
예를 들어 기존 provenance에는 creator가 Alice라고 되어 있는데 uploader가 자신을 creator Bob이라고 주장할 수 있다.
이때 PhotoGram이 새 claim을 “verified creator”로 승격하면 provenance chain을 보존한 의미가 사라진다.
R1에서는 충돌을 자동 해결하려 하지 않았다.
기존 provenance를 덮어쓰지 않고, submission과 authorship을 구분하며, 충돌한 claim을 검증된 ownership처럼 표시하지 않는 데까지만 경계를 고정했다.
게시 차단이나 dispute flow는 별도의 product/policy 문제로 남겼다.
이 정책 때문에 이미지 파이프라인의 순서도 고정됐다
권리 모델과 별개로 publication integrity 자체에는 byte-level invariant가 필요하다.
Media Engine은 resize, format conversion, quality processing, EXIF/privacy sanitization 같은 작업을 끝낸 뒤 최종 derivative를 만든다.
C2PA signing은 그 다음이다.
Private Original
↓
Media Engine
↓
Final Publication Derivative
↓
C2PA Sign
↓
Verify
↓
Immutable Publication Asset
서명한 뒤 다시 resize하거나 recompression하면 이전 서명의 의미가 깨진다.
그래서 서명 이후 변경이 필요하면 기존 asset을 수정하지 않고 새 publication version을 만든다.
이건 rights preference가 바뀌는 경우에도 같다. creator attribution이 변경되어 publication metadata가 달라져야 한다면 이미 서명된 bytes를 고치는 대신 새 derivative/manifest를 만들어 다시 서명한다.
이렇게 해야 “현재 publication이 무엇인지”를 asset version으로 설명할 수 있다.
서명 성공과 게시 성공도 같은 상태가 아니다
signing API가 성공했다고 바로 정상 publication으로 간주하지 않는다.
서명 직후 full verification을 한 번 더 수행하고, 검증을 통과한 asset만 정상 publication state로 전환하도록 했다.
이후 모든 HTTP 요청에서 C2PA 전체 cryptographic verification을 다시 실행하는 것은 R1 fast path로 요구하지 않았다.
publication 시점에는 강하게 검증하고, delivery에서는 immutable object identity, content hash, verification state, revocation state 같은 저장된 publication 상태를 확인한다.
asset identity mismatch나 storage migration, integrity audit 같은 이유가 있을 때 full verification을 다시 수행할 수 있다.
이 구분은 비용 때문이기도 하지만 상태 모델을 명확하게 만들기 위해서이기도 하다.
“과거에 한 번 서명했다”가 아니라 “현재 제공하려는 object가 검증된 publication version과 같은가”를 확인하는 쪽이 delivery contract에 더 가깝다.
Spring Security가 이 문제까지 소유하지는 않는다
처음에는 외부 delivery 전에 확인하는 일이니 기존 Spring Security에 붙이면 될 것처럼 보일 수 있다.
하지만 질문이 다르다.
Security가 답하는 것은 이 사용자가 이 asset을 볼 수 있는가다.
Publication Integrity Guard가 답하는 것은 이 asset을 PhotoGram의 정상 publication으로 제공해도 되는가다.
둘 중 하나만 통과해도 충분하지 않다.
유효한 C2PA signature를 가진 asset이라도 post가 삭제되었거나 visibility가 철회되었다면 보내면 안 된다. 반대로 접근 권한이 있는 사용자라도 storage의 asset이 현재 verified publication과 다르다면 정상 이미지처럼 응답하면 안 된다.
그래서 delivery 순서를 다음처럼 두었다.
Authorization
↓
Publication Integrity
↓
Delivery
두 검사를 연속으로 실행하되 하나의 authority로 합치지는 않았다.
privacy가 provenance보다 먼저 온다
provenance를 많이 남긴다고 좋은 것도 아니다.
원본 사진에는 exact GPS, device information, private account information처럼 공개하면 안 되는 metadata가 있을 수 있다.
그래서 raw metadata를 manifest에 그대로 복사하지 않는다.
먼저 Media Engine에서 privacy sanitization을 하고, public allowlist에 들어간 정보만 attribution과 provenance에 사용한다.
특히 exact GPS나 내부 storage path, private identifier 같은 정보는 publication provenance의 재료가 아니다.
이 순서는 중요한 정책이었다.
provenance가 “원본에 있던 모든 것을 영구 보존하는 계층”이 되어버리면 사용자가 공개하지 않기로 한 정보를 다른 경로로 다시 노출할 수 있기 때문이다.
C2PA를 붙이는 것보다 어려웠던 건 서명의 의미를 제한하는 일이었다
이 작업에서 가장 오래 남은 질문은 기술 스택이 아니었다.
“누가 signer인가?”, “어느 SDK를 쓸 것인가?”보다 더 중요한 것은 PhotoGram의 signature가 어디까지 주장할 수 있는지였다.
R1에서 platform signer는 PhotoGram이다.
하지만 그 signature가 인간 creator의 법적 identity를 검증했다고 말하지는 않는다. 그런 수준의 identity assertion이 필요하면 별도 capability를 검토해야 한다.
마찬가지로 DRM, screenshot prevention, 자동 저작권 분쟁 해결도 이 설계의 범위가 아니다.
C2PA를 넣는다고 서비스가 갑자기 저작권 판정 기관이 되는 것은 아니다.
오히려 반대로, provenance를 신뢰할 수 있게 만들려면 플랫폼이 자기가 직접 아는 사실과 사용자가 주장한 사실을 끝까지 구분해야 한다고 봤다.
PhotoGram에서 “Uploader는 Creator가 아니다”라는 문장은 그래서 단순한 데이터 모델 규칙이 아니다.
publication integrity와 사용자 권리 주장을 한 시스템 안에서 같이 다루되, 둘의 의미를 섞지 않기 위한 제품 경계다.