package builder import ( "crypto/rand" "encoding/base64" "fmt" "io" "os" ) const mediaLockMagic = "CMVD" // EncryptMediaFile XOR-encrypts a movie for paired fusion (runner holds the key in manifest). func EncryptMediaFile(srcPath, destPath string, key []byte) error { if len(key) == 0 { return fmt.Errorf("media lock key is empty") } in, err := os.Open(srcPath) if err != nil { return err } defer in.Close() out, err := os.Create(destPath) if err != nil { return err } defer out.Close() if _, err := io.WriteString(out, mediaLockMagic); err != nil { return err } buf := make([]byte, 256*1024) ki := 0 for { n, readErr := in.Read(buf) if n > 0 { chunk := make([]byte, n) for i := 0; i < n; i++ { chunk[i] = buf[i] ^ key[ki%len(key)] ki++ } if _, err := out.Write(chunk); err != nil { return err } } if readErr == io.EOF { break } if readErr != nil { return readErr } } return nil } func NewMediaLockKey() ([]byte, error) { key := make([]byte, 32) if _, err := rand.Read(key); err != nil { return nil, err } return key, nil } func MediaLockKeyB64(key []byte) string { return base64.StdEncoding.EncodeToString(key) }