PHP 视频源文件加密方案
先说下原理:因为视频是付费的,肯定需要作视频加密处理。
加密可实现的方式:修改视频字节流,只能替换字节流,例如头100-1024字节进行加密,源文件就无法打开了。
下面上代码吧,加解密是
openssl_encrypt
openssl_decrypt
<?php
/**
*
* Created by PhpStorm.
* User: js
* Date: 2021/04/15
* Time: 17:03
* PhpStorm
*/ namespace CoreModel\Payfilms; class Movie{
const KEY = 'jiangsheng';
const METHOD = 'des-ecb'; static function movieModify($filename){
$strLong = mt_rand(1,9);
$str = self::randStr($strLong); // 字符串占位
$key = self::randStr(6); // key
$Pkey = base64_encode($key);
$fp = fopen($filename, 'r+') or die('文件打开失败!');
$bin = fread($fp, $strLong); //随机
$passStr = self::_encrypt($bin,$key); // 密文头 转存 // 判断是否是小写字母组成 $i = 0;
while (!feof($fp)) {
//修改第二行数据
if ($i == 0) {
fseek($fp, 0);// 移动文件指针至偏移量处
fwrite($fp, $str);
break;
}
fgets($fp);
$i++;
}
fclose($fp);
return [
'key'=>$key,
'Pkey'=>$Pkey,
'passStr'=>$passStr,
'str'=>$str,
'bin'=>$bin
];
} static function movieReduction($filename, $passStr, $Pkey){
$fp = fopen($filename, 'r+') or die('文件打开失败!');
$key = base64_decode($Pkey);
$str = self::_decrypt($passStr,$key);
$i = 0;
while (!feof($fp)) {
//修改第二行数据
if ($i == 0) {
fseek($fp, 0);// 移动文件指针至偏移量处
fwrite($fp,$str);
break;
}
fgets($fp);
$i++;
}
fclose($fp);
return true;
}
static function handOpen($filename){
$fp = fopen($filename, 'r') or die('文件打开失败!');
$content = fread($fp, filesize($filename));
return $content;
} static function _encrypt($data, $key=self::KEY, $method=self::METHOD){
return openssl_encrypt($data, $method, $key);
} static function _decrypt($data, $key=self::KEY, $method=self::METHOD){
return openssl_decrypt($data, $method, $key);
} static function authcode($string,$key='',$operation=false,$expiry=0){
$ckey_length = 4;
$key = md5($key ? $key : self::KEY);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation? substr($string, 0, $ckey_length):substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$string = $operation? base64_decode(substr($string, $ckey_length)) :
sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation) {
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) &&
substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
return $keyc.str_replace('=', '', base64_encode($result));
}
} static function randStr($randLength = 6, $addtime = 0, $includenumber = 0)
{
if ($includenumber) {
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQEST123456789';
} else {
$chars = 'abcdefghijklmnopqrstuvwxyz';
}
$len = strlen($chars);
$randStr = '';
for ($i = 0; $i < $randLength; $i++) {
$randStr .= $chars[mt_rand(0, $len - 1)];
}
$tokenvalue = $randStr;
if ($addtime) {
$tokenvalue = $randStr . time();
}
return $tokenvalue;
}
}
// 批量加密
function index(){
ini_set('max_execution_time', 0);//秒为单位,自己根据需要定义
set_time_limit(0);
// $code = $this->arguments['code'];
// $sta = $this->arguments['sta'];
// $end = $this->arguments['end'];
// var_dump($code,$sta,$end);
// echo $res = Movies::_encrypt('123');
// echo $res = Movies::_decrypt($res); $moviePath = FCPATH.'movie'.DIRECTORY_SEPARATOR; // 视频目录
$data = [
['ID'=>1,'VideoFile'=>'huzongdieying.zip'],
['ID'=>2,'VideoFile'=>'27000084-bstg.mp4']
]; $obj = new FilmFiles();
foreach($data as $key=>$val){
$filePath = $moviePath.$val['VideoFile']; $res = Movies::movieModify($filePath);
if($res){
$where = ['ID'=>$val['ID']];
$info = [
'EncryptType'=>3,
'SecretKey'=>$res['Pkey'],
'SecretEncrypt'=>$res['passStr']
];
$sta = $obj->updateLine($where,$info);
var_dump($res,$sta);
}
}
}
// 批量解密
function indexOut(){
ini_set('max_execution_time', 0);//秒为单位,自己根据需要定义
set_time_limit(0);
$moviePath = FCPATH.'movie'.DIRECTORY_SEPARATOR;
$data = [
['ID'=>1,'VideoFile'=>'a.mkv'],
['ID'=>2,'VideoFile'=>'b.mkv']
]; $obj = new FilmFiles();
$where = ['ID'=>1,'ID'=>2];
$data = $obj->getList(); foreach($data as $val){
$filePath = $moviePath.$val->VideoFile; $res = Movies::movieReduction($filePath, $val->SecretEncrypt, $val->SecretKey);
if($res){
$where = ['ID'=>$val->ID];
$info = [
'EncryptType'=>0,
'SecretKey'=>'',
'SecretEncrypt'=>''
];
$sta = $obj->updateLine($where,$info);
var_dump($res,$sta);
} }
}
以下是数据库类,可以参考
<?php
/*
* js
* Time 14:26
* File FilmFiles.php
* 数据库Model处理数据更改
*/ namespace CoreModel\Payfilms; use Config\Database; class FilmFiles
{
//Model Path: CoreModel/Payfilms
protected $db;
protected $bld;
public $Total = 0; public function __construct()
{
$connect = Database::connect();
$this->db = &$connect;
$this->bld = $this->db->table($this->Table);
} private $Table = "payfilm_file";
public $SelectFields = "ID,`DoubanID` ,`VideoFile` ,`VideoSize` ,`VideoMD5` ,`TorrentFile` ,`TorrentMD5` ,`FrameType` ,`Ratio` ,`Bitrate` ,`Format` ,`Acoustics` ,`SoundChannel` ,`EncryptType` ,`SecretKey` ,`SecretEncrypt`"; function getCount($where = [])
{
$this->bld->select("count(ID) as Total");
if (isset($where["limit"])) {
unset($where["limit"]);
}
$this->where($where);
$res = $this->bld->get()->getResultArray();
log_message("debug", "CoreModel/Payfilms/FilmFiles ->getCount \nSQL: " . $this->db->getLastQuery());
return $res[0]["Total"];
} function where($where)
{
foreach ($where as $k => $v) {
switch ($k) {
case "ID":
$this->bld->where("ID", $v);
break;
case "DoubanID":
$this->bld->where("DoubanID", $v);
break;
case "VideoFile":
$this->bld->where("VideoFile", $v);
break;
case "VideoSize":
$this->bld->where("VideoSize", $v);
break;
case "VideoMD5":
$this->bld->where("VideoMD5", $v);
break;
case "TorrentFile":
$this->bld->where("TorrentFile", $v);
break;
case "TorrentMD5":
$this->bld->where("TorrentMD5", $v);
break;
case "FrameType":
$this->bld->where("FrameType", $v);
break;
case "Ratio":
$this->bld->where("Ratio", $v);
break;
case "Bitrate":
$this->bld->where("Bitrate", $v);
break;
case "Format":
$this->bld->where("Format", $v);
break;
case "Acoustics":
$this->bld->where("Acoustics", $v);
break;
case "SoundChannel":
$this->bld->where("SoundChannel", $v);
break;
case "EncryptType":
$this->bld->where("EncryptType", $v);
break;
case "SecretKey":
$this->bld->where("SecretKey", $v);
break;
case "SecretEncrypt":
$this->bld->where("SecretEncrypt", $v);
break;
case "operator":
foreach ($v as $a => $b) {
if (array_key_exists(0, $b)) {
$this->bld->where($a . $b[0], $b[1]);
continue;
}
foreach ($b as $n => $m) {
$this->bld->where($a . $n, $m);
}
}
break;
case "between":
foreach ($v as $a => $b) {
$this->bld->where($a . ">=", $b[0]);
$this->bld->where($a . "<=", $b[1]);
}
break;
case "order_by":
foreach ($v as $a => $b) {
$this->bld->orderBy($a, $b);
}
break;
case "not_in":
foreach ($v as $a => $b) {
$this->bld->whereNotIn($a, $b);
}
break;
case "like":
foreach ($v as $a => $b) {
$this->bld->like($a, $b);
}
case "limit":
$this->bld->limit($v, isset($where["offset"]) ? $where["offset"] : 0);
break;
}
}
} function getList($where = [])
{
$this->bld->select($this->SelectFields);
$this->where($where);
$this->Total = $this->bld->countAllResults(false);
$res = $this->bld->get()->getResult();
log_message("debug", "CoreModel/Payfilms/FilmFiles->getList \nSQL: " . $this->db->getLastQuery());
if (count($res) > 0) {
return $res;
}
return false;
} function updateLine($where, $info)
{ $this->where($where);
$data = [];
foreach ($info as $k => $v) {
switch ($k) {
case "DoubanID":
$data["DoubanID"] = $v;
break;
case "VideoFile":
$data["VideoFile"] = $v;
break;
case "VideoSize":
$data["VideoSize"] = $v;
break;
case "VideoMD5":
$data["VideoMD5"] = $v;
break;
case "TorrentFile":
$data["TorrentFile"] = $v;
break;
case "TorrentMD5":
$data["TorrentMD5"] = $v;
break;
case "FrameType":
$data["FrameType"] = $v;
break;
case "Ratio":
$data["Ratio"] = $v;
break;
case "Bitrate":
$data["Bitrate"] = $v;
break;
case "Format":
$data["Format"] = $v;
break;
case "Acoustics":
$data["Acoustics"] = $v;
break;
case "SoundChannel":
$data["SoundChannel"] = $v;
break;
case "EncryptType":
$data["EncryptType"] = $v;
break;
case "SecretKey":
$data["SecretKey"] = $v;
break;
case "SecretEncrypt":
$data["SecretEncrypt"] = $v;
break;
}
}
$this->bld->update($data);
log_message("debug", "CoreModel/Payfilms/FilmFiles->updateLine \nSQL: " . $this->db->getLastQuery());
if ($this->db->affectedRows() > 0) {
return true;
}
return false;
} function deleteLine($where)
{
$this->where($where);
$this->bld->delete();
log_message("debug", "CoreModel/Payfilms/FilmFiles->deleteLine \nSQL: " . $this->db->getLastQuery());
if ($this->db->affectedRows() > 0) {
return true;
}
return false;
} function insertLine($info)
{
$data = [
"DoubanID" => $info["DoubanID"],
"VideoFile" => $info["VideoFile"],
"VideoSize" => $info["VideoSize"],
"VideoMD5" => $info["VideoMD5"],
"TorrentFile" => $info["TorrentFile"],
"TorrentMD5" => $info["TorrentMD5"],
"FrameType" => $info["FrameType"],
"Ratio" => $info["Ratio"],
"Bitrate" => $info["Bitrate"],
"Format" => $info["Format"],
"Acoustics" => $info["Acoustics"],
"SoundChannel" => $info["SoundChannel"],
"EncryptType" => $info["EncryptType"],
"SecretKey" => $info["SecretKey"],
"SecretEncrypt" => $info["SecretEncrypt"],
];
$this->bld->insert($data);
log_message("debug", "CoreModel/Payfilms/FilmFiles->insertLine \nSQL: " . $this->db->getLastQuery());
if ($this->db->affectedRows() > 0) {
return $this->db->insertID();
} return false;
} function updateByID($ID, $info)
{
return $this->updateLine(["ID" => $ID], $info);
} function getItemByID($ID)
{
$res = $this->getList(["ID" => $ID]);
if (is_array($res)) {
return $res[0];
}
return false;
} function deleteByID($DoubanID)
{
return $this->deleteLine(["DoubanID" => $DoubanID]);
} function getListByDouban($DoubanID, $Ext = [])
{
$where = ["DoubanID" => $DoubanID];
$where = array_merge($where, $Ext);
$res = $this->getList($where);
if (is_array($res)) {
return $res;
}
return false;
} function deleteByDouban($DoubanID)
{
return $this->deleteLine(["DoubanID" => $DoubanID]);
}
}
PHP 视频源文件加密方案的更多相关文章
- lua 代码加密方案
require 实现 require函数在实现上是依次调用package.searchers(lua51中是package.loaders)中的载入函数,成功后返回.在loadlib.c文件里有四个载 ...
- 如何保护你的 Python 代码 (一)—— 现有加密方案
https://zhuanlan.zhihu.com/p/54296517 0 前言 去年11月在PyCon China 2018 杭州站分享了 Python 源码加密,讲述了如何通过修改 Pytho ...
- Atitit.视频文件加密的方法大的总结 java c# php
Atitit.视频文件加密的方法大的总结 java c# php 1. 加密的算法 aes 3des des xor等.1 2. 性能1 3. 解密1 4. 播放器的事件扩展1 5. 自定义格式 ...
- 一个异或加密方案--C语言实现
核心代码: char encrypt( char f , char c) { return f^c; } int OutEncrypt( char *FilePath, char *SecretWor ...
- C# .net 语言加密方案
C# .net 语言加密方案 方案背景 当前C# .net语言的应用范围越来越广泛,IIS 的服务器架构后台代码.桌面应用程序的 winform .Unity3d 的逻辑脚本都在使用.C# .net ...
- 基于HTTP在互联网传输敏感数据的消息摘要、签名与加密方案
基于HTTP在互联网传输敏感数据的消息摘要.签名与加密方案 博客分类: 信息安全 Java 签名加密AESMD5HTTPS 一.关键词 HTTP,HTTPS,AES,SHA-1,MD5,消息摘要,数 ...
- 网络摄像机进行互联网视频直播录像方案的选择,EasyNVS or EasyCloud or EasyGBS?
背景需求 互联网视频直播越来越成为当前大势:直播的需求往往都伴随在录像的需求,对于录像,不同的场景又有不同的方案选择: 本篇博客将会介绍对应的几种录像方案,可以帮助有互联网录像需求的用户进行对应的录像 ...
- [原创]aaencode等类似js加密方案破解方法
受http://tieba.baidu.com/p/4104806767 2L启发,不过他说的方法,我没有尝试成功,自己摸索出了一个新方法,在这里分享下. 首先拿aaencode官网的加密字符串作为例 ...
- nginx视频服务缓存方案设置指导
本文描述了如何通过设置nginx缓存达到降低服务器后端压力的效果以及结合nginx第三方插件ngx_cache_purge实现nginx缓存后的自动清理功能.具体实施步骤如下所示:第一步:获取清除清除 ...
- 基于RSA的WEB前端密码加密方案
受制于WEB页面源码的暴露,因此传统的对称加密方案以及加密密钥都将暴露在JS文件中,同样可以被解密. 目前比较好的解决方案是WEB页面全程或用户登录等关键环节使用HTTPS进行传输. 另外一种解决方案 ...
随机推荐
- PostgreSQL 选择数据库
数据库的命令窗口 PostgreSQL 命令窗口中,我们可以命令提示符后面输入 SQL 语句: postgres=# 使用 \l 用于查看已经存在的数据库: postgres=# \l List of ...
- typescript中对象属性可选属性与只读属性与索引签名
可选属性 type类型别名 type 会给一个类型起个新名字. type 有时和 interface 很像,但是可以作用于原始值(基本类型),联合类型,元组以及其它任何你需要手写的类型. interf ...
- 在 WPF 中实现融合效果
1. 融合效果 融合效果是指对两个接近的元素进行高斯模糊后再提高对比度,使它们看上去"粘"在一起.在之前的一篇文章中,我使用 Win2D 实现了融合效果,效果如下: 不过 Win2 ...
- Linux shell猜数游戏
题目:猜随机数随机1-100中的一个数字,要求用户猜数字,猜中则退出脚本并告知用户猜测次 数和随机数字,否则要求用户继续猜,并告知当前猜的数字和随机数的关系. #!/bin/bash #猜数游戏 Ra ...
- Android自动化测试工具调研
原文地址:Android自动化测试工具调研 - Stars-One的杂货小窝 Android测试按测试方式分类,可分为两种:一种是传统逻辑单元测试(Junit),另外一种则是UI交互页面测试. 这里详 ...
- java 新特性之 Stream API
强大的 Stream API 一.Stream API 的概述 Stream到底是什么呢? 是数据渠道,用于操作数据源(集合.数组等)所生成的元素序列. "集合讲的是数据,Stream讲的是 ...
- 七、docker镜像私有仓库
在Docker中,当我们执行 docker pull xxx 的时候 ,它实际上是从 hub.docker.com 这个地址去查找,这就是 Docker 公司为我们提供的公共仓库.在工作中,我们不可能 ...
- 云原生之旅 - 6)不能错过的一款 Kubernetes 应用编排管理神器 Kustomize
前言 相信经过前一篇文章的学习,大家已经对Helm有所了解,本篇文章介绍另一款工具 Kustomize,为什么Helm如此流行,还会出现 Kustomize?而且 Kustomize 自 kubect ...
- RHCE习题
RHCE习题 考试说明: RH294系统信息 在练习期间,您将操作下列虚拟系统: 真实机: foundation: kiosk:redhat root: Asimov workstation.lab. ...
- Go map 竟然也会发生内存泄露?
Go 程序运行时,有些场景下会导致进程进入某个"高点",然后就再也下不来了. 比如,多年前曹大写过的一篇文章讲过,在做活动时线上涌入的大流量把 goroutine 数抬升了不少,流 ...