使用 Beacon Apps 取證水印

在本主題中,您將學習如何使用 Beacon 應用程序實施取證水印。

簡介

Brightcove 與 NAGRA合作,通過 Beacon 應用程序提供法證水印,以幫助保護優質內容免受盜版和未經授權的內容共享。使用此功能,客戶將能夠識別內容洩漏的來源並採取適當的措施。

下圖顯示了一個概覽:

  • 內容準備
    • Forensic Watermark 是在使用 Nagra 的 SDK 轉碼期間嵌入到視頻中的不可見水印
    • Ingestion 創建了 2 個 VOD 再現,一個帶有水印 A,另一個帶有水印 B;兩種演繹都是 Video Cloud 中同一標題的一部分
  • 送貨
    • 播放內容時,Forensic Watermark 令牌會提供給播放器,然後包含在用於從 CDN 請求內容的 URL 中
    • CDN 解釋令牌並將具有正確 A/B 片段序列的視頻傳送給觀眾
概覽圖
取證水印概述

需求

支持此功能需要滿足以下要求:

  • Beacon 應用需要使用 OIDC 認證
  • 僅適用於 VOD 資產
  • 不會為帶水印的視頻生成 MP4 演繹版

設定

需要以下設置來支持 Brightcove 的取證水印解決方案:

  1. 客戶視頻雲賬號:
    • 確保客戶的帳戶已啟用動態交付。
    • 開啟客戶支援票證以啟用客戶的帳戶進行鑑識浮水印功能;這是 Video Cloud 的付費附加元件。
  2. 客戶將從 NAGRA 獲得他們的許可證密鑰
  3. 客戶將生成一個公私密鑰對,供取證水印令牌 (WMT) 使用並由 CDN 解密。有關示例,請參閱以下部分。
  4. 客戶將使用 NAGRA 提供的腳本生成取證水印令牌 (WMT)。
  5. 從客戶那裡,請求將水印令牌 (WMT) 傳遞給應用程序的聲明的名稱。與 Beacon 團隊分享此聲明,以便他們可以在 Beacon Master CMS 中對其進行配置。

生成公私鑰對

有很多方法可以產生公開私密金鑰組。以下是一些範例:

例如 bash 腳本:

產生金鑰配對的範例指令碼:

#!/bin/bash
set -euo pipefail

NAME=${1:-}
test -z "${NAME:-}" && NAME="brightcove-forensic-watermarking-key-$(date +%s)"
mkdir "$NAME"

PRIVATE_PEM="./$NAME/private.pem"
PUBLIC_PEM="./$NAME/public.pem"
PUBLIC_TXT="./$NAME/public_key.txt"

ssh-keygen -t rsa -b 2048 -m PEM -f "$PRIVATE_PEM" -q -N ""
openssl rsa -in "$PRIVATE_PEM" -pubout -outform PEM -out "$PUBLIC_PEM" 2>/dev/null
openssl rsa -in "$PRIVATE_PEM" -pubout -outform DER | base64 > "$PUBLIC_TXT"

rm "$PRIVATE_PEM".pub

echo "Public key to saved in $PUBLIC_TXT"

執行指令碼:

$ bash keygen.sh
使用示例Go

使用Go編程語言生成密鑰對的示例:

package main
  
  import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/base64"
    "encoding/pem"
    "flag"
    "fmt"
    "io/ioutil"
    "os"
    "path"
    "strconv"
    "time"
  )
  
  func main() {
    var out string
  
    flag.StringVar(&out, "output-dir", "", "Output directory to write files into")
    flag.Parse()
  
    if out == "" {
      out = "rsa-key_" + strconv.FormatInt(time.Now().Unix(), 10)
    }
  
    if err := os.MkdirAll(out, os.ModePerm); err != nil {
      panic(err.Error())
    }
  
    priv, err := rsa.GenerateKey(rand.Reader, 2048)
    if err != nil {
      panic(err.Error())
    }
  
    privBytes := x509.MarshalPKCS1PrivateKey(priv)
  
    pubBytes, err := x509.MarshalPKIXPublicKey(priv.Public())
    if err != nil {
      panic(err.Error())
    }
  
    privOut, err := os.OpenFile(path.Join(out, "private.pem"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
    if err != nil {
      panic(err.Error())
    }
  
    if err := pem.Encode(privOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: privBytes}); err != nil {
      panic(err.Error())
    }
  
    pubOut, err := os.OpenFile(path.Join(out, "public.pem"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
    if err != nil {
      panic(err.Error())
    }
  
    if err := pem.Encode(pubOut, &pem.Block{Type: "PUBLIC KEY", Bytes: pubBytes}); err != nil {
      panic(err.Error())
    }
  
    var pubEnc = base64.StdEncoding.EncodeToString(pubBytes)
  
    var pubEncOut = path.Join(out, "public_key.txt")
    if err := ioutil.WriteFile(pubEncOut, []byte(pubEnc+"\n"), 0600); err != nil {
      panic(err.Error())
    }
  
    fmt.Println("Public key saved in " + pubEncOut)
  }
  

使用 node.js 的範例

使用 node.js 生成密鑰對的示例:

var crypto = require("crypto");
  var fs = require("fs");
  
  var now = Math.floor(new Date() / 1000);
  var dir = "rsa-key_" + now;
  fs.mkdirSync(dir);
  
  crypto.generateKeyPair(
    "rsa",
    {modulusLength: 2048},
    (err, publicKey, privateKey) => {
      fs.writeFile(
        dir + "/public.pem",
        publicKey.export({ type: "spki", format: "pem" }),
        err => {}
      );
      fs.writeFile(
        dir + "/public_key.txt",
        publicKey.export({ type: "spki", format: "der" }).toString("base64") +
          "\n",
        err => {}
      );
      fs.writeFile(
        dir + "/private.pem",
        privateKey.export({ type: "pkcs1", format: "pem" }),
        err => {}
      );
    }
  );
  
  console.log("Public key saved in " + dir + "/public_key.txt");

支持的功能和限制

如需使用「鑑識浮水印」時支援的功能和限制清單,請參閱概觀:法醫浮水印文件。