Bootstrap

android cocoscreator jsc js 间加解密(六)

前言

前面 学了 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,下图是引用了别人的
这张图是引用别人的地址如下 https://www.jianshu.com/p/4272e0805da3
这里自己用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

;