AWS 上的 SPEKE 媒體內容加密執行程式解決方案

- 作者 -
Jill Wang, Technical Account Manager, AWS

[用途]

就“安全內容交付”而言,將數位版權管理(DRM)技術應用於媒體內容是非常普遍且重要的。 AWS Elemental MediaConvert 和MediaPackage 支持安全打包程序和編碼器密鑰交換(SPEKE)API,以通過簡單的配置啟用 DASH / HLS 輸出的 DRM 加密。以下我們將提供如何在 AWS Media Services 搭配 AWS 提供的 SPEKE 參考服務器透過 SPEKE API 取得授權支援的播放程式與 DRM 供應商密鑰服務器進行媒體內容的解密

什麼是 SPEKE?

SPEKE 是 Secure Packager and Encoder Key Exchange (SPEKE) 的英文縮寫,這是一種免權利金的開放原始碼 API 規格,針對即時和隨選串流視訊,定義影片編碼器、轉碼器、原始伺服器和數位版權管理 (DRM) 系統金鑰伺服器之間的加密通訊標準。

SPEKE 藉由增加 CPIX 中沒有的規格,例如金鑰伺服器與加密程式之間的驗證和通訊方法,建立在由 DASH Industry Forum (DASH-IF) 開發的 Content Protection Information Exchange (CPIX) 規格基礎上。(CPIX 也支援 HLS 內容)

Secure Packager and Encoder Key Exchange API 抱定一個宗旨:簡化多個複雜流程。總之,SPEKE 透過下列方式來實現這個宗旨:

* SPEKE 以一個開放、採用標準為基礎的 API,取代多重 DRM 廠商金鑰伺服器和加密程式之間數百種專屬 API 整合的組合,藉此簡化內容加密。
* SPEKE 為媒體和娛樂影片業者提供更大的彈性和廠商選擇。
* SPEKE 支援多重 DRM 結構定義,以及不同觀看裝置類型的多種封裝格式。

下圖顯示將 SPEKE 與在 AWS 雲端中執行的服務和功能搭配使用時的概要架構。


主要服務和元件:

加密程式 – 提供在 AWS 雲端中的加密技術。加密程式接收來自操作者的請求,並透過 Amazon API Gateway 從 DRM 金鑰提供者擷取所需加密金鑰,以保護加密的內容。它會將加密的資訊傳送到 Amazon S3 儲存貯體,或透過 Amazon CloudFront 分發。

AWS IAM 和 Amazon API Gateway – 管理客戶信任的角色和加密程式與金鑰提供者之間的代理程式通訊。API Gateway 提供記錄功能,讓客戶控制其與加密程式和 DRM 平台之間的關係。客戶可透過 IAM 角色組態啟用金鑰提供者存取。API Gateway 所在的 AWS 區域必須與加密程式相同。

AWS Certificate Manager – (選用) 為內容金鑰加密提供憑證管理。建議使用加密內容金鑰以保護通訊安全。Certificate Manager 所在的 AWS 區域必須與加密程式相同。

DRM 平台金鑰提供者 – 透過符合 SPEKE 規定的 API,向加密程式提供加密金鑰。提供者也為媒體播放器提供解密授權。
播放器 – 向相同的 DRM 平台金鑰伺服器請求金鑰,然後使用該金鑰來解鎖內容,並提供給檢視者。

[操作步驟]

此次的解決方案是 AWS 所提供的一個 SPEKE協議和密鑰服務器 (Key Server) 的無服務器 (Serverless) 開源項目。 此解決方案將會透過 CloudFormation 部署一個為 HLS 和 DASH 進行端到端 Segment 提供加密的密鑰服務器 (Key Server) 和密鑰分發緩存,並且包含以下架構會用到的服務到你指定的AWS Account,包含 AWS 身份和訪問管理(IAM),Amazon API Gateway,AWS Lambda,Amazon S3,Amazon CloudFront和AWS Secrets Manager。 而密鑰服務器 (Key Server) 的原始程式碼以 Python 的程式語言實作在一個 Lambda Function 裡面 。因此可以被廣泛的讀者重複使用。

下圖顯示了無服務器 SPEKE 解決方案的主要組件以及這些組件在運行時的連接性。 該圖還顯示了AWS MediaPackage 或 AWS MediaConvert 與 SPEKE 之間其中一種可能的整合架構。


