ปัจจุบัน Claude แนบเมตาดาต้า C2PA provenance ที่ลงนามแล้วกับไฟล์ที่สร้างขึ้น โมเดลภาพของ OpenAI ก็ทำเช่นกัน และ Gemini ก็เช่นกัน ซึ่งหมายความว่าสัญญาณ provenance ที่แท้จริงกำลังมาถึง endpoint การอัปโหลดของคุณเป็นครั้งแรก และมีโอกาสสูงที่ pipeline ของคุณจะลบมันออกไปก่อนที่ใครจะเห็น
ไม่ได้มีเจตนาร้าย แต่เป็นค่าเริ่มต้น sharp().resize() จะสร้างไฟล์ที่สะอาดที่ไม่มีเมตาดาต้า เว้นแต่คุณจะระบุเป็นอย่างอื่น ImageMagick ก็เช่นกัน Pillow ก็เช่นกัน CDN รูปภาพส่วนใหญ่ก็เช่นกัน Manifest ถูกส่งเข้าไป แต่ JPEG ที่เล็กลงกลับออกมา โดยที่ไม่มีอะไรในบันทึกของคุณกล่าวถึงมันเลย
นี่คือความล้มเหลวที่ทดสอบได้ และการทดสอบก็ไม่ซับซ้อน นี่คือวิธีการที่เมตาดาต้าหายไปใน pipeline ปกติ วิธีพิสูจน์ว่ามันเกิดขึ้น และวิธีผูกการตรวจสอบแบบ round-trip เข้ากับ CI เพื่อป้องกันไม่ให้ปัญหากลับมาอีก Apidog จัดการการจัดการ; c2patool จัดการการตรวจสอบระดับไบต์
อะไรที่ถูกทำลายไปจริงๆ
Manifest ของ C2PA คือบล็อกที่ลงนามด้วยการเข้ารหัสที่ฝังอยู่ในคอนเทนเนอร์ไฟล์ มันบันทึกว่าใครเป็นผู้ลงนามในสินทรัพย์และมีการอ้างสิทธิ์อะไรเกี่ยวกับสินทรัพย์นั้น และเนื่องจากมีการลงนาม การเปลี่ยนแปลงไบต์โดยไม่มีการลงนามใหม่จะทำให้ลายเซ็นเสียหายในลักษณะที่ผู้อ่านทุกคนสามารถตรวจจับได้
ระดับคอนเทนเนอร์คือวลีสำคัญ เขียนคอนเทนเนอร์ใหม่และ manifest ก็จะหายไป
| การดำเนินการ | Manifest ยังคงอยู่โดยค่าเริ่มต้นหรือไม่? |
|---|---|
| คัดลอกหรือย้ายแบบไบต์ต่อไบต์ | ใช่ |
sharp().resize().toBuffer() |
ไม่ |
ImageMagick convert / magick |
ไม่ |
Pillow Image.save() |
ไม่ |
| PNG เป็น WebP, JPEG เป็น AVIF | ไม่ |
| การปรับแต่งอัตโนมัติของ Image CDN | โดยปกติไม่ |
| ภาพหน้าจอ (Screenshot) | ไม่ |
| บันทึกซ้ำจากโปรแกรมแก้ไขรูปภาพ | ไม่ |
| การอัปโหลด S3 โดยไม่มีการแปลง | ใช่ |
ทุกอย่างในคอลัมน์ "ไม่" คือสิ่งที่แอปพลิเคชันเว็บปกติทำกับรูปภาพทุกรูปที่รับเข้ามา ไม่ว่าจะเป็นรูปภาพขนาดเล็ก (thumbnails), รูปภาพที่ปรับตามการแสดงผล (responsive variants), การต่อรองรูปแบบ (format negotiation), การล้างข้อมูล EXIF เพื่อความเป็นส่วนตัว แต่ละอย่างมีความสมเหตุสมผลเมื่อพิจารณาแยกกัน และแต่ละอย่างก็ยุติห่วงโซ่ provenance ลงอย่างเงียบๆ
สิ่งที่น่าสังเกต: การใช้ -strip ด้วยเหตุผลด้านความเป็นส่วนตัวมักจะทำโดยเจตนา เพราะ EXIF มีพิกัด GPS และหมายเลขซีเรียลของกล้อง การลบเมตาดาต้าทั้งหมดเพื่อลบข้อมูลตำแหน่งยังเป็นการลบ provenance manifest ออกไปด้วย เป้าหมายทั้งสองนี้ขัดแย้งกัน และการแก้ไขปัญหานี้หมายถึงการเลือกทำบางส่วนมากกว่าการลบทั้งบล็อกทิ้ง
พิสูจน์ได้ในสองนาที
ก่อนที่จะสร้างอะไร ให้ยืนยันว่าคุณมีปัญหาอยู่จริง คุณต้องมีไฟล์หนึ่งไฟล์ที่มี manifest ที่ถูกต้อง รูปภาพใดๆ ที่ Claude สร้างขึ้นก็ใช้ได้ หรือหยิบตัวอย่างที่ลงนามแล้วจาก Content Authenticity Initiative
ติดตั้ง CLI อ้างอิง:
cargo install c2patool
ตรวจสอบว่า fixture ถูกลงนามจริงหรือไม่:
c2patool fixtures/signed-sample.png
คุณควรได้รับรายงาน JSON ที่ระบุถึงผู้สร้างคำกล่าวอ้างและสถานะลายเซ็น ตอนนี้ส่งผ่าน stack ของคุณเองและตรวจสอบที่ปลายอีกด้าน:
# Upload through your real endpoint
curl -sS -X POST https://api.example.com/v1/assets \
-H "Authorization: Bearer $API_TOKEN" \
-F "file=@fixtures/signed-sample.png" \
-o /tmp/upload.json
# Fetch it back through the URL your frontend would use
ASSET_URL=$(jq -r '.url' /tmp/upload.json)
curl -sS "$ASSET_URL" -o /tmp/roundtrip.png
# Did the manifest survive?
c2patool /tmp/roundtrip.png
ผลลัพธ์ที่เป็นไปได้สามอย่าง ซึ่งมีความหมายแตกต่างกัน:
- รายงานที่ถูกต้อง Manifest ยังคงอยู่ ดีมาก
- ไม่พบ Manifest บางสิ่งใน pipeline ของคุณลบออกไป นี่เป็นกรณีที่พบบ่อย
- ข้อผิดพลาดในการตรวจสอบ มี Manifest อยู่ แต่ลายเซ็นไม่ตรงกับไบต์อีกต่อไป มีบางอย่างแก้ไขไฟล์และทิ้ง Manifest เก่าไว้ ซึ่งแย่กว่าการลบออก เพราะมันดูเหมือนการเปลี่ยนแปลงโดยไม่ได้รับอนุญาตสำหรับผู้ตรวจสอบปลายทาง
ผลลัพธ์ที่สามนี้คือสิ่งที่คุณต้องตามหา โดยปกติหมายความว่าไลบรารีการแปลงรักษากลุ่มเมตาดาต้าไว้ในขณะที่เขียนพิกเซลใหม่
ค้นหาขั้นตอนที่เป็นต้นเหตุ
หากการตรวจสอบแบบ round trip ล้มเหลว ให้แบ่งครึ่ง pipeline ตรวจสอบ manifest ทันทีหลังจากแต่ละขั้นตอน แทนที่จะคาดเดา
ผู้ต้องสงสัยทั่วไปตามลำดับความน่าจะเป็น:
1. ขั้นตอนการปรับขนาดหรือสร้างภาพขนาดย่อ (thumbnail) เป็นผู้ร้ายที่น่าจะเป็นไปได้มากที่สุด ใน sharp เมตาดาต้าจะถูกลบออก เว้นแต่คุณจะเก็บมันไว้อย่างชัดเจน:
// Drops the C2PA manifest
await sharp(input).resize(1200).toFile(output);
// Preserves the metadata block
await sharp(input).resize(1200).keepMetadata().toFile(output);
การเก็บบล็อกไว้เป็นสิ่งจำเป็นแต่ไม่เพียงพอ พิกเซลมีการเปลี่ยนแปลง ดังนั้นลายเซ็นเดิมจึงไม่สามารถยืนยันกับไบต์ใหม่ได้อีกต่อไป หากต้องการรักษาห่วงโซ่ provenance ที่ใช้งานได้ คุณจะต้องลงนามผลลัพธ์ใหม่และบันทึกการแปลงเป็นข้อความยืนยันการดำเนินการ โดยทั่วไปคือ c2pa.resized ไลบรารี c2pa สำหรับ Rust, Python, JavaScript และ C ล้วนรองรับสิ่งนี้
2. การแปลงรูปแบบ การให้บริการ AVIF หรือ WebP หมายถึงคอนเทนเนอร์ใหม่ กฎเดียวกัน: เก็บและลงนามใหม่ หรือยอมรับว่าห่วงโซ่จะสิ้นสุดลงที่นั่นและแจ้งให้ทราบ
3. CDN CDN รูปภาพจำนวนมากเขียนซ้ำเมื่อมีการส่งมอบ บางแห่งในปัจจุบันเก็บและลงนาม Content Credentials ได้โดยตรง; ส่วนใหญ่ในอดีตลบออกไป ทดสอบผ่าน URL การส่งมอบที่ผู้ใช้ของคุณเข้าถึงจริง ไม่ใช่ผ่านต้นทาง มิฉะนั้นคุณจะได้ผลลัพธ์สีเขียวที่ไม่มีความหมาย
4. การทำให้การอัปโหลดเป็นมาตรฐาน (Upload normalization) บริการที่เข้ารหัสซ้ำเมื่อรับเข้าเพื่อทำให้รูปแบบเป็นมาตรฐานนั้นง่ายต่อการลืม เพราะโค้ดอยู่ใน repo โครงสร้างพื้นฐานที่ไม่มีใครอ่าน
ทำให้เป็นการทดสอบถาวร
การรัน curl เพียงครั้งเดียวพิสูจน์สถานะในวันนี้ แต่ไม่ได้หยุดใครจากการเพิ่มขั้นตอนการปรับขนาดใน sprint ถัดไป การตรวจสอบนี้ต้องอยู่ใน CI
แบ่งออกเป็นสองชั้น เพราะเครื่องมือสองชนิดมีความสามารถที่แตกต่างกัน
เลเยอร์แรก: การตรวจสอบแบบ round-trip ใน Apidog
การจัดการคือการทดสอบ API แบบต่อเนื่องปกติ: อัปโหลด fixture, บันทึก URL ที่ส่งคืน, ดึงสินทรัพย์กลับมาผ่านเส้นทางการส่งมอบจริง, ยืนยันผลลัพธ์ที่ได้กลับมา
ใน Apidog นี่คือสถานการณ์การทดสอบที่มีสองขั้นตอน
ขั้นตอนที่ 1: POST /v1/assets
- เนื้อหา (Body):
multipart/form-dataโดยแนบ fixture ที่ลงนามของคุณ กลไกเหมือนกับใน การทดสอบ API อัปโหลดไฟล์ - การยืนยัน (Assertions): สถานะคือ
201และการตอบกลับตรงกับ schema ของคุณ - สคริปต์หลังการตอบกลับเพื่อส่ง URL ไปยังขั้นตอนถัดไป:
const body = pm.response.json();
pm.environment.set("ASSET_URL", body.url);
pm.test("upload returns a delivery URL", function () {
pm.expect(body.url).to.be.a("string").and.to.include("https://");
});
ขั้นตอนที่ 2: GET {{ASSET_URL}}
- การยืนยัน (Assertions): สถานะคือ
200,Content-Typeเป็นรูปแบบที่คุณคาดหวัง และขนาดเนื้อหาใกล้เคียงกับสิ่งที่คุณอัปโหลด การลดลงของขนาดอย่างมากเป็นสัญญาณที่ชัดเจนว่าไฟล์ถูกเข้ารหัสใหม่
const uploadedBytes = Number(pm.environment.get("FIXTURE_BYTES"));
const returnedBytes = pm.response.responseSize;
pm.test("asset was not silently re-encoded", function () {
pm.expect(returnedBytes).to.be.above(uploadedBytes * 0.9);
});
ขนาดเป็นเพียงหลักการประมาณ ไม่ใช่ข้อพิสูจน์ มันช่วยตรวจจับความล้มเหลวที่ชัดเจนได้อย่างรวดเร็วและทำงานในชุดทดสอบเดียวกันกับส่วนอื่นๆ รูปแบบการยืนยันมาตรฐานมีอธิบายอยู่ใน API assertions
เลเยอร์สอง: การตรวจสอบระดับไบต์ใน CI
การตรวจสอบลายเซ็นหมายถึงการแยกวิเคราะห์คอนเทนเนอร์ ซึ่งเป็นหน้าที่ของ c2patool ไม่ใช่ของ HTTP client รันเป็นขั้นตอนใน pipeline กับไฟล์ที่ round trip ดึงมา:
# .github/workflows/provenance.yml
name: provenance
on: [pull_request]
jobs:
c2pa-round-trip:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install c2patool
run: cargo install c2patool
- name: Install Apidog CLI
run: npm install -g apidog-cli
- name: Run the round-trip scenario
run: |
apidog run --access-token "$APIDOG_ACCESS_TOKEN" \
-t "$SCENARIO_ID" -e "$ENV_ID" -r cli,html --out-dir ./apidog-reports
env:
APIDOG_ACCESS_TOKEN: ${{ secrets.APIDOG_ACCESS_TOKEN }}
SCENARIO_ID: ${{ vars.PROVENANCE_SCENARIO_ID }}
ENV_ID: ${{ vars.APIDOG_ENV_ID }}
- name: Verify the manifest survived
run: |
set -euo pipefail
curl -sS "$ASSET_URL" -o /tmp/roundtrip.png
c2patool /tmp/roundtrip.png > /tmp/report.json
jq -e '.validation_status == null or (.validation_status | length) == 0' /tmp/report.json
set -euo pipefail มีความสำคัญ หากไม่มีสิ่งนี้ c2patool ที่ล้มเหลวในการทำงานกับไฟล์ที่ถูกลบออกจะสร้างคำเตือนและ build ที่เป็นสีเขียว ซึ่งเป็นความล้มเหลวที่คุณพยายามป้องกันอย่างแม่นยำ หากคุณยังใหม่กับการรัน Apidog scenarios ใน pipeline, การทำให้การทดสอบ API เป็นอัตโนมัติใน GitHub Actions ครอบคลุมการตั้งค่า
เลเยอร์สาม, ทางเลือก: verification endpoint
หาก provenance เป็นคุณสมบัติของผลิตภัณฑ์มากกว่าการตรวจสอบภายใน การออกแบบที่สะอาดที่สุดคือ endpoint เล็กๆ ในบริการของคุณเองที่รันไลบรารี c2pa และส่งคืนผลลัพธ์ที่มีโครงสร้าง จากนั้นทั้งหมดจะสามารถทดสอบได้ในรูปแบบ JSON ทั่วไป และ frontend ของคุณจะได้รับคำตอบที่แท้จริงแทนที่จะเป็นการคาดเดา
{
"asset_id": "img_9f2c41",
"provenance": {
"status": "verified",
"standard": "c2pa",
"signer": "Anthropic",
"signature_valid": true,
"checked_at": "2026-08-11T09:14:22Z",
"tool": "c2patool/0.9"
}
}
เก็บสามสถานะ ไม่ใช่สอง verified (ตรวจสอบแล้ว), absent (ไม่มี), และ invalid (ไม่ถูกต้อง) มีความหมายแตกต่างกันอย่างแท้จริง และการรวม absent และ invalid เป็นค่าบูลีนเดียวจะทิ้งสัญญาณที่น่าสนใจที่สุดที่คุณมี เพิ่ม unchecked (ไม่ได้ตรวจสอบ) หากตัวตรวจสอบของคุณไม่พร้อมใช้งาน เพื่อไม่ให้การหยุดทำงานปลอมแปลงเป็นผลลัพธ์ที่สะอาด
บันทึกโครงสร้างในคำจำกัดความ OpenAPI ของคุณและตรวจสอบความถูกต้องกับมัน เพื่อให้ฟิลด์ต่างๆ ไม่หายไปในการปรับโครงสร้าง วิธีการตรวจสอบ OpenAPI specs ครอบคลุมด้านนั้น
สี่ fixtures ที่ควรเก็บไว้
ชุดทดสอบ provenance ต้องการอินพุตที่เสียโดยเจตนา ไม่ใช่แค่เส้นทางปกติ (happy path) เท่านั้น
- ไฟล์ที่ลงนามถูกต้อง คาดหวัง
verifiedตรวจจับการลบออกที่มากเกินไป - ไฟล์ที่ถูกลบออก (stripped file) รูปภาพเดียวกัน แต่ manifest ถูกลบออกด้วย
exiftool -all=คาดหวังabsentไม่ใช่ข้อผิดพลาดและแน่นอนว่าไม่ใช่verified - ไฟล์ที่มีการแก้ไข (tampered file) ไฟล์ที่ลงนามแล้วโดยมีการเปลี่ยนแปลงไบต์หลังจากลงนาม คาดหวัง
invalidนี่คือสิ่งที่พิสูจน์ว่าคุณกำลังตรวจสอบลายเซ็นไม่ใช่แค่ตรวจสอบว่ามีบล็อกอยู่หรือไม่ - รูปแบบที่ไม่รองรับ รูปแบบที่ไม่มีการรองรับ manifest เลย คาดหวัง
absentที่สะอาดตาแทนที่จะเป็น 500
คอมมิตทั้งสี่ไฟล์นี้ไปยัง repo ถัดจากสถานการณ์การทดสอบ พวกมันมีขนาดเล็ก ไม่เคยเปลี่ยนแปลง และเป็นความแตกต่างระหว่างการทดสอบที่ผ่านกับการทดสอบที่มีความหมาย
ทำไมต้องสนใจ
สามเหตุผล โดยเรียงลำดับจากน้อยไปมากตามค่าใช้จ่ายที่คุณจะต้องเสีย
ข้ออ้างผลิตภัณฑ์ของคุณ หาก UI ของคุณแสดงป้าย provenance และ pipeline ของคุณลบ manifests ทิ้งไป ป้ายนั้นจะผิดสำหรับทุกสินทรัพย์ที่ผ่านการปรับขนาด นั่นคือปัญหาความน่าเชื่อถือที่คุณจะทราบจากผู้ใช้
เรื่องราวการปฏิบัติตามกฎระเบียบของคุณ หากคุณพึ่งพา C2PA สำหรับเรื่องที่เกี่ยวข้องกับมาตรา 50 ใดๆ manifest ที่ถูกลบออกคือการควบคุมที่ไม่ได้ผล การแยกหน้าที่ระหว่างผู้ให้บริการและผู้ใช้งานใน EU AI Act Article 50 สำหรับนักพัฒนา API อธิบายว่าหน้าที่ใดที่แท้จริงเป็นของคุณ
สัญญาณเอง Provenance จะทำงานได้ก็ต่อเมื่อห่วงโซ่ยังคงอยู่ตั้งแต่ต้นจนจบ ทุก pipeline ที่ลบ manifests ออกอย่างเงียบๆ จะทำให้ระบบนิเวศทั้งหมดมีประโยชน์น้อยลง รวมถึงสำหรับคุณเองเมื่อคุณเป็นคนพยายามตรวจสอบบางสิ่ง
ดาวน์โหลด Apidog เพื่อสร้างสถานการณ์ round-trip กับ endpoint ของคุณเอง จากนั้นเชื่อมต่อขั้นตอน c2patool เข้าไปต่อท้าย
คำถามที่พบบ่อย (FAQ)
การปรับขนาดรูปภาพจะลบเมตาดาต้า C2PA ออกไปหรือไม่? ใช่ โดยค่าเริ่มต้นในทุกไลบรารีทั่วไป การเก็บบล็อกเมตาดาต้าต้องใช้ธง (flag) ที่ระบุอย่างชัดเจน และการรักษาลายเซ็นที่ถูกต้องต้องมีการลงนามผลลัพธ์ที่ถูกแปลงใหม่
ฉันจะตรวจสอบได้อย่างไรว่าไฟล์มีเมตาดาต้า C2PA หรือไม่? รัน c2patool <file> จาก command line หรือลากไฟล์ไปวางที่ หน้าตรวจสอบ Content Credentials
ฉันสามารถเก็บเมตาดาต้า C2PA ไว้ได้หรือไม่เมื่อมีการปรับขนาด? ได้ แต่ไม่ใช่แค่การรักษาไว้เพียงอย่างเดียว ให้รักษาบล็อกไว้ จากนั้นลงนามผลลัพธ์ใหม่ด้วยการยืนยันการดำเนินการ เช่น c2pa.resized โดยใช้ไลบรารี c2pa ตัวใดตัวหนึ่ง มิฉะนั้นลายเซ็นเก่าจะไม่ตรงกับไบต์ใหม่
CDN ลบ Content Credentials ออกไปหรือไม่? หลายแห่งทำเมื่อมีการปรับแต่งอัตโนมัติ บางแห่งในปัจจุบันเก็บและลงนามใหม่ได้โดยตรง ทดสอบผ่าน URL การส่งมอบที่ผู้ใช้ของคุณเข้าถึง ไม่ใช่ผ่านต้นทาง
ความแตกต่างระหว่าง manifest ที่ถูกลบออก (stripped) กับ manifest ที่ไม่ถูกต้อง (invalid) คืออะไร? Stripped หมายถึงไม่พบ manifest ซึ่งไม่ได้บอกอะไรคุณเกี่ยวกับที่มาของไฟล์ Invalid หมายถึงมี manifest อยู่ แต่ลายเซ็นไม่ตรงกับไบต์ ซึ่งหมายความว่าไฟล์มีการเปลี่ยนแปลงหลังจากลงนาม ให้เก็บทั้งสองสถานะแยกกัน
Apidog สามารถตรวจสอบลายเซ็น C2PA ได้โดยตรงหรือไม่? Apidog จัดการการตรวจสอบแบบ round trip และยืนยันการตอบกลับ HTTP รวมถึง JSON ของ verification endpoint การแยกวิเคราะห์ลายเซ็นเองเป็นหน้าที่ของ c2patool ซึ่งรันเป็นขั้นตอน CI หรือภายในบริการของคุณเอง ใช้ทั้งสองอย่างร่วมกัน
ฉันควรลบ EXIF เพื่อความเป็นส่วนตัว แต่เก็บ C2PA ไว้หรือไม่? นั่นคือเป้าหมายที่ถูกต้องและต้องใช้วิธีการเลือกทำ การใช้ -strip แบบครอบคลุมจะลบทั้งสองอย่างออก ให้ลบบล็อก EXIF ที่คุณสนใจโดยเฉพาะและปล่อยให้ C2PA manifest ยังคงอยู่
บทสรุป
เมตาดาต้า Provenance มาถึง API ของคุณอย่างสมบูรณ์แต่โดยปกติจะถูกทำลายเป็นชิ้นๆ และไม่มีอะไรในการตรวจสอบของคุณที่จะแจ้งให้คุณทราบ วิธีแก้ไขคือการใช้ fixture, การตรวจสอบแบบ round trip ผ่านเส้นทางการส่งมอบจริง และการตรวจสอบด้วย c2patool ที่จะทำให้ build ล้มเหลว
ใช้เวลาตั้งค่าเพียงยี่สิบนาที และมันจะเปลี่ยนคำกล่าวอ้างที่คุณทำใน UI ของคุณให้เป็นการรับประกันที่ pipeline ของคุณบังคับใช้จริง
