C#实现对视频AES加密解密算法(对byte[]、string加密)

先了解一下什么是AES加密算法
AES高级加密标准又称在加密学Rijndael加密算法

由美国国家标准与技术协会(NIST)所选的高级加密标准(AES)的候选算法。

AES算是Rijndael算法的一种特殊实现,选的分组为128bit(16字节),密钥可以使用128、192 和 256bit三种,而Rijndael使用的密钥和区块长度可以是32位的整数倍,以128位为下限,256比特为上限。加密过程中使用的密钥是由Rijndael密钥生成方案产生。

AES算法过程是在一个4x4字节矩阵(矩阵称为状态state)上运作,初始值是一个文明区块(矩阵一个元素大小就是文明区块的一个byte),加密时,各轮AES加密循环(最后一轮除外)分四步
1.矩阵中每一个字节都与该次轮秘钥做XOR运算;每个子密钥由密钥生成方案产生。
2.通过非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。
3.将矩阵中的每个横列进行循环式位移
4.为了充分混合矩阵中各个直行的操作。这个步骤使用线性转换来混合每列的四个字节
https://blog.csdn.net/qq_28205153/article/details/55798628
这个是详细还有底层
C#的话封装的有一个RijndaelManaged类我们可以调用使用 然后封装一个类

using UnityEngine;
using System.Collections;
using System;
using System.Security.Cryptography;
using System.Text;
public struct RijndaelKey
{
    public byte[] key;
    public byte[] IV;

    public RijndaelKey(byte[] key, byte[] iV)
    {
        this.key = key;
        IV = iV;
    }
}

public class Rijndael : MonoBehaviour
{
    /// 
    /// Rijndael加密
    /// 
    /// 密文
    /// 密钥
    /// 向量
    /// 
    public byte[] Encrypt(byte[] plainData, byte[] key, byte[] IV)
    {
        if (plainData == null || plainData.Length <= 0)
            throw new ArgumentNullException("video");
        if (key == null || key.Length <= 0)
            throw new ArgumentNullException("Key");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("IV");

        byte[] encrypted;
        //创建RijndaelManaged对象
        //使用指定的键和IV。
        //用完就会被释放
        using (RijndaelManaged rijAlg = new RijndaelManaged())
        {
            rijAlg.Key = key;
            rijAlg.IV = IV;
            //设置对称算法的运算模式
            rijAlg.Mode = CipherMode.ECB;
            //设置填充模式
            rijAlg.Padding = PaddingMode.ISO10126;

            //创建加密程序以执行流转换。
            ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
            encrypted = encryptor.TransformFinalBlock(plainData, 0, plainData.Length);
        }
        //从内存流返回加密的字节。
        return encrypted;
    }
    /// 
    /// 解密
    /// 
    /// 
    /// 
    /// 
    /// 
    public byte[] Decrypt(byte[] cipherData, byte[] key, byte[] IV)
    {
        if (cipherData == null || cipherData.Length <= 0)
            throw new ArgumentNullException("video");
        if (key == null || key.Length <= 0)
            throw new ArgumentNullException("Key");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("IV");

        byte[] decrypted;
        using (RijndaelManaged rijAlg = new RijndaelManaged())
        {
            rijAlg.Key = key;
            rijAlg.IV = IV;
            rijAlg.Mode = CipherMode.ECB;
            rijAlg.Padding = PaddingMode.ISO10126;
            //创建解密程序以执行流转换。
            ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
            decrypted = decryptor.TransformFinalBlock(cipherData, 0, cipherData.Length);
        }
        return decrypted;
    }

    /// 
    /// 创建Key 和IV在某个目录下
    /// 
    /// 
    /// 
    public RijndaelKey CreateKeyAndIV(string path)
    {
        RijndaelManaged rijma = new RijndaelManaged();
        rijma.GenerateKey();
        rijma.GenerateIV();
        FileTools.CreateFile(path + "/keyTxt.txt", rijma.Key);
        FileTools.CreateFile(path + "/IVTxt.txt", rijma.IV);

        return new RijndaelKey(rijma.Key, rijma.IV);
    }

    /// 
    /// 获取Key 和IV
    /// 
    /// 
    /// 
    public RijndaelKey GetKeyAndIV(string path)
    {
        byte[] key = FileTools.ReadFile(path + "/keyTxt.txt");
        byte[] IV = FileTools.ReadFile(path + "/IVTxt.txt");
        return new RijndaelKey(key, IV);
    }
}


这是一个IO读写类

using System.Collections;
using System.IO;

