前端如何给 JavaScript 加密(不是混淆)?

JavaScript
关注者
2,047
被浏览
1,111,762
登录后你可以
不限量看优质回答私信答主深度交流精彩内容一键收藏

Update:

从去年开始,自己带着几个小伙伴一起创业,遇到了很多行业流氓,开始慢慢意识到加密的重要性,在做商业化产品的过程中也开发了一些副产品,加密就是其中一项比较重要的工具。

随着WebAssembly技术的兴起,给前端代码保护带来了新的可能,基于wasm,我司的 赵洋 同学开发了一套全新的加密产品:github.com/qiaozi-tech/

SecurityWorker提供完全隐匿且兼容ECMAScript 5.1的类WebWorker的安全可信环境,帮助保护你的核心Javascript代码不被破解。 SecurityWorker不同于普通的Javascript代码混淆,我们使用独立Javascript VM+二进制混淆opcode核心执行的方式防止您的代码被开发者工具调试、代码反向。

用需要的同学可以在我们加密产品的官网进行在线测试:securitify.io/

以下是原答案:


曾经和 @王集鹄 讨论过前端混淆问题,当时的帖子在这里,欢迎围观:

div.io/topic/1220

现在网上那些看起来像乱码的混淆工具都是扯淡的,破解起来不需要1秒钟。之前看到过猎豹浏览器中一个h5小游戏的混淆思路很有意思(评论中 @鲁小夫 大神做的这个混淆器):

ijinshan.com/game/flapp

它的策略不复杂,比如源码是:

var a = document.getElementById('a');
a.innerHTML = 'hello world';


用js的ast工具分析一下,找到所有字面量,然后提出成局部变量进行替换就好了,得到这种效果:

(function(a, b, c, d, e, f){
    a[d] = a[b][c](d);
    a[d][e]=f;
})(this, 'document', 'getElementById', 'a', 'innerHTML', 'hello world');


这是从破坏可读性的角度做的混淆,除非用相同的方式做替换,否则很难还原代码,而且核心部分需要深入debug才能了解。

基于这个思路,@邝嘉豪(现在已经是前端小牛了)使用 esprima 开发了一个小工具

github.com/FF-Mercurial

实现了上述功能,而且针对一些主流框架进行混淆,再回归她们的测试用例验证工具的等价性,没有什么问题。

后来我发现这种混淆对于小段代码的保护性不强,参考了 jscrambler.com/ 之后我加了一层规则,用于打散提取出来的字符串中的字符,最终效果如下:

! function(n) {
    ! function(n, t, r, u, i, o, c) {
        n[r] = n[i][u](r), n[r][o] = c
    }(this, void 0,
        n(0),
        n(1, 2, 3, 4, 5, 2, 6, 2, 7, 3, 8, 9, 10, 11),
        n(11, 12, 13, 14, 6, 2, 7, 3),
        n(15, 7, 7, 2, 16, 17, 18, 19, 20),
        n(21, 2, 5, 5, 12, 22, 23, 12, 16, 5, 11)
    )
}(function(n) {
    return function() {
        for (var t = arguments, r = "", u = 0, i = t.length; i > u; u++)
            r += n[t[u]];
        return r
    }
}([
    "a", "g", "e", "t", "E",
    "l", "m", "n", "B", "y",
    "I", "d", "o", "c", "u",
    "i", "r", "H", "T", "M",
    "L", "h", " ", "w"
]));


虽然看起来挺吓人,其实也没有提升太多破解的成本,对于熟悉ast操作的同学来说可能会10秒钟还原。

前端确实没有秘密可言,还原混淆的成本特别低,大多数混淆策略也不过是障眼法而已(比如这个 raw.githubusercontent.com 我用了一个特殊的Unicode字符来做「混淆」)

期待有人能给出更专业的解决办法。