以下我們將分段介紹如何安裝、測試和設定我們在這裡部屬的密鑰服務器 (Key Server)。將會有以下3個步驟:

* 安裝 - 包含API Gateway、Lambda 的部署和 AWS Elemental MediaPackage 頻道的整合與安裝說明。
* 測試案例 - 包括幾個單元測試和手動測試案例,可用於驗證 SPEKE Reference Server 的運行。 這些測試案例不需要與額外其他的服務整合。
* 設定 AWS Elemental MediaPackage - 驗證 SPEKE參考服務器 在 AWS Elemental MediaPackage 上的操作步驟。

步驟一、利用 CloudFormation 部署架構


託管的 Cloudformation 模板可以在以下地區被支持:ap-northeast-1 ap-northeast-2 ap-south-1 ap-southeast-1 ap-southeast-2 eu-central-1 eu-west-1 eu-west-3 sa-east-1 us-east-1 us-west-1 us-west-2

1.1 登入 AWS Console 後,選擇一個支援的地區,例如: us-east-1 or us-west-2 作為開始。
1.2 點選 AWS Service 進入到 CloudFormation 的 Console 建立一個新的 Stack,選擇 [Create Stack] > [With new resources (standard)] > [Next]
1.3 在 “Specify template” 頁面上,提供 CloudFormation 模板的來源。 將項目發起人託管準備好的 CloudFormation json 模板填到 Amazon S3 URL 的欄位: https://s3.amazonaws.com/rodeolabz-us-east-1/speke/speke_reference.json  並繼續下一步 [Next].


1.4 在 "Specify stack detials" 的頁面我們指定一個 Stack name,比如說 SPEKE
1.5 提供數值給參數 KeyRetentionDays。這個參數的值是將密鑰保留在S3存儲桶中以供客戶端播放的時間。 早於此數值的密鑰將由S3自動刪除。 默認值為2天,通常足以應付多個時區的實時內容。
1.6 其餘的參數以及 “Optional” 的選項我們保留預設空白> [Next] > [Next] 最後到 Reveiw SPEKE 的頁面確認設定無誤。

1.7 滑動至頁面底部,勾選“I acknowledge that AWS CloudFormation might create IAM resources.” 然後按下[Create stack]。 

1.8 在 CloudFormation 主要畫面中,會顯示我們創建的 Stack 狀態為 “CREATE_IN_PROGRESS” .等待大約 5~10 分鐘的時間後,CloudFormation 創建完成,Status 的狀態會顯示 “CREATE_COMPLETE”.在創建完成的 CloudFormation 畫面上方,點選 [Resources] 這個分頁.在這個頁面中,我們可以看到我們利用 CloudFormation 所創建出來的資源.


1.9 點選 [Outputs] 這個分頁, 則可以看到 SPEKE 服務器的 URL 和 存取 MediaPackage 的 RoleARN。 則第一步安裝部屬即完成。


步驟二、建置測試案例

這邊我們創建測試案例,使用靜態數據來生成可預測的回應,該回應可用於檢查 SPEKE 參考服務器的正確操作。我們可以在這邊下載 Python 的程式碼: https://github.com/awslabs/speke-reference-server/tree/master/tests

2.1 Lambda上的測試
2.1.1 開啟 AWS Lambda console。
2.1.2 選擇部署 Cloudformation 的地區 (us-east-1),找到剛剛部屬好的 EkeServerLambdaFunction > 點選 [Test] 這個分頁 ,然後在 Test event 選擇 [New event] 並填上 event 的名稱 ServerKeyRequest 
2.1.3 並在下方的文字框內貼上以下的內容,然後按下 [Save changes] 存檔。(“Host“: 請填寫步驟1.9 所提供的 SPEKEServerURL domain name)

