1.前言
脚本开发过程中,除了启动时保存在内存中的一些数据,还需要保存一下永久数据。我们不会像程序开发一样将数据保存到数据库中,这样需要配置远程服务器,成本也太多了。我们一般将数据保存到本地的txt文件中,这就涉及一些关键数据的加密问题。尤其是账号密码等关键信息,我们为了安全都是加密保存,然后到脚本中解密使用。我在脚本开发时,除了非常简单的数据,哪怕是脚本一些配置信息都会加密保存。比如一些游戏脚本的战斗配置,我也会加密保存,这样更安全,加密和解密过程是非常迅速的,不用担心影响脚本运行速度。
当然,加密也分简单加密和复杂加密。大部分脚本一般采用简单加密的方式,我更加推荐复杂加密的方式。我平时脚本开发过程中,一直使用的复杂加密的方式。虽然很少有人会将保存到本地的数据尝试自己加密,但是我还是推荐复杂加密的方式。加密就是为了更加安全,在不影响脚本运行速度的前提下,肯定选择更加安全的加密方式。
2.简单加密
1.概况
简单加密就是使用base64的方式进行加密,就是利用base64的编码和解码过程实现简单的加密和解密。熟悉base64的都知道,这种加密也就是能够表面加密,任何人再通过base64解码实现解密。由于base64加密和解密过程非常简单,并且大部分脚本使用者根本不了解代脚本开发,因此,许多脚本开发者都使用这种方式加密。但是,我不推荐这种方式就行数据加密。如果调用官方自带的base64,会出现未找到的报错。因为我们使用的是免费版,很容易出现这个问题。我们可以封装两个函数来实现官方文档中的功能,可以通过js实现base64功能或者调用已经存在的base64函数。
autojs能够调用java中的类型或者接口,为了减少工作量,我直接在封装函数中调用java的相关函数了。封装的编码函数(base64Encode)和解码函数(base64Decode)分别官方文档中base64的encode函数和decode函数功能一致。
// base64编码
function base64Encode(str, encoding) {
encoding = encoding ? encoding : "utf-8";
return java.util.Base64.getEncoder().encodeToString(new java.lang.String(str).getBytes(encoding));
}
// base64解码
function base64Decode(str, encoding) {
encoding = encoding ? encoding : "utf-8";
return new java.lang.String(java.util.Base64.getDecoder().decode(str), encoding);
}
2.base64Encode
对应官方文档的base64.encode函数,将字符串编码,需要传递传递两个参数,分别为需要编码的字符串和字符编码,参数类型均为字符串。一般情况下,因为有些数据可能为中文,字符编码选择utf-8即可。解码的字符编码要与编码的字符编码一致,这样才能解密。由于编码和解码要配合使用,会在解码部分一起通过代码进行举例说明。
3.base64Decode
对应官方文档的base64.decode函数,将字符串解码,需要传递传递两个参数,分别为需要解码的字符串和字符编码,参数类型均为字符串。字符串解码要和字符串编码过程中的字符编码一致,由于我们数据中很容易出现中文,我们可以将字符串编码和字符串解码的字符编码一直设置为utf-8。字符串编码过程中,要编码的字符串的类型为字符串,如果不是字符串的数据先要转换为字符串,然后再进行编码。
// 设置对象类型的初始数据
let obj = {
test1: "测试1",
test2: "测试2"
}
// 由于不是字符串类型,先转换为字符串
let objString = JSON.stringify(obj);
console.log("对象转换为字符串的数据为:");
console.log(objString);
console.log("----------------------------");
// 设置字符编码
let characterEncoding = "utf-8";
// 进行base64编码
let base64String = base64Encode(objString, characterEncoding);
console.log("base64加密后的数据为:");
console.log(base64String);
console.log("----------------------------");
// 进行base64解码
let base64DecodeString = base64Decode(base64String, characterEncoding);
console.log("base64解密后的数据为:");
console.log(base64DecodeString);
console.log("----------------------------");
// 将字符串转换为对象
let targetObj = JSON.parse(base64DecodeString);
console.log("解密后对象数据为:");
console.log(targetObj);
// base64编码
function base64Encode(str, encoding) {
encoding = encoding ? encoding : "utf-8";
return java.util.Base64.getEncoder().encodeToString(new java.lang.String(str).getBytes(encoding));
}
// base64解码
function base64Decode(str, encoding) {
encoding = encoding ? encoding : "utf-8";
return new java.lang.String(java.util.Base64.getDecoder().decode(str), encoding);
}
在脚本开发中,可以配合文件系统进行使用,将加密后的字符串通过文件保存到本地,使用时读取本地文件然后解密。
3.复杂加密
1.概况
复杂加密是通过官方文档中“加解密与消息摘要”部分的内容实现,这部分的其他内容很少使用,根据需求自行学习。这部分内容有各种加密方式,每种加密的使用方式也不同,官方对于这方面的介绍比较少,也有概率免费版不支持全部功能。因此,我推荐使用AES这种加密方式,这种加密方式安全性还是比较高的,同时我已经封装好函数了,大家可以直接调用。
2.encrypt
通过AES进行加密,需要传递两个参数,分别为要加密的数据和加密密钥,参数类型分别为任意类型和字符串。其中,加密密钥必须为16位。
// AES加密
// data:需要加密的数据
// key:加密密钥,必须16位
function encrypt(data, key) {
let javaData = new java.lang.String(data);
// 加密算法
let encryptionAlgorithm = "AES";
let cipher = javax.crypto.Cipher.getInstance(encryptionAlgorithm);
let secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes("UTF-8"), encryptionAlgorithm);
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKey);
let encrypted = cipher.doFinal(javaData.getBytes("UTF-8"));
return android.util.Base64.encodeToString(encrypted, android.util.Base64.DEFAULT);
}
3.decrypt
通过AES进行解密,需要传递两个参数,分别为加密后的数据和加密密钥,参数类型均为字符串。其中,加密密钥必须为16位。
// AES解密
// encrypted:需要解密的数据
// key:加密密钥,必须16位
function decrypt(encrypted, key) {
// 加密算法
let encryptionAlgorithm = "AES";
let cipher = javax.crypto.Cipher.getInstance(encryptionAlgorithm);
let secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes("UTF-8"), encryptionAlgorithm);
cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKey);
let decrypted = cipher.doFinal(android.util.Base64.decode(encrypted, android.util.Base64.DEFAULT));
return new java.lang.String(decrypted, "UTF-8").toString();
}
下面是加密和解密的使用方式,其实和上面的base64方式类似,只是多了个加密密钥。这个16位密钥可以自己随便生成,只有这密钥和加密时使用的密钥相同才能成功解析出数据,大大提高了加密的安全性。
// 设置对象类型的初始数据
let obj = {
test1: "测试1",
test2: "测试2"
}
// 由于不是字符串类型,先转换为字符串
let objString = JSON.stringify(obj);
console.log("对象转换为字符串的数据为:");
console.log(objString);
console.log("----------------------------");
// 加密秘钥(必须16位),可以随便输入16位
let encryptionKey = new java.lang.String("kjsnxlemzienglkn");
// 进行AES加密
let aesString = encrypt(objString, encryptionKey);
console.log("AES加密后的数据为:");
console.log(aesString);
console.log("----------------------------");
// 进行AES解密
let aesDecodeString = decrypt(aesString, encryptionKey);
console.log("AES解密后的数据为:");
console.log(aesDecodeString);
console.log("----------------------------");
// 将字符串转换为对象
let targetObj = JSON.parse(aesDecodeString);
console.log("解密后对象数据为:");
console.log(targetObj);
// AES加密
// data:需要加密的数据
// key:加密密钥,必须16位
function encrypt(data, key) {
let javaData = new java.lang.String(data);
// 加密算法
let encryptionAlgorithm = "AES";
let cipher = javax.crypto.Cipher.getInstance(encryptionAlgorithm);
let secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes("UTF-8"), encryptionAlgorithm);
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKey);
let encrypted = cipher.doFinal(javaData.getBytes("UTF-8"));
return android.util.Base64.encodeToString(encrypted, android.util.Base64.DEFAULT);
}
// AES解密
// encrypted:需要解密的数据
// key:加密密钥,必须16位
function decrypt(encrypted, key) {
// 加密算法
let encryptionAlgorithm = "AES";
let cipher = javax.crypto.Cipher.getInstance(encryptionAlgorithm);
let secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes("UTF-8"), encryptionAlgorithm);
cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKey);
let decrypted = cipher.doFinal(android.util.Base64.decode(encrypted, android.util.Base64.DEFAULT));
return new java.lang.String(decrypted, "UTF-8").toString();
}
4.总结
特别注意,只有通过个人主页博客或者个人介绍中方式,才能获取源码