使用加密锁加密Unity工程插件源码

最近在unity3D中开发了一款插件,需要卖给客户,但是公司需要隐藏插件的源码,而且保证客户只有指定的电脑才能使用该插件开发!
	针对这个问题,分为两个步骤:1.隐藏插件源码,将插件源码编译成dll;2.使用加密锁加密源码。
	1.将Unity3d代码编译成dll
	在VS中创建一个C#类库工程,添加引用,引用Unity3d的类库UnityEditor.dll 和 UnityEngine.dll,本机它们的地址在D:\Program Files (x86)\Unity\Editor\Data\Managed。

unity 通过mono 加密android 程序 unity源码加密_3d

创建C#类库工程

unity 通过mono 加密android 程序 unity源码加密_unity3d_02


unity 通过mono 加密android 程序 unity源码加密_System_03

引用Unity3d的dll新建一个class,将unity3d的C#脚本复制粘贴到这个class中,注意,这个类是有命名空间的,在unity3d中调用这个dll的函数需要引用命名空间。

unity 通过mono 加密android 程序 unity源码加密_System_04

unity 通过mono 加密android 程序 unity源码加密_命名空间_05

在Class1类中继承MonoBehaviour,在Update函数中打印,测试能否将该类挂在在unity的GameObject上,再写一个函数测试是否能被unity的C#脚本正常调用。

unity 通过mono 加密android 程序 unity源码加密_3d_06

将解决方案配置改为Release,然后编译,则会生成dll

unity 通过mono 加密android 程序 unity源码加密_3d_07

unity 通过mono 加密android 程序 unity源码加密_命名空间_08

在unity工程中新建Plugins文件夹,将DllTest粘贴到该文件夹。

unity 通过mono 加密android 程序 unity源码加密_unity3d_09


打开unity工程,再场景中拖入一个GameObject,将脚本Class1挂载上去。

unity 通过mono 加密android 程序 unity源码加密_unity3d_10

在unity工程中新建脚本TestDll,引用命名空间DllTest,调用Class1的函数,将脚本挂载载GameObject上,运行。

unity 通过mono 加密android 程序 unity源码加密_3d_11

通过打印可判断我们已经成功的将Dll的Class1挂载在unity场景中的GameObject,并能成功调用Class1的公有函数。

2.使用加密锁加密源码
一开始直接使用Gemalto超级狗,希望直接加密Dll(这种方式载UE4可用),从安装它们的软件,到最后加密成功,花了2天的时间,最后在unity中测试,发现即使插上了超级狗还是不能正常使用,问了厂家后说不支持unity编辑器中的dll,暂不知道原因,为了解决问题,在京东搜索其他品牌的,也都说不支持unity编辑器中的dll,但是域天加密锁厂家给我提供了一个方案,就是加密源码,解决了我的问题,为了表示感谢,在博客里帮忙宣传一下。

unity 通过mono 加密android 程序 unity源码加密_unity3d_12

使用域天厂家提供的工具YTTool,会生成一个密钥和对应的SoftKey.cs代码,密钥可设置给加密锁硬件,具体方法厂家会提供,这里详细描述一下如何使用SoftKey.cs加密源码。

在步骤1中的类库工程中添加一个类命名未SoftLock,将SoftKey中的代码复制粘贴上去,在新建一个单例类命名未SoftKeyManager用来管理加密锁功能。

using System;
using UnityEngine;
using System.Runtime.InteropServices;


namespace WindowsApplication1
{
    public class SoftLockManager
    {
        private static SoftLockManager instance = null;
        private SoftLockManager()
        {
            ytsoftkey = new SoftKey();
            //CheckSoftLock(true);
        }

        public static SoftLockManager Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new SoftLockManager();
                }
                return instance;
            }
        }


        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

        public const int WM_SYSCOMMAND = 0x0112;


        public const int SC_CLOSE = 0xF060;

        private bool isCheckedSoftLock = true;
        public bool GetIsCheckedSoftLock
        {
            get { return isCheckedSoftLock; }
        }

        SoftKey ytsoftkey;

        public bool CheckSoftLock(bool isShowMessage)
        {

            if (Application.platform == RuntimePlatform.WindowsPlayer)
            {
                isCheckedSoftLock = true;
            }
            else
            {
                if (ytsoftkey.CheckKeyByFindort_2() == 0)
                {
                    isCheckedSoftLock = true;
                }
                else
                {
                    if (isShowMessage)
                    {
                        MessageBox(new IntPtr(0), "检测到未插上加密锁!", "错误", 0);
                    }
                    isCheckedSoftLock = false;
                }
            }

            return isCheckedSoftLock;
        }
    }
}

此类提供了接口去检测是否有加密狗,如果有,则返回true,没有,则弹出提示框,返回false;公司需求需在unity编辑器中加密锁功能启用,打包后不启用,在这里加了一个Application.platform == RuntimePlatform.WindowsPlayer判断,测试在编辑器中运行未false,打包后在windows中运行未true。
ytsoftkey.CheckKeyByFindort_2() == 0是场家提供检测是否插入加密锁,加入返回true,未插入返回false。

此时可在插件的核心代码调用单例类的函数CheckSoftLock(true)进行加密锁检测,返回true则运行代码,返回false则不运行,编译生成新的dll,按照步骤1的操作使用该dll即可。