{
  "resource": "/copyProtection",
  "path": "/copyProtection",
  "httpMethod": "POST",
  "headers": {
    "Accept": "*/*",
    "content-type": "application/xml",
    "Host": "<your API ID>.execute-api.us-east-1.amazonaws.com"
  },
  "requestContext": {
    "path": "/EkeStage/copyProtection",
    "stage": "EkeStage",
    "resourcePath": "/copyProtection",
    "httpMethod": "POST"
  },
  "body":
"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48Y3BpeDpDUElYIGlkPSI1RTk5MTM3QS1CRDZDLTRFQ0
MtQTI0RC1BM0VFMDRCNEUwMTEiIHhtbG5zOmNwaXg9InVybjpkYXNoaWY6b3JnOmNwaXgiIHhtbG5zOnBza2M9InVybjppZ
XRmOnBhcmFtczp4bWw6bnM6a2V5cHJvdjpwc2tjIiB4bWxuczpzcGVrZT0idXJuOmF3czphbWF6b246Y29tOnNwZWtlIj48
Y3BpeDpDb250ZW50S2V5TGlzdD48Y3BpeDpDb250ZW50S2V5IGtpZD0iNmM1ZjUyMDYtN2Q5OC00ODA4LTg0ZDgtOTRmMTM
yYzFlOWZlIj48L2NwaXg6Q29udGVudEtleT48L2NwaXg6Q29udGVudEtleUxpc3Q+PGNwaXg6RFJNU3lzdGVtTGlzdD48Y3
BpeDpEUk1TeXN0ZW0ga2lkPSI2YzVmNTIwNi03ZDk4LTQ4MDgtODRkOC05NGYxMzJjMWU5ZmUiIHN5c3RlbUlkPSI4MTM3N
jg0NC1mOTc2LTQ4MWUtYTg0ZS1jYzI1ZDM5YjBiMzMiPiAgICA8Y3BpeDpDb250ZW50UHJvdGVjdGlvbkRhdGEgLz4gICAg
PHNwZWtlOktleUZvcm1hdCAvPiAgICA8c3Bla2U6S2V5Rm9ybWF0VmVyc2lvbnMgLz4gICAgPHNwZWtlOlByb3RlY3Rpb25
IZWFkZXIgLz4gICAgPGNwaXg6UFNTSCAvPiAgICA8Y3BpeDpVUklFeHRYS2V5IC8+PC9jcGl4OkRSTVN5c3RlbT48L2NwaX
g6RFJNU3lzdGVtTGlzdD48Y3BpeDpDb250ZW50S2V5UGVyaW9kTGlzdD48Y3BpeDpDb250ZW50S2V5UGVyaW9kIGlkPSJrZ
XlQZXJpb2RfZTY0MjQ4ZjYtZjMwNy00Yjk5LWFhNjctYjM1YTc4MjUzNjIyIiBpbmRleD0iMTE0MjUiLz48L2NwaXg6Q29u
dGVudEtleVBlcmlvZExpc3Q+PGNwaXg6Q29udGVudEtleVVzYWdlUnVsZUxpc3Q+PGNwaXg6Q29udGVudEtleVVzYWdlUnV
sZSBraWQ9IjZjNWY1MjA2LTdkOTgtNDgwOC04NGQ4LTk0ZjEzMmMxZTlmZSI+PGNwaXg6S2V5UGVyaW9kRmlsdGVyIHBlcm
lvZElkPSJrZXlQZXJpb2RfZTY0MjQ4ZjYtZjMwNy00Yjk5LWFhNjctYjM1YTc4MjUzNjIyIi8+PC9jcGl4OkNvbnRlbnRLZ
XlVc2FnZVJ1bGU+PC9jcGl4OkNvbnRlbnRLZXlVc2FnZVJ1bGVMaXN0PjwvY3BpeDpDUElYPg==",
  "isBase64Encoded": true
}


2.1.4 按下 [Invoke]。隨後便會產生測試結果的 Log。
2.1.5 我們展開測試結果的 Log 可以看到以下的 XML 資料輸出,內容包含編碼過的加密密鑰值和密鑰ID (kid)。


