- 加密/解密的过程可逆的算法,叫做加密算法
- 加密/解密使用相同的密钥,叫做对称加密算法
- 对称加密算法的密钥可以随机给,但是有位数要求
- 对称加密算法的输入数据没有长度要求,加密速度快
- 各算法的密钥长度
RC4 密钥长度1-256字节
DES 密钥长度8字节
3DES/DESede/TripleDES 密钥长度24字节
AES 密钥长度16、24、32字节
根据密钥长度不同AES又分为AES-128、AES-192、AES-256
- 对称加密分类
-
序列加密/流加密: 以字节流的方式,依次加密(解密)明文(密文)中的每一个字节
RC4
-
分组加密: 将明文消息分组(每组有多个字节),逐组进行加密
DES、3DES、AES
DES
SecretKeySpec desKey = new SecretKeySpec("12345678".getBytes(), "DES");
// IvParameterSpec ivParameterSpec = new IvParameterSpec("12345678".getBytes());
Cipher des = Cipher.getInstance("DES/CBC/PKCS5Padding");
des.init(Cipher.ENCRYPT_MODE, desKey)
byte[] result3 = des.doFinal("123456".getBytes());
//解密
des.init(Cipher.DECRYPT_MODE, desKey);
byte[] result4 = des.doFinal(result3);
CBC需要Iv向量
SecretKeySpec desKey = new SecretKeySpec("12345678".getBytes(), "DES");
IvParameterSpec ivParameterSpec = new IvParameterSpec("12345678".getBytes());
Cipher des = Cipher.getInstance("DES/CBC/PKCS5Padding");
des.init(Cipher.ENCRYPT_MODE, desKey, ivParameterSpec);
des.doFinal("123456".getBytes());
-
对称加密算法里,使用NOPadding,加密的明文必须等于分组长度倍数,否则报错
-
没有指明加密模式和填充方式,表示使用默认的DES/ECB/PKCS5Padding
-
加密后的字节数组可以编码成Hex、Base64
-
要复现一个对称加密算法,需要得到明文、key、iv、mode、padding
-
明文、key、iv需要注意解析方式,而且不一定是字符串形式
-
如果加密模式是ECB,则不需要加iv,加了的话会报错
-
ECB模式和CBC模式的区别
-
如果使用PKCS5Padding,会对加密的明文填充1字节-1个分组的长度
-
DES算法明文按64位进行分组加密
-
如果明文中有两个分组的内容相同,ECB会得到完全一样的密文,CBC不会
-
加密算法的结果通常与明文等长或者更长,如果变短了,那可能是gzip、protobuf、消息摘要算法
DESede
SecretKeySpec secretKeySpec = new SecretKeySpec("123456781234567812345678".getBytes(), "DESede");
IvParameterSpec ivParameterSpec = new IvParameterSpec("12345678".getBytes());
Cipher desede = Cipher.getInstance("DESede/CBC/PKCS5Padding");
desede.init(Cipher.ENCRYPT_MODE, desedeKey, ivParameterSpec);
desede.doFinal("xxxx".getBytes());
-
DESede实际上是先进行DES加密,再进行DES解密,再进行DES加密
-
DESede的密钥24个字节,第1个8字节密钥用于DES加密,之后类推
-
如果DESede的3个8字节密钥相同,则加密结果与DES一致
-
为了保证DESede的安全性,一般前2个或者3个8字节密钥都不一致
-
DESede的其他特征与DES一致
AES
根据密钥长度不同,分为AES128、AES192、AES256
AES加解密的Java实现
SecretKeySpec key = new SecretKeySpec("1234567890abcdef".getBytes(),"AES");
AlgorithmParameterSpec iv = new IvParameterSpec("1234567890abcdef".getBytes());
Cipher aes = Cipher.getInstance("AES/CBC/PKCS5Padding");
aes.init(Cipher.ENCRYPT_MODE, key, iv);
aes.doFinal("xxxxbbbbcccc1234xxxxbbbbcccc1234".getBytes());
AES算法明文按128位进行分组加密,其余特征与DES一致
DES、3DES、AES算法通杀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());
}
// toUtf8("xiaojianbang",[48, 49, 50, 51, 52]);
// toBase64("xiaojianbang",[48, 49, 50, 51, 52]);
// toHex("xiaojianbang",[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!");
console.log("=======================================================");
return this.update(data);
}
messageDigest.update.overload('java.nio.ByteBuffer').implementation = function (data) {
console.log("MessageDigest.update('java.nio.ByteBuffer') is called!");
console.log("=======================================================");
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!");
console.log("=======================================================");
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!");
console.log("=======================================================");
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!");
console.log("=======================================================");
return this.doFinal(output, outOffset);
}
var cipher = Java.use("javax.crypto.Cipher");
cipher.init.overload('int', 'java.security.cert.Certificate').implementation = function () {
console.log("Cipher.init('int', 'java.security.cert.Certificate') is called!");
console.log("=======================================================");
return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.Key', 'java.security.SecureRandom').implementation = function () {
console.log("Cipher.init('int', 'java.security.Key', 'java.security.SecureRandom') is called!");
console.log("=======================================================");
return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.cert.Certificate', 'java.security.SecureRandom').implementation = function () {
console.log("Cipher.init('int', 'java.security.cert.Certificate', 'java.security.SecureRandom') is called!");
console.log("=======================================================");
return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters', 'java.security.SecureRandom').implementation = function () {
console.log("Cipher.init('int', 'java.security.Key', 'java.security.AlgorithmParameters', 'java.security.SecureRandom') is called!");
console.log("=======================================================");
return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec', 'java.security.SecureRandom').implementation = function () {
console.log("Cipher.init('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec', 'java.security.SecureRandom') is called!");
console.log("=======================================================");
return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters').implementation = function () {
console.log("Cipher.init('int', 'java.security.Key', 'java.security.AlgorithmParameters') is called!");
console.log("=======================================================");
return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.Key').implementation = function () {
console.log("Cipher.init('int', 'java.security.Key') is called!");
var algorithm = this.getAlgorithm();
var tag = algorithm + " init Key";
var className = JSON.stringify(arguments[1]);
if(className.indexOf("OpenSSLRSAPrivateKey") === -1){
var keyBytes = arguments[1].getEncoded();
toUtf8(tag, keyBytes);
toHex(tag, keyBytes);
toBase64(tag, keyBytes);
}
console.log("=======================================================");
return this.init.apply(this, arguments);
}
cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec').implementation = function () {
console.log("Cipher.init('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec') is called!");
var algorithm = this.getAlgorithm();
var tag = algorithm + " init Key";
var keyBytes = arguments[1].getEncoded();
toUtf8(tag, keyBytes);
toHex(tag, keyBytes);
toBase64(tag, keyBytes);
var tags = algorithm + " init iv";
var iv = Java.cast(arguments[2], Java.use("javax.crypto.spec.IvParameterSpec"));
var ivBytes = iv.getIV();
toUtf8(tags, ivBytes);
toHex(tags, ivBytes);
toBase64(tags, ivBytes);
console.log("=======================================================");
return this.init.apply(this, arguments);
}
cipher.doFinal.overload('java.nio.ByteBuffer', 'java.nio.ByteBuffer').implementation = function () {
console.log("Cipher.doFinal('java.nio.ByteBuffer', 'java.nio.ByteBuffer') is called!");
console.log("=======================================================");
return this.doFinal.apply(this, arguments);
}
cipher.doFinal.overload('[B', 'int').implementation = function () {
console.log("Cipher.doFinal('[B', 'int') is called!");
console.log("=======================================================");
return this.doFinal.apply(this, arguments);
}
cipher.doFinal.overload('[B', 'int', 'int', '[B').implementation = function () {
console.log("Cipher.doFinal('[B', 'int', 'int', '[B') is called!");
console.log("=======================================================");
return this.doFinal.apply(this, arguments);
}
cipher.doFinal.overload('[B', 'int', 'int', '[B', 'int').implementation = function () {
console.log("Cipher.doFinal('[B', 'int', 'int', '[B', 'int') is called!");
console.log("=======================================================");
return this.doFinal.apply(this, arguments);
}
cipher.doFinal.overload().implementation = function () {
console.log("Cipher.doFinal() is called!");
console.log("=======================================================");
return this.doFinal.apply(this, arguments);
}
cipher.doFinal.overload('[B').implementation = function () {
console.log("Cipher.doFinal('[B') is called!");
showStacks();
var algorithm = this.getAlgorithm();
var tag = algorithm + " doFinal data";
var data = arguments[0];
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
var result = this.doFinal.apply(this, arguments);
var tags = algorithm + " doFinal result";
toUtf8(tags, result);
toHex(tags, result);
toBase64(tags, result);
console.log("=======================================================");
return result;
}
cipher.doFinal.overload('[B', 'int', 'int').implementation = function () {
console.log("Cipher.doFinal('[B', 'int', 'int') is called!");
showStacks();
var algorithm = this.getAlgorithm();
var tag = algorithm + " doFinal data";
var data = arguments[0];
toUtf8(tag, data);
toHex(tag, data);
toBase64(tag, data);
var result = this.doFinal.apply(this, arguments);
var tags = algorithm + " doFinal result";
toUtf8(tags, result);
toHex(tags, result);
toBase64(tags, result);
console.log("=======================================================", arguments[1], arguments[2]);
return result;
}
});