tapeshelf เข้ารหัสวิดีโออย่างไร และทำไมจึงไม่เก็บคีย์ไว้

วิดีโอส่วนตัวบน tapeshelf มีไว้สำหรับเจ้าของและคนที่เจ้าของเลือกเท่านั้น บทความนี้เล่าว่าแอปรักษาสัญญานั้นอย่างไร และการป้องกันสิ้นสุดตรงไหน
จากการอัปโหลดถึงการสตรีม
เบราว์เซอร์ของคุณอัปโหลดไฟล์ตรงไปยังบักเก็ตส่วนตัวในพื้นที่จัดเก็บที่รองรับ S3 เป็นส่วนละ 16 MB ซึ่งอัปโหลดต่อได้ถ้าการเชื่อมต่อหลุด ไฟล์ไม่ผ่านเซิร์ฟเวอร์ API ของเราเลย
ตัวประมวลผลเบื้องหลัง (worker) ตรวจไฟล์ด้วย ffprobe แล้วลบเมทาดาทาออก (สถานที่และเวลาที่ถ่าย กล้อง ผู้สร้าง ความเห็น) ด้วยการเขียนไฟล์ใหม่โดยไม่เข้ารหัสภาพและเสียงซ้ำ ไฟล์ที่ทำความสะอาดแล้วนี้คือไฟล์ที่ผู้คนดาวน์โหลด วิดีโอที่อัปโหลดก่อนวันที่ 18 ตุลาคม 2026 ยังมีเมทาดาทาอยู่
วิดีโอ H.264 ความละเอียดไม่เกิน 1080p ที่ผ่านการตรวจอีกไม่กี่ข้อจะแค่ถูกแพ็กใหม่ ซึ่งใช้เวลาไม่กี่วินาที นอกนั้นจะถูกแปลงเป็น H.264 ความละเอียดไม่เกิน 1080p จากนั้น ffmpeg จะตัดผลลัพธ์เป็นเซกเมนต์ HLS ยาวหกวินาที Safari เล่นได้เอง ส่วนเบราว์เซอร์อื่นเล่นผ่าน hls.js
การเข้ารหัสเซกเมนต์
ffmpeg เข้ารหัส HLS เองได้ แต่ต้องการคีย์เป็นไฟล์บนดิสก์ เราไม่อยากให้คีย์อยู่บนดิสก์ใดเลย worker จึงเข้ารหัสเซกเมนต์เอง
- แต่ละเซกเมนต์เข้ารหัสด้วย AES-128 โหมด CBC ตามวิธีที่มาตรฐาน HLS กำหนด
- คีย์ยาว 16 ไบต์ ไม่ซ้ำกันในแต่ละวิดีโอ และอยู่ในหน่วยความจำของ worker เฉพาะตอนที่ทำงานเท่านั้น
- เวกเตอร์เริ่มต้น (IV) คือหมายเลขลำดับของเซกเมนต์ ซึ่งเครื่องเล่น HLS จะใช้เองเมื่อเพลย์ลิสต์ไม่ได้ระบุไว้
มีเพียงเซกเมนต์ที่เข้ารหัสแล้วและเพลย์ลิสต์ของมันที่ถูกส่งไปยังบักเก็ตส่วนตัว ไฟล์ชั่วคราวของ worker จะถูกลบเมื่องานเสร็จ
คีย์ที่ไม่เคยถูกเก็บ
หลังจากนั้น คีย์จะไม่ถูกเก็บไว้ที่ไหนเลย แทนที่จะสร้างคีย์สุ่มแล้วต้องคอยเฝ้า tapeshelf จะคำนวณคีย์ขึ้นใหม่ทุกครั้งที่ต้องใช้
video key = HKDF-SHA256(master key, "video:" + video id + version) → 16 bytes
การแก้ไขวิดีโอจะเพิ่มเวอร์ชัน วิดีโอจึงได้คีย์ใหม่
มาสเตอร์คีย์คือความลับหนึ่งตัวในการกำหนดค่าของเซิร์ฟเวอร์ ไม่อยู่ในฐานข้อมูล บักเก็ต หรือข้อมูลสำรอง สำเนาของฐานข้อมูลจึงไม่มีคีย์วิดีโอเลย และบักเก็ตก็มีแต่เซกเมนต์ที่เข้ารหัสแล้ว ผู้โจมตีจึงต้องได้การกำหนดค่าของเซิร์ฟเวอร์ไปด้วย
ถ้ามาสเตอร์คีย์หาย จะไม่มีวิดีโอไหนเล่นได้อีก และข้อมูลสำรองของฐานข้อมูลก็ช่วยอะไรไม่ได้ เรื่องนี้สำคัญที่สุดถ้าคุณรัน tapeshelf บนเซิร์ฟเวอร์ของตัวเอง
สามคำขอเมื่อคุณกดเล่น
- การเล่น API ตรวจว่าคุณมีสิทธิ์ดู คือคุณเป็นผู้สร้าง วิดีโออยู่บนชั้นวางของคุณ หรือเป็นวิดีโอสาธารณะ จากนั้นส่งที่อยู่ของเพลย์ลิสต์ที่มีโทเค็นแบบลงนามอยู่ข้างใน ซึ่งระบุวิดีโอและตัวคุณ (หรือไม่ระบุใครถ้าคุณไม่ได้เข้าสู่ระบบ) ใช้ได้หนึ่งชั่วโมง
- เพลย์ลิสต์ API ตรวจโทเค็นและสิทธิ์ของคุณอีกครั้ง แล้วเขียนเพลย์ลิสต์ใหม่ทันที ทุกเซกเมนต์กลายเป็นลิงก์พื้นที่จัดเก็บแบบลงนาม และบรรทัดคีย์ชี้กลับมาที่ API
- คีย์ โทเค็นต้องเป็นของวิดีโอนี้ ถ้าเป็นวิดีโอส่วนตัว เซสชันที่คุณเข้าสู่ระบบอยู่ต้องเป็นของคนที่ระบุในโทเค็นด้วย เมื่อนั้น API จึงจะคำนวณคีย์และส่ง 16 ไบต์นั้นมา
ลิงก์ชั่วคราวไม่มีบัญชีให้ตรวจ บนหน้าของลิงก์นั้นโทเค็นจึงระบุตัวลิงก์แทน ทุกคำขอจะตรวจว่าลิงก์ยังใช้ได้และยังมีวิดีโอนั้นอยู่ และโทเค็นจะไม่มีอายุยาวกว่าลิงก์ วิดีโอที่แขกได้รับจากการแลกเปลี่ยนก็เล่นแบบเดียวกันบนหน้าการแลกเปลี่ยนเป็นเวลาหนึ่งสัปดาห์
ผลการตรวจสิทธิ์จะถูกแคชไว้หนึ่งนาที ภาพยนตร์ยาวสองชั่วโมงจึงไม่ต้องเรียกฐานข้อมูลทุกคำขอ วิดีโอที่ถูกลบยังเริ่มเล่นได้ภายในนาทีนั้น ส่วนลิงก์ชั่วคราวที่หมดอายุหรือถูกยกเลิกจะหยุดทันที ไม่ว่ากรณีไหน เครื่องเล่นที่เล่นอยู่แล้วยังมีคีย์และลิงก์เซกเมนต์อยู่ และอาจเล่นต่อไปได้
ลิงก์เซกเมนต์ก็ลงนามและหมดอายุเช่นกัน หลังหนึ่งชั่วโมงหรือนานกว่านั้น เครื่องเล่นโหลดเพลย์ลิสต์แค่ครั้งเดียว และลิงก์อายุสั้นจะทำให้แค่กดหยุดชั่วคราวก็พังได้ เมื่อลิงก์หมดอายุ เครื่องเล่นจะขอการเล่นใหม่และเล่นต่อจากจุดเดิม และถ้าไม่มีคีย์ เซกเมนต์ก็ไม่มีประโยชน์อยู่แล้ว
ทำไมจึงไม่มีไฟล์ให้ฉกไป
เครื่องเล่นไม่เคยได้ลิงก์ไปยังไฟล์วิดีโอ สิ่งที่ได้คือเพลย์ลิสต์ที่ผูกกับโทเค็น ชิ้นส่วนที่เข้ารหัส และคีย์ที่อยู่หลังการตรวจสิทธิ์ ถ้าคัดลอกที่อยู่เพลย์ลิสต์ของวิดีโอส่วนตัวไปเปิดในเบราว์เซอร์ของเพื่อน จะไม่มีอะไรเล่น เพราะคีย์ต้องใช้เซสชันของคุณ
การดาวน์โหลดเป็นอีกเรื่องหนึ่ง คนที่เข้าสู่ระบบดาวน์โหลดสิ่งที่ตัวเองมีสิทธิ์ดูได้ ถ้าไม่มีบัญชี จะดาวน์โหลดได้เฉพาะผ่านลิงก์ชั่วคราวที่มีคนส่งให้ หรือวิดีโอที่ได้รับในฐานะแขกจากการแลกเปลี่ยน เป็นเวลาหนึ่งสัปดาห์ ลิงก์ดาวน์โหลดมีอายุสองนาที
รูปภาพทำงานต่างออกไป ภาพขนาดย่อ 16 เฟรมที่ดึงจากแต่ละวิดีโอ และพรีวิวแบบเฟรมที่สร้างจากเฟรมเหล่านั้น อยู่ในบักเก็ตสาธารณะภายใต้ชื่อสุ่มยาวๆ และไม่มีใครดึงรายการไฟล์ในบักเก็ตได้ พรีวิวของวิดีโอส่วนตัวมองเห็นได้โดยตั้งใจ เพื่อให้ผู้เข้าชมรู้ว่ากำลังจะขออะไร
สิ่งที่ป้องกันได้
- คนที่ไม่มีสิทธิ์จะไม่ได้เพลย์ลิสต์ ไม่ได้เซกเมนต์ และไม่ได้คีย์
- ลิงก์เซกเมนต์ที่รั่วไหลเป็นแค่ข้อมูลเข้ารหัสที่อ่านไม่ออก ลิงก์เพลย์ลิสต์ของวิดีโอส่วนตัวที่รั่วไหลจะใช้ไม่ได้ถ้าไม่มีเซสชันของคนที่ได้รับลิงก์นั้น และหมดอายุภายในหนึ่งชั่วโมงอยู่ดี
- สำเนาฐานข้อมูลที่ถูกขโมยไปจะไม่เผยคีย์ใดเลย
สิ่งที่ป้องกันไม่ได้
- ใครดูได้ก็บันทึกได้ คนที่มีสิทธิ์ดูสามารถบันทึกหน้าจอหรือบันทึกสตรีมด้วยเครื่องมือที่เหมาะสม เพราะเขาได้คีย์มาอย่างถูกต้อง tapeshelf ไม่มี DRM DRM จริงอย่าง Widevine หรือ FairPlay ต้องพึ่งเซิร์ฟเวอร์ใบอนุญาตเชิงพาณิชย์ และก็ยังห้ามกล้องที่ถ่ายหน้าจอไม่ได้อยู่ดี
- คนที่คุณแชร์ให้ การแชร์หรือการแลกเปลี่ยนทำให้อีกฝ่ายได้สำเนาถาวร และดาวน์โหลดไฟล์ได้ ใครก็ตามที่เปิดลิงก์ชั่วคราวที่คุณส่งไปก็ดาวน์โหลดได้เช่นกันตราบที่ลิงก์ยังใช้ได้ สิ่งที่เกิดกับไฟล์หลังจากนั้นอยู่นอกเหนือการควบคุมของเรา แชร์ให้คนที่คุณไว้ใจเท่านั้น
- ตัวเซิร์ฟเวอร์เอง นี่ไม่ใช่การเข้ารหัสแบบต้นทางถึงปลายทาง เซิร์ฟเวอร์เป็นผู้คำนวณคีย์ คนที่ดูแลเซิร์ฟเวอร์จึงเล่นวิดีโอใดก็ได้ บน tapeshelf.com คนนั้นคือเรา และเราจะเปิดวิดีโอส่วนตัวเมื่อจำเป็นต่อการให้บริการและการกลั่นกรองเนื้อหา ส่วนบนอินสแตนซ์ที่โฮสต์เอง คือผู้ดูแลระบบ
ฉบับย่ออยู่ที่หน้าความปลอดภัย ถ้าอยากตรวจสอบเองแทนที่จะเชื่อคำพูดของเรา โค้ดเป็นโอเพนซอร์ส และคุณจะรันเองได้