2.2 API Gateway上的測試
2.2.1 開啟 AWS API  Gateway console。(同步驟 2.1.1 - 2.1.2)
2.2.2 選擇 SPEKEReferenceAPI > /copyProtection > POST 方法 > 按下右邊 client [TEST] Link,將以下的文字貼在 Header 的部分。
Host:<your API ID>.execute-api.us-east-1.amazonaws.com
2.2.3 在"Request Body" 的部分貼上以下的內容。然後按下  [Test]。
<?xml version="1.0" encoding="UTF-8"?>
<cpix:CPIX id="5E99137A-BD6C-4ECC-A24D-A3EE04B4E011"
    xmlns:cpix="urn:dashif:org:cpix"
    xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc"
    xmlns:speke="urn:aws:amazon:com:speke">
    <cpix:ContentKeyList>
        <cpix:ContentKey kid="6c5f5206-7d98-4808-84d8-94f132c1e9fe"></cpix:ContentKey>
    </cpix:ContentKeyList>
    <cpix:DRMSystemList>
        <cpix:DRMSystem kid="6c5f5206-7d98-4808-84d8-94f132c1e9fe" systemId="81376844-f976-481e-a84e-cc25d39b0b33">
            <cpix:ContentProtectionData />
            <speke:KeyFormat />
            <speke:KeyFormatVersions />
            <speke:ProtectionHeader />
            <cpix:PSSH />
            <cpix:URIExtXKey />
        </cpix:DRMSystem>
    </cpix:DRMSystemList>
    <cpix:ContentKeyPeriodList>
        <cpix:ContentKeyPeriod id="keyPeriod_e64248f6-f307-4b99-aa67-b35a78253622" index="11525"/>
    </cpix:ContentKeyPeriodList>
    <cpix:ContentKeyUsageRuleList>
        <cpix:ContentKeyUsageRule kid="6c5f5206-7d98-4808-84d8-94f132c1e9fe">
            <cpix:KeyPeriodFilter periodId="keyPeriod_e64248f6-f307-4b99-aa67-b35a78253622"/>
        </cpix:ContentKeyUsageRule>
    </cpix:ContentKeyUsageRuleList>
</cpix:CPIX>

2.2.4 此時你會得到一個回應在右側,然後查看 Response Body 的內容即可看到編碼過後的密鑰值。
<pskc:PlainValue>mkwV0dh7PL2xQJ15uq9HtQ==</pskc:PlainValue>



步驟三、設定 SPEKE 參考服務器到 AWS Elemental MediaPackage

在此步驟你將可以使用我們在這邊部署的 SPEKE 服務器在現有的 AWS Elemental MediaPackage 頻道上建立 HLS 的加密端點。
但,在此之前你需要先設定好一個完整的 AWS Elemental MediaLive 和 MediaPackage 媒體工作流,你可以參考這篇 Blog 的教學: https://aws.amazon.com/tw/events/taiwan/techblogs/articles-Live_Streaming/

Note: 請注意你的編碼器 (MediaLive) ,打包器 (MediaPackage) 和 SPEKE 服務器應該要位於同一個區域或是盡可能相近的位置以減少密鑰生成中的請求/回應的延遲。

預先所需要的資訊
* MediaPackage 頻道的 Channel ID
* Cloudformation 所以建立出來的 MediaPackageInvokeSPEKERole
* 線上直播時新的密鑰替換的間隔秒數
* SPEKE服務器的 URL
3.1 開啟 AWS Elemental MediaPackage console。
3.2 在左邊的版面選擇 [Channels] 選擇既有或是重新創建一個新的頻道。
3.3 然後點選這個既有或是新建的頻道找到 “Endpoints” 的分類 > 點選 [Add/edit endpoints]。
3.4 進入Endpoints的編輯頁面後選擇新增 [Add] 一個新的端點。ID 的部分我們填上 hls。
 
3.5 滾動到下方的設定找到 “Package encryption” 的分類,選擇 “Encypt content”。Resource ID 的部分你可以選擇使用 UUID 或是 GUID 任何合法的字串。System ID 則可以輸入以下字串:
81376844-f976-481e-a84e-cc25d39b0b33
System ID 是 DASH-IF CPIX 標準的一部分,我們已將其套用於密鑰交換協議。 它定義了 DRM 系統。System ID 是為了 DASH Widevine,DASH PlayReady等 DRM 系統定義出來的。 當你需要設置自己的 HLS DRM 解決方案時,您可以在端點上配置任何內容,只要您的密鑰服務器知道如何處理即可

