This commit is contained in:
陈皮皮
2020-08-02 19:19:28 +08:00
parent 1442c38021
commit dc349b6966
8 changed files with 190 additions and 135 deletions

View File

@@ -1,4 +1,12 @@
### 1.0.2.20200530 (当前版本)
### 1.0.3.20200802 (当前版本)
1. 支持 Cocos Creator 2.4.x
2. 去除【需要混淆的文件】选项
3. 代码优化
### 1.0.2.20200530
1. 调整混淆时机(支持 MD5 Cache
2. 配置面板参数添加中文名称

View File

@@ -1,35 +1,49 @@
# 代码混淆工具
### 介绍
## 介绍
[Cocos Creator 编辑器插件] 混淆代码工具支持项目构建后自动混淆代码以及主动混淆目标文件TODO
- 混淆引擎:[javascript-obfuscator@0.28.0](https://github.com/javascript-obfuscator/javascript-obfuscator)
### 截图
如果此项目对你有帮助,请不要忘记 [![star](https://gitee.com/ifaswind/ccc-obfuscated-code/badge/star.svg?theme=dark)](https://gitee.com/ifaswind/ccc-obfuscated-code/stargazers)
![screenshot](https://gitee.com/ifaswind/image-storage/raw/master/ccc-obfuscated-code/screenshot.png)
如有使用上的问题,可以在 gitee 上提 issue 或者添加我的微信 `im_chenpipi` 并留言。
### 运行环境
## 截图
![screenshot](https://gitee.com/ifaswind/image-storage/raw/master/repositories/ccc-obfuscated-code/screenshot.png)
## 环境
平台Windows、Mac
编辑器Cocos Creator 2.x.x理论上通用
引擎Cocos Creator 2.x.x理论上通用
### 插件说明
1. 插件默认禁用
2. 点击 **[ 扩展 --> 代码混淆工具 --> 构建后自动混淆 ]** 启用自动混淆并设置参数
## 说明
3. 配置文件保存路径为 **[ {项目根目录}/local/ccc-obfuscated-code.json ]**
1. 将插件文件夹 `ccc-obfuscated-code` 放置在 `${用户目录}/.CocosCreator/packages` 目录下即可
### 参数说明
3. 本插件默认禁用,需自行启用
2. 点击顶部菜单栏的 **[ 扩展 --> 代码混淆工具 ]** 打开插件配置面板
4. 配置文件存放路径:`${项目目录}/local/ccc-obfuscated-code.json`
## 参数说明
- Javascript Obfuscator 文档:[传送门](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/README.md)
- 以下均为我人工翻译的内容,尽我所能翻译得通俗易懂了。
- 原英文文档:[传送门](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/README.md)
**compact**
@@ -476,15 +490,9 @@
}
```
### 关于
作者陈皮皮ifaswind
公众号:文弱书生陈皮皮
![weixin](https://gitee.com/ifaswind/image-storage/raw/master/weixin/qrcode.png)
### *License*
## *License*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@@ -504,4 +512,28 @@ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
# 菜鸟小栈
我是陈皮皮,这是我的个人公众号,专注但不仅限于游戏开发、前端和后端技术记录与分享。
每一篇原创都非常用心,你的关注就是我原创的动力!
> Input and output.
![](https://gitee.com/ifaswind/image-storage/raw/master/weixin/official-account.png)
## 交流群
皮皮创建了一个游戏开发交流群,供大家交流经验、问题求助等。
感兴趣的小伙伴可以添加我微信 `im_chenpipi` 并留言 `加群`

View File

@@ -0,0 +1 @@
{}

194
main.js
View File

@@ -6,8 +6,8 @@ const configFileDir = 'local/';
const configFileName = 'ccc-obfuscated-code.json';
const defaultConfig = {
auto: false,
files: ['/src/project.js'],
useAbsPath: false,
// extraFiles: [],
// useAbsPath: false,
preset: 'lower',
options: {}
};
@@ -15,78 +15,6 @@ const defaultConfig = {
const presetFileUrl = 'packages://ccc-obfuscated-code/preset.json';
let presets = null;
/**
* 保存配置
* @param {object} config
*/
function saveConfig(config) {
let projectPath = Editor.Project.path || Editor.projectPath;
let configDirPath = Path.join(projectPath, configFileDir);
if (!Fs.existsSync(configDirPath)) Fs.mkdirSync(configDirPath);
let configFilePath = Path.join(configDirPath, configFileName);
// 读取本地配置
let object = {};
if (Fs.existsSync(configFilePath)) {
object = JSON.parse(Fs.readFileSync(configFilePath, 'utf8'));
}
// 写入配置
for (let key in config) object[key] = config[key];
let string = JSON.stringify(object, null, 2);
Fs.writeFileSync(configFilePath, string);
Editor.log('[CC]', '配置文件路径', configFilePath);
}
/**
* 读取配置
*/
function getConfig() {
let projectPath = Editor.Project.path || Editor.projectPath;
let configFilePath = Path.join(projectPath, configFileDir, configFileName);
let config = null;
if (Fs.existsSync(configFilePath)) {
config = JSON.parse(Fs.readFileSync(configFilePath, 'utf8'));
}
if (!config) {
config = JSON.parse(JSON.stringify(defaultConfig));
config.options = getPreset('off');
if (config.preset !== 'off') {
let preset = getPreset(config.preset);
for (let key in preset) {
config.options[key] = preset[key];
}
}
}
return config;
}
/**
* 读取预设参数
* @param {string} type 预设名
*/
function getPreset(type) {
if (presets) return presets[type];
let presetFilePath = Editor.url(presetFileUrl);
if (Fs.existsSync(presetFilePath)) {
presets = JSON.parse(Fs.readFileSync(presetFilePath, 'utf8'));
return presets[type];
}
return null;
}
/**
* 混淆
* @param {string} path 文件路径
* @param {ObfuscatorOptions} options 混淆参数
*/
function obfuscate(path, options) {
let sourceCode = Fs.readFileSync(path, 'utf8');
let obfuscationResult = JavascriptObfuscator.obfuscate(sourceCode, options);
let obfuscatedCode = obfuscationResult.getObfuscatedCode();
Fs.writeFileSync(path, obfuscatedCode);
}
module.exports = {
load() {
@@ -102,25 +30,24 @@ module.exports = {
messages: {
'open-panel'() {
Editor.log('[CC]', '代码混淆工具/构建后自动混淆');
Editor.Panel.open('ccc-obfuscated-code');
},
// TODO
// 'open-panel-do'() {
// Editor.log('[CC] 代码混淆工具/主动混淆');
// Editor.Panel.open('ccc-obfuscated-code-do');
// },
'save-config'(event, config) {
Editor.log('[CC]', '保存配置');
saveConfig(config);
const configFilePath = saveConfig(config);
Editor.log('[CC]', '保存配置', configFilePath);
event.reply(null, true);
},
'read-config'(event) {
Editor.log('[CC]', '读取配置');
let config = getConfig();
const config = getConfig();
if (config) Editor.log('[CC]', '读取本地配置');
else Editor.log('[CC]', '未找到本地配置文件');
event.reply(null, config);
},
@@ -158,21 +85,104 @@ module.exports = {
onBeforeChangeFiles(options, callback) {
const config = getConfig();
if (config.auto) {
Editor.log('[CC]', '正在混淆代码...');
for (let i = 0; i < config.files.length; i++) {
if (config.files[i] === '') continue;
let path = config.useAbsPath ? config.files[i] : Path.join(options.dest, config.files[i]);
if (Fs.existsSync(path)) {
obfuscate(path, config.options);
Editor.log('[CC]', '已混淆文件', path);
} else {
Editor.warn('[CC]', '文件不存在', path);
}
Editor.log('[CC]', '正在混淆代码');
// Cocos Creator 2.4 以下
const srcPath = Path.join(options.dest, 'src', 'project.js');
if (Fs.existsSync(srcPath)) {
obfuscate(srcPath, config.options);
Editor.log('[CC]', '已混淆项目代码文件', srcPath);
}
Editor.log('[CC]', '混淆已结束');
// Cocos Creator 2.4 以上
const assetsPath = Path.join(options.dest, 'assets', 'main', 'index.js');
if (Fs.existsSync(assetsPath)) {
obfuscate(assetsPath, config.options);
Editor.log('[CC]', '已混淆项目代码文件', assetsPath);
}
// 额外需要混淆的文件
// for (let i = 0; i < config.extraFiles.length; i++) {
// if (config.extraFiles[i] === '') continue;
// const path = config.useAbsPath ? config.extraFiles[i] : Path.join(options.dest, config.extraFiles[i]);
// if (Fs.existsSync(path)) {
// obfuscate(path, config.options);
// Editor.log('[CC]', '已额外混淆文件', path);
// } else {
// Editor.warn('[CC]', '需额外混淆文件不存在', path);
// }
// }
Editor.log('[CC]', '混淆已完成');
}
callback();
},
}
}
/**
* 保存配置
* @param {object} config
*/
function saveConfig(config) {
// 查找目录
const projectPath = Editor.Project.path || Editor.projectPath;
const configDirPath = Path.join(projectPath, configFileDir);
if (!Fs.existsSync(configDirPath)) Fs.mkdirSync(configDirPath);
const configFilePath = Path.join(projectPath, configFileDir, configFileName);
// 读取本地配置
let object = {};
if (Fs.existsSync(configFilePath)) {
object = JSON.parse(Fs.readFileSync(configFilePath, 'utf8'));
}
// 写入配置
for (const key in config) { object[key] = config[key]; }
Fs.writeFileSync(configFilePath, JSON.stringify(object, null, 2));
return configFilePath;
}
/**
* 读取配置
*/
function getConfig() {
const projectPath = Editor.Project.path || Editor.projectPath;
const configFilePath = Path.join(projectPath, configFileDir, configFileName);
let config = null;
if (Fs.existsSync(configFilePath)) {
config = JSON.parse(Fs.readFileSync(configFilePath, 'utf8'));
}
if (!config) {
config = JSON.parse(JSON.stringify(defaultConfig));
config.options = getPreset('off');
if (config.preset !== 'off') {
const preset = getPreset(config.preset);
for (const key in preset) { config.options[key] = preset[key]; }
}
}
return config;
}
/**
* 读取预设参数
* @param {string} type 预设名
*/
function getPreset(type) {
if (presets) return presets[type];
const presetFilePath = Editor.url(presetFileUrl);
if (Fs.existsSync(presetFilePath)) {
presets = JSON.parse(Fs.readFileSync(presetFilePath, 'utf8'));
return presets[type];
}
return null;
}
/**
* 混淆
* @param {string} filePath 文件路径
* @param {ObfuscatorOptions} options 混淆参数
*/
function obfuscate(filePath, options) {
const sourceCode = Fs.readFileSync(filePath, 'utf8');
const obfuscationResult = JavascriptObfuscator.obfuscate(sourceCode, options);
const obfuscatedCode = obfuscationResult.getObfuscatedCode();
Fs.writeFileSync(filePath, obfuscatedCode);
}

View File

@@ -1,11 +1,11 @@
{
"name": "ccc-obfuscated-code",
"version": "1.0.2.20200530",
"version": "1.0.3.20200802",
"description": "代码混淆工具,支持项目构建后自动混淆代码。",
"author": "文弱书生陈皮皮",
"main": "main.js",
"main-menu": {
"扩展/代码混淆工具/构建后自动混淆": {
"i18n:MAIN_MENU.package.title/代码混淆工具/构建后自动混淆": {
"message": "ccc-obfuscated-code:open-panel"
}
},
@@ -13,10 +13,10 @@
"main": "panel/index.js",
"type": "dockable",
"title": "代码混淆工具/构建后自动混淆",
"width": 600,
"height": 900
"width": 620,
"height": 910
},
"dependencies": {
"javascript-obfuscator": "^0.28.0"
}
}
}

View File

@@ -4,12 +4,13 @@
<div>
<ui-prop name="构建后自动混淆" type="boolean" v-value="auto" tooltip="· 项目构建完成后根据已保存配置自动混淆代码。"></ui-prop>
<hr />
<ui-prop name="需要混淆的文件" style='height: 50;'
<!-- <ui-prop name="额外需要混淆的文件(非项目代码文件)" style='height: 50;'
tooltip="· 默认根目录为项目导出目录 build/{dest}/&#10;· 绝对路径如E:\hahaha\build\web-mobile\src\project.js&#10;* 多个值之间用 ',' 隔开">
<ui-checkbox v-value="useAbsPath">绝对路径?</ui-checkbox>
<ui-text-area class="flex-1" type="string" v-value="files"></ui-text-area>
<ui-text-area v-show="extraFiles != ''" class="flex-1" type="string" v-value="extraFiles"></ui-text-area>
<ui-input v-show="extraFiles == ''" class="flex-1" type="string" v-value="extraFiles"></ui-input>
</ui-prop>
<hr />
<hr /> -->
<ui-prop name="预设"
tooltip="· 可用值:&#10;- 高度混淆,性能较低:性能比不混淆慢 50 - 100%&#10;- 中度混淆,性能均衡:性能比不混淆慢 30 - 50%&#10;- 轻度混淆,性能较高:性能只会比不混淆稍微慢一点点">
<ui-select class="flex-1" v-value="preset">
@@ -37,8 +38,9 @@
<ui-prop name="controlFlowFlattening逻辑扁平化" type="boolean" v-value="options.controlFlowFlattening"
tooltip="· 皮皮:就是将代码逻辑扁平化了。&#10;· 注意:该选项将严重影响性能,影响高达 1.5 倍。使用 controlFlowFlatteningThreshold 选项来控制转换概率。&#10;· 开启代码控制流扁平化。控制流扁平化会转换源代码的结构,阻碍程序的阅读理解。">
</ui-prop>
<ui-prop name="controlFlowFlatteningThreshold扁平化比例" v-if="options.controlFlowFlattening" indent="1" type="number"
v-value="options.controlFlowFlatteningThreshold" step="0.01" min="0" max="1" tooltip="· 应用控制流扁平化的概率。"></ui-prop>
<ui-prop name="controlFlowFlatteningThreshold扁平化比例" v-if="options.controlFlowFlattening" indent="1"
type="number" v-value="options.controlFlowFlatteningThreshold" step="0.01" min="0" max="1"
tooltip="· 应用控制流扁平化的概率。"></ui-prop>
<ui-prop name="deadCodeInjection注入废代码" type="boolean" v-value="options.deadCodeInjection"
tooltip="· 皮皮:就是往代码里面随机加一些没有用的代码,迷惑敌人~&#10;· 注意:该选项会大大增加代码的体积(甚至高达 200%)。可以使用 deadCodeInjectionThreshold 来设置添加的比例。&#10;· 注意:开启这个选项会强制使用 stringArray 。">
</ui-prop>

View File

@@ -1,4 +1,4 @@
let Fs = require('fs');
const Fs = require('fs');
Editor.Panel.extend({
@@ -7,7 +7,7 @@ Editor.Panel.extend({
template: Fs.readFileSync(Editor.url('packages://ccc-obfuscated-code/panel/index.html'), 'utf8'),
ready() {
let vue = new window.Vue({
const app = new window.Vue({
el: this.shadowRoot,
data() {
@@ -15,8 +15,8 @@ Editor.Panel.extend({
isSaving: false,
auto: false,
files: '/src/project.js',
useAbsPath: false,
// extraFiles: '',
// useAbsPath: false,
preset: 'low',
options: {
compact: true,
@@ -59,7 +59,7 @@ Editor.Panel.extend({
watch: {
options: {
handler(value) {
if (value.deadCodeInjection) vue.options.stringArray = true;
if (value.deadCodeInjection) app.options.stringArray = true;
},
deep: true
}
@@ -75,13 +75,13 @@ Editor.Panel.extend({
let config = {
auto: this.auto,
files: this.files.split(','),
useAbsPath: this.useAbsPath,
// useAbsPath: this.useAbsPath,
preset: this.preset,
options: {}
};
for (let key in this.options) {
switch (key) {
// case 'extraFiles':
case 'domainLock': case 'identifiersDictionary': case 'reservedNames': case 'reservedStrings':
config.options[key] = this.options[key] == '' ? [] : this.options[key].split(',');
break;
@@ -109,8 +109,8 @@ Editor.Panel.extend({
Editor.Ipc.sendToMain('ccc-obfuscated-code:read-config', (err, config) => {
if (err) return;
this.auto = config.auto;
this.files = config.files.join(',');
this.useAbsPath = config.useAbsPath;
// this.extraFiles = config.extraFiles.join(',');
// this.useAbsPath = config.useAbsPath;
this.preset = config.preset;
for (let key in config.options) {
this.options[key] = Array.isArray(config.options[key]) ? config.options[key].join(',') : config.options[key];
@@ -132,7 +132,8 @@ Editor.Panel.extend({
}
});
vue.readConfig();
app.readConfig();
}
});

View File

@@ -1,7 +1,8 @@
/**
* Cocos Creator
* @author ifaswind
* @see https://gitee.com/ifaswind/eazax-ccc/blob/master/declaration/editor.d.ts
* @version 20200727
* @see https://gitee.com/ifaswind/eazax-ccc/blob/master/declarations/editor.d.ts
*/
declare namespace Editor {
@@ -1102,4 +1103,4 @@ declare module Editor.Utils {
}
}
}