簡介
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 的取證水印解決方案:
-
客戶視頻雲賬號:
- 確保客戶的帳戶已啟用動態交付。
- 開啟客戶支援票證以啟用客戶的帳戶進行鑑識浮水印功能;這是 Video Cloud 的付費附加元件。
- 客戶將從 NAGRA 獲得他們的許可證密鑰。
- 客戶將生成一個公私密鑰對,供取證水印令牌 (WMT) 使用並由 CDN 解密。有關示例,請參閱以下部分。
- 客戶將使用 NAGRA 提供的腳本生成取證水印令牌 (WMT)。
- 從客戶那裡,請求將水印令牌 (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");
支持的功能和限制
如需使用「鑑識浮水印」時支援的功能和限制清單,請參閱概觀:法醫浮水印文件。