作者:Python进阶者

来源:Python爬虫与数据挖掘

为什么要学习加密算法

在搞逆向进行抓包的时候,可以经常发现一些莫名其妙的字符串,可能是81dc9bdb52d04dc20036dbd8313ed055等之类的一长串字符,这些是怎么生成呢?

这些其实就是加密,加密算法主要分为两大类

标准加密算法任何语言中的实现,结果都是一样的。

应该是一样的,也可能不一样,如果不一样,说明更改了标准算法的某些变量,但是这种情况比较少。

非标准算法那就是自己写的了,这就具有很大的不确定性了,全靠程序员发挥!

注意:

  1. 在安卓逆向中,加密算法通常出现在Java层和C 中!
  2. 在Java层标准算法是有固定名字的,即使再混淆,固定名字是不能混淆的所以比较好处理!
  3. 在C 层标准加密算法是没有固定名字的,那就只能根据算法特征去识别了!
常用标准算法有哪些?
  1. 消息摘要算法(散列函数、哈希函数) MD5、SHA、MAC
  2. 对称加密算法 DES、3DES、AES
  3. 非对称加密算法 RSA
  4. 数字签名算法 MD5withRSA、SHA1withRSA、SHA256withRSA

因为本次主要是安卓逆向,所以就将常用的标准加密算法使用Android来复现一下!

我的环境

AndroidStudio 2020.3.1版本 Jdk 8版本

项目

CryptologyDemo.zip

Hex和Base64

Hex和Base64不是加密,它是一种编码!!!

Hex和Base64编码是加密算法中最常用的编码,任何加密算法最终都要选择它的表现形式,而Hex和Base64是最常用的!

添加依赖

api 'com.squareup.okhttp3:okhttp:3.10.0'

记得点击Sync Now

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(1)

Hex

Hex编码是一种用16个字符(0-9 a-f)表示任意二进制数据的方法!

它是一种编码,而非加密!

Hex主要应用在MD5等加密表现形式上。

代码

//从字符串到hex byte[] bytes = "zhangsan".getBytes(StandardCharsets.UTF_8); ByteString of = ByteString.of(bytes); String hex = of.hex(); Log.d(TAG, "hex:" hex);

示例

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(2)

Base64

Base64是一种用64个字符(A-Z a-z 0-9 / =)表示任意二进制数据的方法。

它是一种编码,而非加密。

相比较之下,Base64应用就广泛的很多,像图片,,长密文甚至文件,都采用Base64,因为可承载的数据很多!

代码

//从字符串到base64 byte[] bytes = "zhangsan".getBytes(StandardCharsets.UTF_8); ByteString of = ByteString.of(bytes); //方式一 String base64 = of.base64(); Log.d(TAG, "base64_1:" base64); //方式二 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { String s = Base64.getEncoder().encodeToString("zhangsan".getBytes(StandardCharsets.UTF_8)); byte[] encode = Base64.getEncoder().encode("zhangsan".getBytes(StandardCharsets.UTF_8)); Log.d(TAG, "base64_2:" s); Log.d(TAG, "base64_2:" new String(encode)); } //方式三 String s = android.util.Base64.encodeToString("zhangsan".getBytes(StandardCharsets.UTF_8),0); Log.d(TAG, "base64_3:" new String(s));

示例

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(3)

消息摘要算法

消息摘要算法最主要的特征!

密文是不可逆的!

不定长度输入,固定长度输出

加密结果唯一!

MD5

这就是最常用的md5加密,在update时压入数据,通过digest获得加密结果,md5一般通过hex展示加密结果!

MD系列算法

算法摘要长度实现MD2128Java6MD5128Java6MD5128Bouncy Castle

代码

