为什么需要学习密码学
客户端发送给服务器的数据包中,有些参数不知道来源,可能是随机生成、标准算法加密的、自写算法加密的
安卓中,标准算法加密通常会出现在Java、so(C/C++)、JS中
Java有现成的系统API调用,开发者想要使用这些API,必须使用固定的方法名去访问。这些API也就是我们需要学习的内容。
C/C++没有现成的系统API调用,开发者要么自己去实现算法,要么调用别人写好的模块,算法的运行不依赖系统API,因此方法名可以混淆。你要做的就是根据各种标准算法的特征,去识别是否标准算法。这些算法的特征,就是我们需要学习的内容。
JS也没有现成的系统API调用,开发者一般使用CryptoJS、jsencrypt等第三方加密库来加密
重点学习
消息摘要算法(散列函数、哈希函数)
MD5、SHA、MAC
对称加密算法
DES、3DES、AES
非对称加密算法
RSA
数字签名算法
MD5withRSA、SHA1withRSA、SHA256withRSA
任何语言对于标准算法的实现都相同
H5APP
- H5的核心代码通常在JS文件中
解决方法:远程调试、修改JS代码注入代码
- WebView远程调试的要求
- 手机端的WebView版本要比电脑端的chrome版本低
- 手机端的WebView需要开启可调试
- 需要有一个科学上网的vpn,因为点击inspect时要去下载一些东西,不然打开是白屏
- 通常app中的WebView是不开启可调试的,需要通过Hook来开启Hook WebView
- H5的app也分很多种
- 纯JS发包,这时可以在远程调试工具上抓到包,也有相应JS代码
- 部分JS发包,部分Java发包,这时有些包可以在调试工具上抓到,有些不行,需要做额外的分析
比如:JS和Java如何相互调用,从这个角度入手,找Java里面的接口
加密可能部分在JS文件中,部分在Java中,说白了有些代码可以在调试工具中看到,有些代码是Java只能逆向app去找
- 纯Java发包,典型是uni-app。uni-app核心代码都在JS中
Hex编码
Hex编码是一种用16个字符表示任意二进制数据的方法是一种编码,而非加密
USC2编码、URL编码,其实与Hex编码差不多
python
public String hex(){
char[] result = new char[data.length*2];
int c=0;
for (byte b:data){
result[c++] = HEX_DIGITS[(b>>4) & 0xf];
result[c++] = HEX_DIGITS[b & 0xf];
}
return new String(result);
}
Hex编码的代码实现和码表
python
build.gradle
dependencies {
api 'com.squareup.okhttp3:okhttp:3.10.0'
}
//okio.ByteString
ByteString byteString = ByteString.of("100".getBytes());
byteString.hex();
Hex编码表的妙用
python
char[] HEX_DIGITS={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}
修改为
char[] HEX_DIGITS={'h','j','k','3','4','5','6','7','8','9','a','b','c','d','e','f'}
Hex编码特点
a) 用0-9 a-f 16个字符表示。
b) 每个十六进制字符代表4bit, 也就是2个十六进制字符代表一个字节。
c) 在实际应用中,比如密钥初始化,一定要分清楚传进去的密钥是哪种编码的,采用对应 方式解析,才能得到正确的结果
d) 编程中很多问题,需要从字节甚至二进制位的角度去考虑,才能明白
Base64编码
- 什么是Base64
Base64是一种用64个字符表示任意二进制数据的方法
是一种编码,而非加密
A-Z a-z 0-9 + / =
- Base64的应用
RSA密钥、加密后的密文、图片等数据中,会有一些不可见字符,直接转成文本传输的话,会有乱码、数据错误、数据丢失等情况出现,就可以使用Base64编码
- Base64的代码实现和码表
python
//java.util.Base64 码表 Android8.0以上可用
Base64.getEncoder().encodeToString("小肩膀".getBytes())
//android.util.Base64 码表
Base64.encodeToString
//okio.ByteString
build.gradle
dependencies {
api 'com.squareup.okhttp3:okhttp:3.10.0'
}
ByteString byteString = ByteString.of("100".getBytes());
byteString.base64(); //码表 okio.Base64 encode
- Base64码表的妙用
为了传输数据安全,通常会对Base64数据进行URL编码,或者会把+和/替换成-和_
- Base64编码细节
每个Base64字符代表原数据中的6bit
Base64编码后的字符数,是4的倍数
编码的字节数是3的倍数时,不需要填充
- Base64编码的特点
a) Base64编码是编码,不是压缩,编码后只会增加字节数
b) 算法可逆, 解码很方便, 不用于私密信息通信
c) 标准的Base64每行为76个字符,行末添加换行符
d) 加密后的字符串只有65种字符, 不可打印字符也可传输
e) 在Java层可以通过hook对应方法名来快速定位关键代码
f) 在so层可以通过输入输出的数据和码表来确定算法