3.6 URL 的部分我們填上先前部署好的 SKPEKE服務器的 API Gateway URL 並加上 /EkeStage/copyProtection, 如下:
https://<your API ID>.execute-api.us-west-2.amazonaws.com/EkeStage/copyProtection
3.7 RoleARN 的部分我們填上在先前 Cloudformation所創建的 MediaPackageInvokeSPEKERole (參考步驟 1.9)。
3.8 展開 Additional configuration 的部分,“Encryption method” 這邊選用 “AES-128”。並且將 Key rotaion interval (sec) 設定成 60 秒。然後儲存。

現在應該已經可以對輸出的影片進行加密(您可以通過下載撥放清單進行檢查)。 你可以把端點在 Mac 上的 Safari 瀏覽器和Quicktime 撥放器上播放。

HLS 播放清單檢查
加密過後的 HLS 播放清單可以在 EXT-X-KEY 的標籤中找到包含一個或多段的密鑰檢索訊息。
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-TARGETDURATION:7
#EXT-X-MEDIA-SEQUENCE:9922
#EXT-X-KEY:METHOD=AES-128,URI="https://d33vycj6dbbmzj.cloudfront.net/
7e4de17c-a065-4ce8-874f-f3ed68c5c5f1/f50e4740-d16e-4374-a2e5-4f43134b3cf2"
#EXTINF:6.006,
index_9_9922.ts?m=1524544797
#EXTINF:6.006,
index_9_9923.ts?m=1524544797
#EXTINF:6.006,
index_9_9924.ts?m=1524544797
#EXTINF:6.006,
index_9_9925.ts?m=1524544797
#EXTINF:6.006,
index_9_9926.ts?m=1524544797
#EXTINF:6.006,
index_9_9927.ts?m=1524544797
#EXTINF:6.006,
index_9_9928.ts?m=1524544797
#EXTINF:6.006,
index_9_9929.ts?m=1524544797
#EXT-X-KEY:METHOD=AES-128,URI="https://d33vycj6dbbmzj.cloudfront.net/
7e4de17c-a065-4ce8-874f-f3ed68c5c5f1/62e65271-1e30-4e0d-aed5-06a947028d99"
#EXTINF:6.006,
index_9_9930.ts?m=1524544797

播放加密影片
您可以使用以下方式播放 AES-128 加密的 HLS 端點:

*在 MediaPackage console 中點開剛剛創建好的加密 HLS 端點。 
*單擊 HLS 端點的預覽。


[此方案的限制及注意事項]

* 該解決方案僅支持以下 DRM 技術的密鑰建立:Widevine 和 Playready
* 如果使用 Apple Fairplay System ID,則此解決方案將只會發送空白的 CPIX 回應。
* 此解決方案僅支持 contentProtection 方法來處理參考服務器解決方案與媒體服務之間的通信。 用戶必須實現copyProtectionData 方法才能處理客戶端/播放器對內容進行解密的請求。
* 如果你的加密對象是 DASH,您需要許可證服務器 (License Server) 和其他架構搭配才能獲得完整的解決方案。 對於 HLS, 用戶可以使用 Simple-AES 加密,僅需要 SPEKE 服務器和打包程序,例如使用 AWS Elemental MediaPackage。 您可以使用兼容的 HLS播放器播放加密的串流。

也請注意此解決方案僅提供概念驗證 (PoC) 而非實際線上產品可以直接套用。此方案的 DRM 服務器也屬於模擬的靜態加密。

實現到線上產品的架構圖如下,用戶會需要實作數位版權管理 (DRM) 系統,或亦也可參考 Amazon 合作夥伴提供適用於 SPEKE 的第三方 DRM 平台實作解決方案[*] 搭配實作。


[參考資料]




  • 免費註冊AWS帳號

    數百萬名客戶正使用 AWS 雲端解決方案建立提升彈性、可擴展性、安全性和可靠性的應用程式,歡迎探索各類免費方案在 AWS 上進行建置。

    免費註冊>>

  • 與我們聯絡

    遇到問題?不管是架構設計、架構優化、效能提升等等,都竭誠歡迎你/妳聯絡 AWS 的雲端業務!

    留下資料 >>

  • 與專人線上對談

    有任何新專案的想法,想要評估使用 AWS 服務,或目前在使用上需要原廠協助之處,都可以跟我們聊聊!

    開啓對話>>