//md5 public static String md5(String plainText) throws Exception { MessageDigest md5 = MessageDigest.getInstance("MD5"); //1. md5加密的数据可以直接放在digest中 //2. digest是加密之后的数据,但是有不可见字符,不要使用hex或base64来展示 md5.update(plainText.getBytes(StandardCharsets.UTF_8)); byte[] digest = md5.digest(); //1. 效果完全同上,update可以压入数据,区别是digest是一次性压入,update可以分批次压入 //byte[] digest = md5.digest(plainText.getBytes(StandardCharsets.UTF_8)); //使用hex和base64来表示加密之后的数据,因为直接加密的有不可见字符 ByteString of = ByteString.of(digest); String hex = of.hex(); String base64 = of.base64(); return hex "||" base64; }

示例

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(4)

SHA

常用的是sha-1算法,所以本次演示的是sha-1算法。

sha-1算法,甚至来说消息摘要算法基本上api都是通用的。

只需要换一个algorithm即可,所以就不废话了。

SHA系列算法

算法摘要长度实现SHA-1160Java6SHA-256256Java6SHA-384384Java6SHA-512512Java6SHA224224Bouncy Castle

代码

//SHA-1 public static String sha_1(String plainText) throws Exception { MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); sha1.update(plainText.getBytes(StandardCharsets.UTF_8)); byte[] digest = sha1.digest(); ByteString of = ByteString.of(digest); String hex = of.hex(); String base64 = of.base64(); return hex "||" base64; }

示例

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(5)

MAC

mac这个名字听着挺牛逼的,其实就是比md5和sha算法多了个密钥而已,不必大惊小怪。

MAC系列算法

算法消息摘要实现HmacMD5128Java6HmacSHA1160Java6HmacSHA256256Java6HmacSHA384384Java6HmacSHA512512Java6HmacMD2128Java6HmacMD4128Bouncy CastleHmacSHA224224Bouncy Castle

代码

