- 算法特点
a) 消息摘要算法/单向散列函数/哈希函数
b) 不同长度的输入,产生固定长度的输出
c) 散列后的密文不可逆
d) 散列后的结果唯一
e) 哈希碰撞
f) 一般用于校验数据完整性、签名sign
由于密文不可逆,所以服务端也无法解密
想要验证,就需要跟前端一样的方式去重新签名一遍
签名算法一般会把源数据和签名后的值一起提交到服务端
要保证在签名时候的数据和提交上去的源数据一致
- 常见算法
MD5、SHA1、SHA256、SHA512、HmacMD5、HmacSHA1、HmacSHA256、HmacSHA512
RIPEMD160、HmacRIPEMD160、PBKDF2、EvpKDF
MD5
MD5的java实现
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update("xiaojianbang".getBytes());
md5.digest();
加密后的字节数组可以编码成Hex、Base64
没有任何输入,也能计算hash值
碰到加salt的MD5,可以直接输入空的值,得到结果去CMD5查询一下,有可能就得到salt
SHA
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
sha1.update("xiaojianbang".getBytes());
sha1.digest();
加密后的字节数组可以编码成Hex、Base64
没有任何输入,也能计算hash值
算法通杀脚本开发
工具函数封装
Java.perform(function () {
function showStacks() {
console.log(
Java.use("android.util.Log")
.getStackTraceString(
Java.use("java.lang.Throwable").$new()
)
);
}
var ByteString = Java.use("com.android.okhttp.okio.ByteString");
function toBase64(data) {
console.log(ByteString.of(data).base64());
}
function toHex(data) {
console.log(ByteString.of(data).hex());
}
function toUtf8(data) {
console.log(ByteString.of(data).utf8());
}
// toBase64([48,49,50,51,52]);
// toHex([48,49,50,51,52]);
// toUtf8([48,49,50,51,52]);
//console.log(Java.enumerateLoadedClassesSync().join("\n"));});
MD5算法通杀hook SHA算法通杀hook
Java.perform(function () {
function showStacks() {
console.log(
Java.use("android.util.Log")
.getStackTraceString(
Java.use("java.lang.Throwable").$new()
)
);
}
var ByteString = Java.use("com.android.okhttp.okio.ByteString");
function toBase64(tag, data) {
console.log(tag + " Base64: " + ByteString.of(data).base64());
}
function toHex(tag, data) {
console.log(tag + " Hex: " + ByteString.of(data).hex());
}
function toUtf8(tag, data) {
console.log(tag + " Utf8: " + ByteString.of(data).utf8());
}
var messageDigest = Java.use("java.security.MessageDigest");
messageDigest.update.overload('byte').implementation = function (data) {
console.log("MessageDigest.update('byte') is called!");
showStacks();
return this.update(data);
}
messageDigest.update.overload('java.nio.ByteBuffer').implementation = function (data) {
console.log("MessageDigest.update('java.nio.ByteBuffer') is called!");
showStacks();
return this.update(data);
}
messageDigest.update.overload('[B').implementation = function (data) {
console.log("MessageDigest.update('[B') is called!");
showStacks();
var algorithm = this.getAlgorithm();
var tag = algorithm + " update data";
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
console.log("=======================================================");
return this.update(data);
}
messageDigest.update.overload('[B', 'int', 'int').implementation = function (data, start, length) {
console.log("MessageDigest.update('[B', 'int', 'int') is called!");
showStacks();
var algorithm = this.getAlgorithm();
var tag = algorithm + " update data";
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
console.log("=======================================================", start, length);
return this.update(data, start, length);
}
messageDigest.digest.overload().implementation = function () {
console.log("MessageDigest.digest() is called!");
showStacks();
var result = this.digest();
var algorithm = this.getAlgorithm();
var tag = algorithm + " digest result";
toUtf8(tag, result);
toHex(tag, result);
toBase64(tag, result);
console.log("=======================================================");
return result;
}
messageDigest.digest.overload('[B').implementation = function (data) {
console.log("MessageDigest.digest('[B') is called!");
showStacks();
var algorithm = this.getAlgorithm();
var tag = algorithm + " digest data";
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
var result = this.digest(data);
var tags = algorithm + " digest result";
toUtf8(tag, result);
toHex(tags, result);
toBase64(tags, result);
console.log("=======================================================");
return result;
}
messageDigest.digest.overload('[B', 'int', 'int').implementation = function (data, start, length) {
console.log("MessageDigest.digest('[B', 'int', 'int') is called!");
showStacks();
var algorithm = this.getAlgorithm();
var tag = algorithm + " digest data";
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
var result = this.digest(data, start, length);
var tags = algorithm + " digest result";
toHex(tags, result);
toBase64(tags, result);
console.log("=======================================================", start, length);
return result;
}
});
MAC
MAC算法与MD和SHA的区别是多了一个密钥,密钥可以随机给
MAC的Java实现
SecretKeySpec secretKeySpec =
new SecretKeySpec("a12345678".getBytes(),"HmacSHA1");
Mac mac = Mac.getInstance(secretKeySpec.getAlgorithm());
mac.init(secretKeySpec);
mac.update("xxxa".getBytes());
mac.doFinal();
加密后的字节数组可以编码成Hex、Base64
没有任何输入,也能计算hash值
Java.perform(function () {
function showStacks() {
console.log(
Java.use("android.util.Log")
.getStackTraceString(
Java.use("java.lang.Throwable").$new()
)
);
}
var ByteString = Java.use("com.android.okhttp.okio.ByteString");
function toBase64(tag, data) {
console.log(tag + " Base64: " + ByteString.of(data).base64());
}
function toHex(tag, data) {
console.log(tag + " Hex: " + ByteString.of(data).hex());
}
function toUtf8(tag, data) {
console.log(tag + " Utf8: " + ByteString.of(data).utf8());
}
// toUtf8("xx",[48, 49, 50, 51, 52]);
// toBase64("xx",[48, 49, 50, 51, 52]);
// toHex("xx",[48, 49, 50, 51, 52]);
var messageDigest = Java.use("java.security.MessageDigest");
messageDigest.update.overload('byte').implementation = function (data) {
console.log("MessageDigest.update('byte') is called!");
showStacks();
return this.update(data);
}
messageDigest.update.overload('java.nio.ByteBuffer').implementation = function (data) {
console.log("MessageDigest.update('java.nio.ByteBuffer') is called!");
showStacks();
return this.update(data);
}
messageDigest.update.overload('[B').implementation = function (data) {
console.log("MessageDigest.update('[B') is called!");
showStacks();
var algorithm = this.getAlgorithm();
var tag = algorithm + " update data";
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
console.log("=======================================================");
return this.update(data);
}
messageDigest.update.overload('[B', 'int', 'int').implementation = function (data, start, length) {
console.log("MessageDigest.update('[B', 'int', 'int') is called!");
showStacks();
var algorithm = this.getAlgorithm();
var tag = algorithm + " update data";
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
console.log("=======================================================", start, length);
return this.update(data, start, length);
}
messageDigest.digest.overload().implementation = function () {
console.log("MessageDigest.digest() is called!");
showStacks();
var result = this.digest();
var algorithm = this.getAlgorithm();
var tag = algorithm + " digest result";
toUtf8(tag, result);
toHex(tag, result);
toBase64(tag, result);
console.log("=======================================================");
return result;
}
messageDigest.digest.overload('[B').implementation = function (data) {
console.log("MessageDigest.digest('[B') is called!");
showStacks();
var algorithm = this.getAlgorithm();
var tag = algorithm + " digest data";
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
var result = this.digest(data);
var tags = algorithm + " digest result";
toUtf8(tag, result);
toHex(tags, result);
toBase64(tags, result);
console.log("=======================================================");
return result;
}
messageDigest.digest.overload('[B', 'int', 'int').implementation = function (data, start, length) {
console.log("MessageDigest.digest('[B', 'int', 'int') is called!");
showStacks();
var algorithm = this.getAlgorithm();
var tag = algorithm + " digest data";
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
var result = this.digest(data, start, length);
var tags = algorithm + " digest result";
toHex(tags, result);
toBase64(tags, result);
console.log("=======================================================", start, length);
return result;
}
var mac = Java.use("javax.crypto.Mac");
mac.init.overload('java.security.Key', 'java.security.spec.AlgorithmParameterSpec').implementation = function (key, AlgorithmParameterSpec) {
console.log("Mac.init('java.security.Key', 'java.security.spec.AlgorithmParameterSpec') is called!");
return this.init(key, AlgorithmParameterSpec);
}
mac.init.overload('java.security.Key').implementation = function (key) {
console.log("Mac.init('java.security.Key') is called!");
var algorithm = this.getAlgorithm();
var tag = algorithm + " init Key";
var keyBytes = key.getEncoded();
toUtf8(tag, keyBytes);
toHex(tag, keyBytes);
toBase64(tag, keyBytes);
console.log("=======================================================");
return this.init(key);
}
mac.update.overload('byte').implementation = function (data) {
console.log("Mac.update('byte') is called!");
return this.update(data);
}
mac.update.overload('java.nio.ByteBuffer').implementation = function (data) {
console.log("Mac.update('java.nio.ByteBuffer') is called!");
return this.update(data);
}
mac.update.overload('[B').implementation = function (data) {
console.log("Mac.update('[B') is called!");
var algorithm = this.getAlgorithm();
var tag = algorithm + " update data";
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
console.log("=======================================================");
return this.update(data);
}
mac.update.overload('[B', 'int', 'int').implementation = function (data, start, length) {
console.log("Mac.update('[B', 'int', 'int') is called!");
var algorithm = this.getAlgorithm();
var tag = algorithm + " update data";
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
console.log("=======================================================", start, length);
return this.update(data, start, length);
}
mac.doFinal.overload().implementation = function () {
console.log("Mac.doFinal() is called!");
var result = this.doFinal();
var algorithm = this.getAlgorithm();
var tag = algorithm + " doFinal result";
toUtf8(tag, result);
toHex(tag, result);
toBase64(tag, result);
console.log("=======================================================");
return result;
}
mac.doFinal.overload('[B').implementation = function (data) {
console.log("Mac.doFinal.overload('[B') is called!");
return this.doFinal(data);
}
mac.doFinal.overload('[B', 'int').implementation = function (output, outOffset) {
console.log("Mac.doFinal.overload('[B', 'int') is called!");
return this.doFinal(output, outOffset);
}
});