iT邦幫忙

2026 iThome 鐵人賽

DAY 10
0
Software Development

下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練系列 第 10

Day 10:AES-128 加密的片段,金鑰跟初始向量(IV)從哪裡來

  • 分享至 

  • xImage
  •  

前言:片段加密了,但金鑰藏在哪?

昨天解析出的 Media playlist,除了片段清單,有時候還會帶一個 #EXT-X-KEY 標籤,宣告這份清單的片段是加密過的。第一次遇到會有個直覺疑問:加密的內容要解密,金鑰在哪裡?答案是:清單本身會告訴你去哪裡拿金鑰,但初始向量(IV)不一定會明講

今日目標

  • 看懂 #EXT-X-KEY 標籤帶的資訊
  • 理解 AES-128-CBC 需要金鑰跟 IV 兩樣東西才能解密
  • 知道 IV 沒有明講時,規格怎麼定義該用什麼補上

#EXT-X-KEY 標籤長這樣

#EXT-X-KEY:METHOD=AES-128,URI="https://example.com/key",IV=0x0000000000000000000000000000f0
#EXTINF:8.0,
segment000.ts

METHOD 宣告加密演算法(AES-128 是 HLS 最常見的加密方式,使用 CBC 模式);URI 是取得金鑰本身的位置——金鑰不是寫在清單裡,而是要另外發一次請求去下載;IV 則是這次加密使用的初始向量,用十六進位字串表示。

IV 不是每次都會明講

規格(RFC 8216)定義:如果 #EXT-X-KEY 沒有帶 IV 屬性,就要用這個片段的媒體序號(media sequence number)當作 IV,把序號轉成對應長度的位元組序列來使用。這代表解密邏輯不能假設「一定拿得到 IV 字串」,要準備好在沒有明講時,用片段序號推算出對應的 IV。

❌ vs ✅:假設一定有 IV vs 明確處理沒有的情況

❌ 反例:假設清單一定會帶 IV

def get_cipher(key: bytes, key_tag) -> AES:
    iv = bytes.fromhex(key_tag.iv.replace("0x", ""))  # 沒有 IV 時直接拋例外
    return AES.new(key, AES.MODE_CBC, iv)

✅ 正例:沒有明講時,退回用媒體序號推算

def get_cipher(key: bytes, key_tag, sequence: int) -> AES:
    if key_tag.iv is not None:
        iv = bytes.fromhex(key_tag.iv.replace("0x", ""))
    else:
        iv = sequence.to_bytes(16, byteorder="big")  # 規格定義的退路
    return AES.new(key, AES.MODE_CBC, iv)

今日思考題

如果你處理過某種加密協定,協定裡有沒有「某個參數在特定情況下可以省略、規格定義了預設推算方式」這種細節?你的實作有沒有處理省略的情況,還是只驗證過「有明講」的那條路徑?

今日重點回顧

  • #EXT-X-KEY 宣告加密方式跟金鑰位置,金鑰本身要另外發請求取得
  • AES-128-CBC 解密需要金鑰跟 IV 兩樣東西
  • IV 沒有明講時,規格定義要用片段的媒體序號推算,不是隨便留空或拋錯

明日預告

明天是一個真實踩過的坑:解密結果是亂碼,問題出在 IV 沒處理對。


上一篇
Day 09:Master playlist vs Media playlist——為什麼有時候要多繞一層
下一篇
Day 11:案例——沒有實作規格定義的 IV 退路,會在什麼情況下出包
系列文
下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言