public static String mac(String plainText) throws Exception { //生成密钥 SecretKeySpec hmacMD5 = new SecretKeySpec("123".getBytes(StandardCharsets.UTF_8), "HmacMD5"); //hmacMD5.getAlgorithm()表示获取算法,此时获取的就是HmacMD5 Mac instance = Mac.getInstance(hmacMD5.getAlgorithm()); //同上 //Mac instance = Mac.getInstance("HmacMD5"); //初始化 instance.init(hmacMD5); //压入数据 instance.update(plainText.getBytes(StandardCharsets.UTF_8)); byte[] doFinal = instance.doFinal(); //同上 //byte[] doFinal = instance.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); ByteString of = ByteString.of(doFinal); String hex = of.hex(); String base64 = of.base64(); return hex "||" base64; }

示例

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(6)

对称加密算法

虽然md5也叫加密算法,但是他是无法解密的,但是对称加密算法是可以进行加密和解密的,这就nice很多了。

因为加密和解密使用的密钥相同,所以叫做对称加密算法,那不同的,就是非对称咯!

注意了啊,对称加密算法的密钥是可以随便给的,但是有长度要求的,不是乱给的,但是加密的内容无限制。

各算法密钥长度

根据密钥长度不同AES又分为AES-128,AES-192,AES-256

DES

ECB和CBC模式主要区别在于CBC模式需要一个iv向量!

DES算法

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(7)

ECB模式加解密代码//DES ECB 加密 Cipherpublic static String des_encrypt_ECB(String plainText) throws Exception {//生成des所需要的keySecretKeySpec desKey = new SecretKeySpec("12345678".getBytes(StandardCharsets.UTF_8), "DES");//默认工作模式就是ECB,填充模式PKCS5Padding,//Cipher instance = Cipher.getInstance("DES");//也可以写全Cipher instance = Cipher.getInstance("DES/ECB/PKCS5Padding");//初始化,指定是加密模式还是解密模式和密钥instance.init(Cipher.ENCRYPT_MODE, desKey);//关于Cipher的update似乎有些问题,所以用doFinal的多//加密内容,返回结果byte[] doFinal = instance.doFinal(plainText.getBytes(StandardCharsets.UTF_8));ByteString of = ByteString.of(doFinal);String hex = of.hex();String base64 = of.base64();return hex "||" base64;}//DES ECB 解密public static String des_decrypt_ECB(byte[] cipherBytes) throws Exception {//生成des所需要的keySecretKeySpec desKey = new SecretKeySpec("12345678".getBytes(StandardCharsets.UTF_8), "DES");Cipher instance = Cipher.getInstance("DES/ECB/PKCS5Padding");instance.init(Cipher.DECRYPT_MODE, desKey);byte[] doFinal = instance.doFinal(cipherBytes);return new String(doFinal);}//ECBString des_encrypt_ECP = des_encrypt_ECB("zhangsan");Log.d(TAG, "des加密,ECP模式:" des_encrypt_ECP);//加密拿到的des加密,ECP模式base结果为:AtLfLL8jc1n uVm31GQvyw==byte[] bytes1 = ByteString.decodeBase64("AtLfLL8jc1n uVm31GQvyw==").toByteArray();String s1 = des_decrypt_ECB(bytes1);Log.d(TAG, "des解密,ECP模式:" s1);示例

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(8)

CBC模式加解密

CBC模式就比ECB多了个iv向量而已,其他用法一样。

代码

//DES CBC,需要iv向量 public static String des_encrypt_CBC(String plainText) throws Exception { SecretKeySpec desKey = new SecretKeySpec("12345678".getBytes(StandardCharsets.UTF_8), "DES"); Cipher instance = Cipher.getInstance("DES/CBC/PKCS5Padding"); //CBC需要iv向量 IvParameterSpec ivParameterSpec = new IvParameterSpec("12345678".getBytes()); //初始化时添加上iv向量 instance.init(Cipher.ENCRYPT_MODE, desKey,ivParameterSpec); byte[] doFinal = instance.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); ByteString of = ByteString.of(doFinal); String hex = of.hex(); String base64 = of.base64(); return hex "||" base64; } //DES CBC 解密 public static String des_decrypt_CBC(byte[] cipherBytes) throws Exception { //生成des所需要的key SecretKeySpec desKey = new SecretKeySpec("12345678".getBytes(StandardCharsets.UTF_8), "DES"); Cipher instance = Cipher.getInstance("DES/CBC/PKCS5Padding"); IvParameterSpec ivParameterSpec = new IvParameterSpec("12345678".getBytes()); instance.init(Cipher.DECRYPT_MODE, desKey,ivParameterSpec); byte[] doFinal = instance.doFinal(cipherBytes); return new String(doFinal); }

示例

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(9)

DESede(3DES/TripleDES)

DESede也分CBC和ECB,使用方法同上,这里将他们合二为一!

DESede算法

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(10)

代码//DESedepublic static String DESede_encrypt(String plainText) throws Exception {SecretKeySpec desKey = new SecretKeySpec("123456781234567812345678".getBytes(), "DESede");//ECB模式// Cipher instance = Cipher.getInstance("DESede/ECB/PKCS5Padding");// instance.init(Cipher.ENCRYPT_MODE, desKey);// byte[] doFinal = instance.doFinal(plainText.getBytes(StandardCharsets.UTF_8));//CBC模式需要iv向量Cipher instance = Cipher.getInstance("DESede/CBC/PKCS5Padding");IvParameterSpec ivParameterSpec = new IvParameterSpec("12345678".getBytes());//初始化时添加上iv向量instance.init(Cipher.ENCRYPT_MODE, desKey, ivParameterSpec);byte[] doFinal = instance.doFinal(plainText.getBytes(StandardCharsets.UTF_8));ByteString of = ByteString.of(doFinal);String hex = of.hex();String base64 = of.base64();return hex "||" base64;}//DESedepublic static String DESede_decrypt(byte[] cipherBytes) throws Exception {//生成des所需要的keySecretKeySpec desKey = new SecretKeySpec("123456781234567812345678".getBytes(StandardCharsets.UTF_8), "DESede");//ECB模式// Cipher instance = Cipher.getInstance("DESede/ECB/PKCS5Padding");// instance.init(Cipher.DECRYPT_MODE, desKey);// byte[] doFinal = instance.doFinal(cipherBytes);//CBC模式Cipher instance = Cipher.getInstance("DESede/CBC/PKCS5Padding");IvParameterSpec ivParameterSpec = new IvParameterSpec("12345678".getBytes());instance.init(Cipher.DECRYPT_MODE, desKey,ivParameterSpec);byte[] doFinal = instance.doFinal(cipherBytes);return new String(doFinal);}//DESedeString deSede_encrypt = DESede_encrypt("zhangsan");Log.d(TAG, "DESede加密:" deSede_encrypt);//AtLfLL8jc1n uVm31GQvyw==byte[] bytes3 = ByteString.decodeBase64("3M7YukhZweaysZBNnqYLBw==").toByteArray();String s3 = DESede_decrypt(bytes3);Log.d(TAG, "DESede解密:" s3);示例

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(11)

AES

AES算法是对称加密算法中最常用的算法!

AES也分CBC和ECB,这里也合二为一的!

AES算法

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(12)

代码public static String AES_encrypt(String plainText) throws Exception {SecretKeySpec secretKeySpec = new SecretKeySpec("0123456789abcdef".getBytes(), "AES");//ECB模式Cipher instance = Cipher.getInstance("AES/ECB/PKCS5Padding");instance.init(Cipher.ENCRYPT_MODE, secretKeySpec);byte[] doFinal = instance.doFinal(plainText.getBytes(StandardCharsets.UTF_8));//CBC模式需要iv向量// Cipher instance = Cipher.getInstance("DESede/CBC/PKCS5Padding");// IvParameterSpec ivParameterSpec = new IvParameterSpec("12345678".getBytes());// //初始化时添加上iv向量// instance.init(Cipher.ENCRYPT_MODE, desKey, ivParameterSpec);// byte[] doFinal = instance.doFinal(plainText.getBytes(StandardCharsets.UTF_8));ByteString of = ByteString.of(doFinal);String hex = of.hex();String base64 = of.base64();return hex "||" base64;}public static String AES_decrypt(byte[] cipherBytes) throws Exception {//生成des所需要的keySecretKeySpec secretKeySpec = new SecretKeySpec("0123456789abcdef".getBytes(), "AES");//ECB模式Cipher instance = Cipher.getInstance("AES/ECB/PKCS5Padding");instance.init(Cipher.DECRYPT_MODE, secretKeySpec);byte[] doFinal = instance.doFinal(cipherBytes);//CBC模式// Cipher instance = Cipher.getInstance("DESede/CBC/PKCS5Padding");// IvParameterSpec ivParameterSpec = new IvParameterSpec("12345678".getBytes());// instance.init(Cipher.DECRYPT_MODE, desKey, ivParameterSpec);// byte[] doFinal = instance.doFinal(cipherBytes);return new String(doFinal);}示例

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(13)

非堆成加密算法

非堆成加密算法中,最常用最典型的加密算法就是RSA。原来说过,对称加密算法是因为加密解密用的是同一个密钥,但是非对称就不是了。

它需要一堆,称为公钥和私钥,当然,密钥不是随便写的!

在线密钥生成网站:http://web.chacuo.net/netrsakeypair

RSARSA算法

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(14)

代码 //RSA//解析公钥key并返回public static PublicKey generatePublic(String publicKeyBase64) throws Exception {byte[] bytes = ByteString.decodeBase64(publicKeyBase64).toByteArray();X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(bytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");return keyFactory.generatePublic(x509EncodedKeySpec);}public static PrivateKey generatePrivate(String privateKeyBase64) throws Exception {byte[] bytes = ByteString.decodeBase64(privateKeyBase64).toByteArray();PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(bytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");return keyFactory.generatePrivate(pkcs8EncodedKeySpec);}//RSA 这里使用私钥解密public static String RSAPrivateDecrypt(byte[] cipherBytes) throws Exception {String BEGIN_PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMOVkFb2U8aOxLZr\n" "v/R/Vq/8 vB1fp4GnLLmBhH/g343Q5J6/9AVqbflgf9DRgzP/zBUoauRQnvfsUBt\n" "6NXKv3t2bkkAkA4ulCqk6 pxW/Zy03LyyADUtkBrDrTfGHqaw6vJSp0qjT56u563\n" "V0nOoUboUmj AIZRrzNEcwAKa7B1AgMBAAECgYB4oflDCe mGkzOTys4PIpVRe3o\n" "/i84fM NsD6yPyz1XlS5NlAuIg5qNI63yOCd6nR1dN26mn tM8159dCUfNcY1W3F\n" "JaTvBZKD5 6fDUKQ5UfHhlrd4rVxWKK kuhdYe67/Y6twrMzL/TE OXmn7jdxuq2\n" "Au93oa2kxraM6pGJCQJBAN/P ckCGRl26UraqzP3XwrVPq yGQUMb8y627MXwVJJ\n" "LsE3c9vuoDkm79rYN8jCXbxSkUbBpxopHYfdSxT/Dt8CQQDftlI8PZXDzJLlJAmm\n" "LynoC7OO52sdC PoqndJ04DDjo1rg6fcWaaIXFmOL/WTn5HJt8pa4r7vi54DChZ7\n" "ju8rAkBUBUSVdGctyxk7k6mv4Y7Zh0J4PNjtr0SNTBzMN//IP1cBDCs/hm655ecn\n" "dgJDKMx9tVV6hZqQ1JyUc7wLDtFrAkB1s6ZmvXw7jTnIR4KwJeZliSqKyGVJ3gSm\n" "WHH0rMv1l93 MEG0JJMC8ZvIvKD3b6Azwng8A0q0HAAh1z/m FgLAkEA0PahyHnX\n" "ZCzB5ic4QvkiKCqZ SyibYXOGxBGyCXkuirCwqrtaEorrFxgNEssdpHcEmk71 nv\n" "gvrL5QkvgcLvMA==";PrivateKey privateKey = generatePrivate(BEGIN_PRIVATE_KEY);Cipher instance = Cipher.getInstance("RSA/ECB/PKCS1Padding");instance.init(Cipher.DECRYPT_MODE,privateKey);byte[] doFinal = instance.doFinal(cipherBytes);return new String(doFinal);}//RSA 使用公钥加密public static String RSAPublicEncrypt(String plainText) throws Exception {String BEGIN_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDlZBW9lPGjsS2a7/0f1av/Prw\n" "dX6eBpyy5gYR/4N N0OSev/QFam35YH/Q0YMz/8wVKGrkUJ737FAbejVyr97dm5J\n" "AJAOLpQqpOvqcVv2ctNy8sgA1LZAaw603xh6msOryUqdKo0 eruet1dJzqFG6FJo\n" "/gCGUa8zRHMACmuwdQIDAQAB";PublicKey publicKey = generatePublic(BEGIN_PUBLIC_KEY);Cipher instance = Cipher.getInstance("RSA/ECB/PKCS1Padding");instance.init(Cipher.ENCRYPT_MODE,publicKey);byte[] doFinal = instance.doFinal(plainText.getBytes());ByteString of = ByteString.of(doFinal);return of.base64();}//RSA//加密String rsaPublicEncrypt = RSAPublicEncrypt("zhangsan");Log.d(TAG, "RSA加密:" rsaPublicEncrypt);//解密byte[] bytes5 = ByteString.decodeBase64(rsaPublicEncrypt).toByteArray();String rsaPrivateDecrypt = RSAPrivateDecrypt(bytes5);Log.d(TAG, "RSA解密:" rsaPrivateDecrypt);示例

android应用防护和逆向分析(盘点几个安卓逆向之常用加密算法)(15)

总结

本文讲述的加密算法主要分为三大类,也是最常用的几个加密算法。

经过比较发现,在Java中加密算法有几大特点

嗯,似乎你不太懂什么意思,意思就是可以通过类反推算法。

这样就可以完成自吐算法了,什么算法直接都一把梭哈了,后面再讲!

如果在操作过程中有任何问题,记得下面留言,我们看到会第一时间解决问题。

越努力,越幸运。

我是码农星期八,如果觉得还不错,记得动手点赞一下哈。

感谢你的观看。

本教程只用于学习探讨,不允许任何人使用技术进行违法操作!

,