ปัจจุบัน Claude แนบเมตาดาต้า C2PA provenance ที่ลงนามแล้วกับไฟล์ที่สร้างขึ้น โมเดลภาพของ OpenAI ก็ทำเช่นกัน และ Gemini ก็เช่นกัน ซึ่งหมายความว่าสัญญาณ provenance ที่แท้จริงกำลังมาถึง endpoint อัปโหลดของคุณเป็นครั้งแรก แต่มีโอกาสสูงที่ pipeline จะลบมันทิ้งก่อนถึงผู้ใช้
โดยปกติไม่ได้เกิดจากเจตนาร้าย แต่เกิดจากค่าเริ่มต้น เช่น sharp().resize() จะสร้างไฟล์ใหม่โดยไม่มีเมตาดาต้า เว้นแต่จะระบุให้เก็บไว้ เช่นเดียวกับ ImageMagick, Pillow และ Image CDN ส่วนใหญ่ ผลลัพธ์คือ manifest ถูกอัปโหลดเข้ามา แต่ไฟล์ JPEG ที่เล็กลงถูกส่งออกไปโดยไม่มี provenance และไม่มี log แจ้งเตือน
บทความนี้จะแสดงวิธีตรวจสอบว่าปัญหาเกิดขึ้นใน pipeline ของคุณหรือไม่ ระบุขั้นตอนที่ทำให้ manifest หาย และเพิ่มการตรวจสอบแบบ round-trip เข้า CI โดยใช้ Apidog สำหรับ flow ของ API และ c2patool สำหรับการตรวจสอบระดับไบต์
อะไรที่ถูกทำลายไปจริงๆ
Manifest ของ C2PA คือข้อมูลที่ลงนามด้วยการเข้ารหัสและฝังอยู่ในคอนเทนเนอร์ของไฟล์ โดยระบุผู้ลงนามในสินทรัพย์และคำกล่าวอ้างที่เกี่ยวข้องกับไฟล์นั้น
เพราะ manifest ถูกลงนามไว้ การเปลี่ยนไบต์ของไฟล์โดยไม่ลงนามใหม่จะทำให้ลายเซ็นไม่ถูกต้อง และตัวตรวจสอบสามารถตรวจพบได้
ประเด็นสำคัญคือ ระดับคอนเทนเนอร์: เมื่อคุณเขียนคอนเทนเนอร์ไฟล์ใหม่ manifest เดิมมักหายไป
| การดำเนินการ | Manifest ยังคงอยู่โดยค่าเริ่มต้นหรือไม่? |
|---|---|
| คัดลอกหรือย้ายแบบไบต์ต่อไบต์ | ใช่ |
sharp().resize().toBuffer() |
ไม่ |
ImageMagick convert / magick
|
ไม่ |
Pillow Image.save()
|
ไม่ |
| PNG เป็น WebP, JPEG เป็น AVIF | ไม่ |
| การปรับแต่งอัตโนมัติของ Image CDN | โดยปกติไม่ |
| ภาพหน้าจอ | ไม่ |
| บันทึกซ้ำจากโปรแกรมแก้ไขรูปภาพ | ไม่ |
| การอัปโหลด S3 โดยไม่มีการแปลง | ใช่ |
รายการในคอลัมน์ “ไม่” คือสิ่งที่ web application ทำกับรูปภาพอยู่แล้ว: สร้าง thumbnail, สร้าง responsive variant, แปลง format, หรือล้าง EXIF เพื่อความเป็นส่วนตัว แต่ละขั้นตอนอาจสมเหตุสมผล แต่สามารถตัดห่วงโซ่ provenance ได้แบบเงียบ ๆ
ตัวอย่างที่ต้องระวังคือ -strip เพื่อความเป็นส่วนตัว เนื่องจาก EXIF อาจมีพิกัด GPS หรือหมายเลขซีเรียลของกล้อง แต่การลบเมตาดาต้าทั้งหมดจะลบ C2PA manifest ไปด้วย หากต้องการลบข้อมูลส่วนตัวแต่ยังเก็บ provenance ให้ลบเฉพาะบล็อก EXIF ที่ต้องการ แทนการ strip ทุกอย่าง
พิสูจน์ได้ในสองนาที
ก่อนแก้ pipeline ให้ตรวจสอบก่อนว่าปัญหาเกิดขึ้นจริงหรือไม่
เตรียม fixture หนึ่งไฟล์ที่มี manifest ถูกต้อง เช่น ไฟล์ภาพที่ Claude สร้าง หรือไฟล์ตัวอย่างที่ลงนามแล้วจาก Content Authenticity Initiative
ติดตั้ง CLI อ้างอิง:
cargo install c2patool
ตรวจสอบว่า fixture มีลายเซ็นที่ใช้ได้:
c2patool fixtures/signed-sample.png
คุณควรได้รายงาน JSON ที่มีข้อมูลผู้สร้างคำกล่าวอ้างและสถานะลายเซ็น จากนั้นอัปโหลดผ่าน endpoint จริง แล้วดึงไฟล์กลับผ่าน URL เดียวกับที่ frontend ใช้งาน:
# 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
ตีความผลลัพธ์เป็น 3 กรณี:
- รายงานถูกต้อง — manifest ยังอยู่และลายเซ็นตรวจสอบผ่าน
- ไม่พบ manifest — มีขั้นตอนใน pipeline ลบ manifest ออก
- ข้อผิดพลาดในการตรวจสอบ — manifest ยังอยู่ แต่ลายเซ็นไม่ตรงกับไบต์ปัจจุบัน
กรณีที่สามต้องให้ความสำคัญเป็นพิเศษ เพราะมักหมายความว่าเครื่องมือแปลงภาพเก็บ metadata block ไว้ แต่เขียนพิกเซลใหม่ ทำให้ไฟล์ดูเหมือนถูกแก้ไขหลังการลงนาม
ค้นหาขั้นตอนที่เป็นต้นเหตุ
หาก round-trip ล้มเหลว อย่าคาดเดา ให้ตรวจสอบ manifest หลังแต่ละขั้นตอนของ pipeline เพื่อหา breakpoint
ผู้ต้องสงสัยหลักมีดังนี้
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);
อย่างไรก็ตาม keepMetadata() เพียงอย่างเดียวไม่ทำให้ provenance ใช้งานได้เสมอไป เพราะพิกเซลเปลี่ยนแล้ว ลายเซ็นเดิมจึงไม่สามารถยืนยันกับไบต์ใหม่ได้
หากต้องการรักษาห่วงโซ่ provenance ที่ถูกต้อง ให้ทำทั้งสองอย่าง:
- เก็บ metadata ที่ต้องการ
- ลงนามผลลัพธ์ใหม่ พร้อมบันทึกการแปลงเป็น action assertion เช่น
c2pa.resized
ไลบรารี c2pa สำหรับ Rust, Python, JavaScript และ C รองรับแนวทางนี้
2. การแปลงรูปแบบ
การแปลง PNG เป็น WebP หรือ JPEG เป็น AVIF หมายถึงการสร้างคอนเทนเนอร์ใหม่
ทางเลือกมี 2 แบบ:
- เก็บข้อมูลที่จำเป็นและลงนามไฟล์ผลลัพธ์ใหม่
- ยอมรับว่าห่วงโซ่ provenance สิ้นสุดที่ขั้นตอนนี้ และแสดงสถานะให้ชัดเจน
3. Image CDN
Image CDN จำนวนมากเขียนไฟล์ใหม่ตอนส่งมอบ เช่น ปรับคุณภาพ ปรับขนาด หรือแปลง format อัตโนมัติ
ต้องทดสอบผ่าน delivery URL ที่ผู้ใช้เข้าถึงจริง ไม่ใช่ origin URL มิฉะนั้นผลทดสอบอาจผ่านทั้งที่ไฟล์จริงหน้าเว็บสูญเสีย manifest ไปแล้ว
4. Upload normalization
บริการบางตัวเข้ารหัสรูปใหม่ทันทีหลังอัปโหลดเพื่อทำให้ไฟล์เป็นมาตรฐาน ขั้นตอนนี้มักซ่อนอยู่ใน infrastructure repository หรือ worker ที่ไม่ค่อยถูกตรวจสอบ
เพิ่มการตรวจสอบ c2patool ก่อนและหลัง normalization เพื่อยืนยันผลลัพธ์
ทำให้เป็นการทดสอบถาวร
การรัน curl ครั้งเดียวบอกได้เพียงสถานะปัจจุบัน แต่ไม่ได้ป้องกัน regression เมื่อมีคนเพิ่ม resize step ใน sprint ถัดไป
ให้แยกการทดสอบเป็น 2 เลเยอร์:
- Apidog ตรวจสอบ API round-trip และ HTTP response
-
c2patoolตรวจสอบ manifest และลายเซ็นระดับไบต์
เลเยอร์แรก: การตรวจสอบแบบ round-trip ใน Apidog
สร้าง scenario ที่มี 2 ขั้นตอน:
- อัปโหลด fixture ที่ลงนามแล้ว
- ดาวน์โหลด asset จาก delivery URL ที่ API ส่งกลับ
ขั้นตอนที่ 1: POST /v1/assets
- ตั้งค่า Body เป็น
multipart/form-data - แนบ signed fixture
- ตรวจสอบว่า response status เป็น
201 - ตรวจสอบ response schema
- เก็บ URL จาก response ไว้ใช้ในขั้นตอนถัดไป
แนวทางการตั้งค่า multipart เหมือนกับบทความ การทดสอบ API อัปโหลดไฟล์
เพิ่ม post-response script:
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}}
ตรวจสอบว่า:
- status เป็น
200 -
Content-Typeตรงกับรูปแบบที่คาดหวัง - ขนาด response ไม่ลดลงอย่างผิดปกติ
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);
});
การเทียบขนาดไฟล์เป็นเพียง heuristic ไม่ใช่ข้อพิสูจน์ว่าลายเซ็นยังใช้ได้ แต่ช่วยตรวจจับการ re-encode ที่ชัดเจนได้เร็วใน test suite เดียวกัน
ดูแนวทาง assertion เพิ่มเติมได้ที่ API assertions
เลเยอร์สอง: การตรวจสอบระดับไบต์ใน CI
Apidog ตรวจสอบ flow ของ HTTP ได้ แต่การ parse และตรวจสอบลายเซ็น C2PA ต้องใช้ c2patool
ตัวอย่าง GitHub Actions:
# .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 ล้มเหลวแต่ shell ไม่ส่งผลให้ job ล้มเหลว คุณจะได้ build สีเขียวทั้งที่ manifest ถูกลบออกไปแล้ว
หากเพิ่งเริ่มรัน Apidog scenario ใน pipeline ดูการตั้งค่าได้ใน การทำให้การทดสอบ API เป็นอัตโนมัติใน GitHub Actions
เลเยอร์สาม: verification endpoint
หาก provenance เป็น feature ของผลิตภัณฑ์ ไม่ใช่แค่ internal check ให้สร้าง endpoint สำหรับตรวจสอบโดยเฉพาะ
endpoint นี้ควรรันไลบรารี c2pa และส่งคืนผลแบบมีโครงสร้าง เช่น:
{
"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"
}
}
อย่าใช้เพียง boolean เดียว ให้เก็บอย่างน้อย 3 สถานะ:
-
verified— พบ manifest และลายเซ็นถูกต้อง -
absent— ไม่พบ manifest -
invalid— พบ manifest แต่ลายเซ็นไม่ตรงกับไฟล์
และควรเพิ่ม:
-
unchecked— ยังไม่ได้ตรวจสอบ เช่น verifier ไม่พร้อมใช้งาน
absent และ invalid มีความหมายต่างกัน การรวมทั้งสองเป็น false จะทำให้คุณสูญเสียสัญญาณสำคัญ
กำหนด schema นี้ใน OpenAPI และตรวจสอบใน CI เพื่อป้องกัน field หายระหว่าง refactor ดูแนวทางได้ที่ วิธีการตรวจสอบ OpenAPI specs
สี่ fixtures ที่ควรเก็บไว้
ชุดทดสอบ provenance ไม่ควรมีเฉพาะ happy path ให้เก็บ fixture ที่ครอบคลุม failure mode ด้วย
ไฟล์ที่ลงนามถูกต้อง
คาดหวังverifiedใช้ตรวจจับการลบ manifest โดยไม่ตั้งใจไฟล์ที่ถูกลบ manifest แล้ว
ใช้รูปเดียวกัน แต่ลบ metadata ด้วยexiftool -all=
คาดหวังabsentไม่ใช่verifiedและไม่ควรเป็น server errorไฟล์ที่ถูกแก้ไขหลังลงนาม
เปลี่ยนไบต์บางส่วนหลังจากลงนาม
คาดหวังinvalidเพื่อพิสูจน์ว่าระบบตรวจลายเซ็นจริง ไม่ใช่แค่ตรวจว่ามี metadata blockรูปแบบที่ไม่รองรับ
ใช้ไฟล์ที่ไม่มีการรองรับ manifest
คาดหวังabsentอย่างชัดเจน แทนการตอบ500
คอมมิต fixture ทั้ง 4 ไฟล์ไว้ใน repository ถัดจาก scenario ทดสอบ ไฟล์เหล่านี้ควรมีขนาดเล็ก คงที่ และใช้ซ้ำได้ในทุก pull request
ทำไมต้องสนใจ
มี 3 เหตุผลหลัก
1. ความถูกต้องของ product claim
หาก UI แสดงป้าย provenance แต่ pipeline ลบ manifest เมื่อสร้าง thumbnail หรือ responsive image ป้ายนั้นจะผิดทันทีสำหรับไฟล์ที่ผ่านการแปลง
2. การปฏิบัติตามข้อกำหนด
หากคุณใช้ C2PA ใน flow ที่เกี่ยวข้องกับ Article 50 การลบ manifest คือ control ที่ใช้งานไม่ได้ ดูรายละเอียดการแบ่งหน้าที่ของ provider และ deployer ได้ใน EU AI Act Article 50 สำหรับนักพัฒนา API
3. ความน่าเชื่อถือของสัญญาณ provenance
Provenance มีประโยชน์ก็ต่อเมื่อห่วงโซ่ยังอยู่ครบตั้งแต่ต้นทางถึงปลายทาง ทุก pipeline ที่ลบ manifest แบบเงียบ ๆ ทำให้ระบบนิเวศตรวจสอบเนื้อหาได้ยากขึ้น รวมถึงเมื่อคุณต้องตรวจสอบไฟล์จากผู้อื่น
ดาวน์โหลด Apidog เพื่อสร้าง scenario แบบ round-trip กับ endpoint ของคุณ แล้วต่อด้วยขั้นตอน c2patool ใน CI
คำถามที่พบบ่อย
การปรับขนาดรูปภาพจะลบเมตาดาต้า C2PA หรือไม่?
ใช่ โดยค่าเริ่มต้นในไลบรารีทั่วไป การเก็บ metadata ต้องเปิด flag อย่างชัดเจน และหากพิกเซลเปลี่ยน ต้องลงนามผลลัพธ์ใหม่เพื่อให้ลายเซ็นยังถูกต้อง
ฉันจะตรวจสอบได้อย่างไรว่าไฟล์มีเมตาดาต้า C2PA หรือไม่?
รันคำสั่ง:
c2patool <file>
หรืออัปโหลดไฟล์ไปที่ หน้าตรวจสอบ Content Credentials
ฉันสามารถเก็บ C2PA เมื่อปรับขนาดภาพได้หรือไม่?
ได้ แต่ต้องมากกว่าการเก็บ metadata block เดิม ให้เก็บข้อมูลที่จำเป็น แล้วลงนามไฟล์ผลลัพธ์ใหม่พร้อม action assertion เช่น c2pa.resized มิฉะนั้นลายเซ็นเดิมจะไม่ตรงกับไบต์ใหม่
CDN ลบ Content Credentials หรือไม่?
หลาย CDN ลบออกเมื่อมีการปรับแต่งภาพอัตโนมัติ บางระบบสามารถเก็บและลงนามใหม่ได้ ต้องทดสอบผ่าน delivery URL ที่ผู้ใช้ใช้งานจริง ไม่ใช่ origin
ความแตกต่างระหว่าง stripped กับ invalid คืออะไร?
-
strippedหรือabsent: ไม่พบ manifest -
invalid: พบ manifest แต่ลายเซ็นไม่ตรงกับไบต์ของไฟล์
ให้เก็บสองสถานะนี้แยกกัน เพราะบ่งชี้ปัญหาคนละแบบ
Apidog ตรวจสอบลายเซ็น C2PA ได้โดยตรงหรือไม่?
Apidog เหมาะกับการตรวจสอบ round-trip, HTTP response และ JSON จาก verification endpoint ส่วนการ parse และตรวจสอบลายเซ็นเป็นหน้าที่ของ c2patool หรือไลบรารี c2pa ในบริการของคุณเอง
ควรลบ EXIF เพื่อความเป็นส่วนตัว แต่เก็บ C2PA ไว้หรือไม่?
ควรทำ หากต้องการลบข้อมูลส่วนตัว เช่น GPS ให้ลบเฉพาะบล็อก EXIF ที่เกี่ยวข้อง หลีกเลี่ยงการใช้ -strip แบบครอบคลุม เพราะจะลบ C2PA manifest ออกด้วย
บทสรุป
เมตาดาต้า provenance อาจเข้ามาถึง API ของคุณอย่างสมบูรณ์ แต่ถูกทำลายระหว่าง resize, re-encode หรือ CDN delivery โดยไม่มีการแจ้งเตือน
แนวทางที่ใช้งานได้จริงคือ:
- เตรียม signed fixture
- ทดสอบ upload และ download ผ่าน delivery path จริง
- ใช้ Apidog ตรวจสอบ API flow
- ใช้
c2patoolตรวจสอบ manifest ใน CI - ทำให้ build ล้มเหลวเมื่อ manifest หายหรือสถานะลายเซ็นไม่ถูกต้อง
ใช้เวลาเซ็ตอัปไม่นาน แต่ช่วยเปลี่ยนป้าย provenance ใน UI จากคำกล่าวอ้าง ให้กลายเป็นสิ่งที่ pipeline ของคุณบังคับใช้ได้จริง
Top comments (0)