Android常见加密算法实现

逆向的时候,经常会遇到各种加密算法,google查起来比较乱,这里整理下。

编码:base64、
哈希算法:md5、sha-1、sha-256
对称加密:AES、DES、3DES
非对称加密:RSA

一、常见算法的Android实现

base64

1
2
3
4
5
6
7
8
//编码
byte[] data = text.getBytes("UTF-8");
String base64 = Base64.encodeToString(data, Base64.DEFAULT);

//解码
String x = ""
byte[] data = Base64.decode(x, Base64.DEFAULT);
String text = new String(data, "UTF-8");

md5、sha-1、sha-256

写法都一样,区别在于MessageDigest.getInstance(“MD5”)指明要使用的算法,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fun md5(str: String): String {
val digest = MessageDigest.getInstance("MD5")
val result = digest.digest(str.toByteArray())
//没转16进制之前是16位
println("result${result.size}")
//转成16进制后是32字节
return toHex(result)
}

fun sha1(str:String): String {
val digest = MessageDigest.getInstance("SHA-1")
val result = digest.digest(str.toByteArray())
return toHex(result)
}

fun sha256(str:String): String {
val digest = MessageDigest.getInstance("SHA-256")
val result = digest.digest(str.toByteArray())
return toHex(result)
}

DES

这里DES加解密的区别只有一点,
cipher.init(Cipher.DECRYPT_MODE, securekey, sr),Cipher.DECRYPT_MODE为解密,Cipher.ENCRYPT_MODE为加密。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//DES加密
//DES加密的key必须是8个字节
String key="mykeysss";
// 生成一个可信任的随机数
SecureRandom sr = new SecureRandom();

// 从原始密钥数据创建DESKeySpec对象
DESKeySpec dks = new DESKeySpec(key.getBytes());

// 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(dks);

// Cipher对象实际完成加密操作
Cipher cipher = Cipher.getInstance("DES"); //默认为DES/ECB/PKCS5Padding

// 用密钥初始化Cipher对象
cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);

return cipher.doFinal(data);

//DES解密
//DES解密的key必须是8个字节
String key="mykeysss";
// 生成一个可信任的随机数源
SecureRandom sr = new SecureRandom();

// 从原始密钥数据创建DESKeySpec对象
DESKeySpec dks = new DESKeySpec(key.getBytes());

// 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(dks);

// Cipher对象实际完成解密操作
Cipher cipher = Cipher.getInstance("DES"); //默认为DES/ECB/PKCS5Padding

// 用密钥初始化Cipher对象
cipher.init(Cipher.DECRYPT_MODE, securekey, sr);

return cipher.doFinal(data);

AES

AES加解密的区别也是只有一个地方,cipher.init(Cipher.DECRYPT_MODE, skeySpec),Cipher.DECRYPT_MODE为解密,Cipher.ENCRYPT_MODE 加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//AES加密	
String key = "mysecret";
byte[] raw = key.getBytes("utf-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

//初始化cipher 算法/模式/补码方式
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

//加密
byte[] bytesContent;
byte[] enc = cipher.doFinal(bytesContent);
return enc;


//AES解密
//key相关
byte[] raw = key.getBytes("utf-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

//"算法/模式/补码方式" 初始化cipher
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);

//执行解密
byte[] bytesContent;
byte[] dec = cipher.doFinal(bytesContent);
return dec;

RSA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//秘钥长度为1024 生成公钥和私钥
KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair= keyPairGenerator.generateKeyPair();

//获取公钥 私钥
PublicKey publicKey=keyPair.getPublic();
PrivateKey privateKey=keyPair.getPrivate();

//公钥加密 java默认"RSA"="RSA/ECB/PKCS1Padding"
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encBytes = cipher.doFinal(bytesData);



//私钥解密 java默认"RSA"="RSA/ECB/PKCS1Padding"
Cipher cipher1=Cipher.getInstance("RSA");
cipher1.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decBytes = cipher1.doFinal(encBytes);
Log.d("xxx",new String(decBytes));

二、python实现

逆向时需要进行算法验证,比较讨厌java代码的写法,可以用python进行验证。

python base64

1
2
3
4
5
6
7
8
9
10
11
12
13
import base64

s = "mykey"
# 必须为byte类型
encoder = base64.b64encode(s.encode("utf-8"))
print(encoder) # byte类型 b'5oiR5piv5LiA5Liq5a2X56ym5Liy'
print(encoder.decode('utf-8')) # str类型 5oiR5piv5LiA5Liq5a2X56ym5Liy

# 解码过程
#参数为string类型
s = '5oiR5piv5LiA5Liq5a2X56ym5Liy'
decoder = base64.b64decode(s)
print(decoder.decode('utf-8')) # str类型

python DES

需要保证ECB或CBC模式、padmode与java实现一致。例如java的Cipher.getInstance(“DES”)默认为DES/ECB/PKCS5Padding模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pyDes import *

def des_encrypt(s):
secret_key = 'QExW+yCC'
iv = secret_key
k = des(secret_key, ECB, iv, pad=None, padmode=PAD_PKCS5)
en = k.encrypt(s, padmode=PAD_PKCS5)
return en


def des_descrypt(s):
secret_key = 'QExW+yCC'
iv = secret_key
k = des(secret_key, ECB, iv, pad=None, padmode=PAD_PKCS5)
de = k.decrypt(s, padmode=PAD_PKCS5)
return de

python AES

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#pip3 install pycryptodome
from Crypto.Cipher import AES
data = b"aaaaaaa"
key = b'Sixteen byte key'
cipher = AES.new(key, AES.MODE_EAX)
nonce = cipher.nonce
ciphertext, tag = cipher.encrypt_and_digest(data)
print(ciphertext, tag)


key = b'Sixteen byte key'
cipher = AES.new(key, AES.MODE_EAX, nonce=nonce)
plaintext = cipher.decrypt(ciphertext)
try:
cipher.verify(tag)
print("The message is authentic:", plaintext)
except ValueError:
print("Key incorrect or message corrupted")

python RSA

1
2
3
4
5
6
7
8
9
>>> from Crypto.PublicKey import RSA
>>>
>>> key = RSA.generate(2048)
>>> f = open('mykey.pem','wb')
>>> f.write(key.export_key('PEM'))
>>> f.close()
...
>>> f = open('mykey.pem','r')
>>> key = RSA.import_key(f.read())

三、openssl命令

使用openssl命令似乎更方便

base64

编码

1
echo m4bln | openssl base64

解码

1
echo YWJjCg== | openssl base64 -d

md5/sha1/sha256

1
2
3
echo abc | openssl md5
echo abc | openssl sha1
echo abc | openssl sha256

des/aes/rsa

待补充

参考资料:

  1. android官方文档-加密 https://developer.android.com/guide/topics/security/cryptography?hl=zh-cn
  2. frida hook AES DES RSA 自吐算法 https://zhuanlan.zhihu.com/p/320229007