/// 
/// IO读写类
/// 
public class FileTools
{
    /// 
    /// 创建目录文件夹 有就不创建
    /// 
    public static void CreateDirectory(string filePath)
    {
        if (!string.IsNullOrEmpty(filePath))
        {
            if (!File.Exists(filePath))
            {
                Directory.CreateDirectory(filePath);
            }
        }
    }
    /// 
    /// 创建文件
    /// 
    /// 
    /// 
    public static void CreateFile(string filePath, byte[] bytes)
    {
        using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
        {
            fs.Write(bytes, 0, bytes.Length);
        }
    }
    /// 
    /// 读取文件
    /// 
    /// 
    /// 
    public static byte[] ReadFile(string filePath)
    {
        using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            byte[] infbytes = new byte[fs.Length];
            fs.Read(infbytes, 0, infbytes.Length);
            return infbytes;
        }
    }

}

这个是官方对string加密解密的
https://docs.microsoft.com/zh-cn/dotnet/api/system.security.cryptography.cryptostream?redirectedfrom=MSDN&view=netframework-4.8
然后我们要写一个处理视频的工具 在Unity里

using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;
using System.IO;

public class EncryptTools
{
    /// 
    /// 复制一份加密的出来
    /// 
    /// 
    [MenuItem("Tools/EncryptVideo")]
    static void EncryptVideo(MenuCommand cmd)
    {
        //获取选择文件夹的路径
        string[] str = Selection.assetGUIDs;
        string path = AssetDatabase.GUIDToAssetPath(str[0]);
        string newPath = Application.dataPath + "/StreamingAssets/videoNew";
        FileTools.CreateDirectory(newPath);

        //获取指定路径下的指定类型资源
        DirectoryInfo root = new DirectoryInfo(path);
        FileInfo[] files = root.GetFiles("*.mp4");
        Rijndael rij = new Rijndael();
        RijndaelKey rijKey = rij.CreateKeyAndIV(newPath);

        for (int i = 0; i < files.Length; i++)
        {
            byte[] enBytes = rij.Encrypt(FileTools.ReadFile(files[i].FullName), rijKey.key, rijKey.IV);

            string strWriteFile = newPath + "/" + files[i].Name;
            FileTools.CreateFile(strWriteFile, enBytes);
         
            EditorUtility.DisplayProgressBar("进度", i + "/" + files.Length + "完成修改值", (float)i / files.Length);
        }
        EditorUtility.ClearProgressBar();
        AssetDatabase.Refresh();
    }

    /// 
    /// C#获取指定目录下多种指定类型文件
    /// 
    /// 路径
    /// 
    static List GetVideoFiles(string filePath)
    {
        DirectoryInfo di = new DirectoryInfo(filePath);
        FileInfo[] files = di.GetFiles();
        string fileName;
        List list = new List();
        for (int i = 0; i < files.Length; i++)
        {
            fileName = files[i].Name.ToLower();
            if (fileName.EndsWith(".mp4") || fileName.EndsWith(".avi"))
            {
                list.Add(fileName);
            }
        }
        return list;
    }
}

这个放在Editor文件夹下 选中你想加密视频的文件夹 然后点击


image.png

就OK了 会在StreamingAssets/videoNew生成一份加密的视频和key还有向量 之前的没加密的视频还在 然后是只会加密拷贝当前文件夹下的视频 而不是该文件夹下所有子文件夹的视频
因为我用的是avpro 新版本可以直接读byte[]视频
放一个不完整的处理代码 这个可以粘贴到之前的AvProControl那个类里面使用

   private IEnumerator LoadEncryptVideoWithFading(string path)
    {
        string newPath = Application.dataPath + "/StreamingAssets/videoNew";
        path = newPath+"/" + path;     
        
        Rijndael rij = new Rijndael();
       
        RijndaelKey rijKey = rij.GetKeyAndIV(newPath);
        byte[] enBytes = rij.Decrypt(FileTools.ReadFile(path), rijKey.key, rijKey.IV);

        // Wait 3 frames for display object to update
        yield return new WaitForEndOfFrame();
        yield return new WaitForEndOfFrame();
        yield return new WaitForEndOfFrame();
        // Load the video
        if (Application.isPlaying)
        {
            if (!mediaPlayer.OpenVideoFromBuffer(enBytes))
            {
                Debug.LogError("Failed to open video!");
            }
            else
            {
                // Wait for the first frame to come through (could also use events for this)
                while (Application.isPlaying && (VideoIsReady(mediaPlayer) || AudioIsReady(mediaPlayer)))
                {
                    yield return null;
                }
                // Wait 3 frames for display object to update
                yield return new WaitForEndOfFrame();
                yield return new WaitForEndOfFrame();
                yield return new WaitForEndOfFrame();
            }

        }
        duration = mediaPlayer.Info.GetDurationMs();

    }

你可能感兴趣的:(C#实现对视频AES加密解密算法(对byte[]、string加密))