前面 学了 aandroid cocoscreator 热更新 超详细篇(五)
这章 主要学习 cocoscreator 构建后 jsc 与js 文件 之间相互转化(加解密)并实际测试.
可以配置cocoscreator热更新使用
1: 准备
win7 64位
cocoscreator2.0.10 (新版本如 2.4.7应该也是可以的)
2:创建个cocoscreator helloworld工程,并构建
构建完后 在 build\jsb-link\src (这里选择是link 模板) 有3个jsc文件,在build\jsb-link\js backups (useful for debugging) 有这3个的未加密的原文件
这里主要用到 xxtea加解密算法 压缩用的是gzip,下图是引用了别人的
这里自己用go写了小工具
主要代码如下
//eh create
package main
import (
"bytes"
"compress/gzip"
"github.com/xxtea/xxtea-go/xxtea"
"io"
"io/ioutil"
"log"
"os"
"path"
"path/filepath"
"strconv"
)
func main() {
var strkey string
var deensign uint8 //-s 1bit 0 解密 1 加密 2bit 0 无解压或加压 1 需要解压或压缩
var filename string
var outputpath string //简化到了,直接输出到当前目录
//decodeencodejsc -f
if len(os.Args)&1 != 1 {
log.Printf("eg:decode decodeencodejsc -s 0 -k 123456 -f 1.jsc " +
"encode decodeencodejsc -s 1 -k 123456 -f 1.js ")
return
}
for i := 1; i < len(os.Args); i += 2 {
switch os.Args[i] {
case "-s":
if tflag, ef := strconv.Atoi(os.Args[i+1]); ef == nil {
deensign = uint8(tflag)
if deensign > 3 {
log.Printf("-s params(1bit 0 解密 1 加密 2bit 0 无解压或加压 1 需要解压或压缩) ")
}
deensign &= 3
} else {
log.Printf("-s params is error!")
return
}
case "-k":
strkey = os.Args[i+1]
case "-f":
filename = os.Args[i+1]
case "-p"://这个参数暂时没用到
outputpath = os.Args[i+1]
println("%v", outputpath)
default:
log.Printf("params is error")
return
}
}
//strkey = "dc6c9a10-42bb-4f"
//decode unzip
// filename = "tmp/settings.jsc"
//filename = "zip/settings.jsc"
// deensign = 2
//encode zip
//filename = "enzip/settings.js"
//deensign = 3
//jsc 352 byte js 453 byte
if len(filename) < 4 || len(strkey) < 4 { //|| len(outputpath) < 1
log.Printf("check params is error!")
return
}
cfgpath, _ := filepath.Abs(filepath.Dir(os.Args[0]))
absolutepathname := path.Join(cfgpath, filename)
cfg, err := os.Open(absolutepathname)
if err != nil {
log.Printf("can't find ", filename)
return
}
data, err := ioutil.ReadAll(cfg)
if err != nil {
cfg.Close()
return
}
cfg.Close()
if deensign&1 == 0 { //decode 解密
//*.jsc
tarfile := absolutepathname[:len(absolutepathname)-4]
decodedata := xxtea.Decrypt(data, []byte(strkey))
if deensign&2 > 0 { //解压
if nlen, tdata := fungzip(decodedata); nlen > 0 {
decodedata = make([]byte, nlen)
copy(decodedata, tdata)
} else {
log.Printf("fungzip fail %v", absolutepathname)
return
}
}
writefile(tarfile+".js", decodedata)
} else { //encode 加密
//*.js
tarfile := absolutepathname[:len(absolutepathname)-3]
decodedata := data
if deensign&2 > 0 { //加压
if nlen, tdata := fgzip(data); nlen > 0 {
decodedata = make([]byte, nlen)
copy(decodedata, tdata)
} else {
log.Printf("fgzip fail %v", absolutepathname)
return
}
}
decodedata = xxtea.Encrypt(decodedata, []byte(strkey))
writefile(tarfile+".jsc", decodedata)
}
}
func checkFileIsExist(filename string) bool {
var exist = true
if _, err := os.Stat(filename); os.IsNotExist(err) {
exist = false
}
return exist
}
//31 139 8 //0-2
// 0 0 0 0 0 0 (6个0) //3-8
//10 141 144 75 111 (9-13)
//194 48 16 132 255 139 (14-19)
func fungzip(data []byte) (int32, []byte) {
b := new(bytes.Buffer)
// Test NewReader.
in := bytes.NewReader(data)
r2, err := gzip.NewReader(in)
if err != nil {
log.Printf("ungzip error=%v", err)
return 0, []byte{}
}
defer r2.Close()
b.Reset()
//n, err := io.Copy(b, r2)
n, err := io.Copy(b, r2)
if err != nil {
//t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, tt.err)
log.Printf("ungzip error=%v", err)
return 0, []byte{}
}
return int32(n), b.Bytes()
}
//func fgzip(data []byte, filename string) (int32, []byte) {
func fgzip(data []byte) (int32, []byte) {
//
buf := new(bytes.Buffer)
w := gzip.NewWriter(buf)
n0 := buf.Len()
if n0 != 0 {
//t.Fatalf("buffer size = %d before writes; want 0", n0)
log.Printf("fgzip buffer size = %d before writes; want 0", n0)
defer w.Close()
return 0, []byte{}
}
w1, e1 := w.Write(data)
if e1 != nil {
log.Printf("fgzip buffer size = %d before writes; want %v", w1, n0)
defer w.Close()
return 0, []byte{}
}
// log.Printf("write date len=%v", w1)
n1 := buf.Len()
if err := w.Flush(); err != nil {
log.Printf("fgzip err=%v", err.Error())
defer w.Close()
return 0, []byte{}
}
n2 := buf.Len()
if n2 == n1 {
log.Printf("no data after first flush")
defer w.Close()
return 0, []byte{}
}
w.Close()
n3 := buf.Len()
// log.Printf("write date len=%v", n3)
return int32(n3), buf.Bytes()
//
}
func writefile(filename string, filedata []byte) bool {
if f, e := os.Create(filename); e == nil {
f.Write(filedata)
f.Close()
return true
}
return false
}
假如编译的执行文件叫 decodeencodejsc
1:解密
执行文件跟jsc 文件放同目录下
1> 不需要解压
decodeencodejsc -s 0 -k 密钥 -f 1.jsc
2> 需要解压
decodeencodejsc -s 2 -k 密钥 -f 1.jsc
同目录下生成1.js
2:加密
执行文件跟js 文件放同目录下
1> 不需要压缩
decodeencodejsc -s 1 -k 密钥 -f 1.js
2> 需要压缩
decodeencodejsc -s 3 -k 密钥 -f 1.js
同目录下生成1.jsc
3:测试
1:把cocoscreator生成jsc解密
执行后得到,结果是OK的
2:把js 加密
怎么测试呢,把生成jsc文件替换掉 build\jsb-link\src 的,再打包成apk 运行就知道了
4:查看引擎的xxtea zip 代码
万一XXTEA zip 版本跟引擎的不一致呢,会不会出错
这里告诉大家引擎版本的的原文件位置(构建后,以android为例用as打开)
如需工程代码后续在上传,执行文件下载地址(x86_64架构下 windows7 centos7 执行文件)
https://download.csdn.net/download/yunteng521/74707369
重复下 使用说明
假如执行文件叫 decodeencodejsc
1:解密
执行文件跟jsc 文件放同目录下
1> 不需要解压
decodeencodejsc -s 0 -k 密钥 -f 1.jsc
2> 需要解压
decodeencodejsc -s 2 -k 密钥 -f 1.jsc
同目录下生成1.js
2:加密
执行文件跟js 文件放同目录下
1> 不需要压缩
decodeencodejsc -s 1 -k 密钥 -f 1.js
2> 需要压缩
decodeencodejsc -s 3 -k 密钥 -f 1.js
同目录下生成1.jsc