作者:Python進階者
來源:Python爬蟲與數(shù)據(jù)挖掘
為什么要學(xué)習(xí)加密算法
在搞逆向進行抓包的時候,可以經(jīng)常發(fā)現(xiàn)一些莫名其妙的字符串,可能是81dc9bdb52d04dc20036dbd8313ed055等之類的一長串字符,這些是怎么生成呢?
這些其實就是加密,加密算法主要分為兩大類
- 標(biāo)準(zhǔn)加密算法
- 非標(biāo)準(zhǔn)加密算法
標(biāo)準(zhǔn)加密算法在任何語言中的實現(xiàn),結(jié)果都是一樣的。
是應(yīng)該是一樣的,也可能不一樣,如果不一樣,說明更改了標(biāo)準(zhǔn)算法的某些變量,但是這種情況比較少。
非標(biāo)準(zhǔn)算法那就是自己寫的了,這就具有很大的不確定性了,全靠程序員發(fā)揮!
注意:
常用標(biāo)準(zhǔn)算法有哪些?
因為本次主要是安卓逆向,所以就將常用的標(biāo)準(zhǔn)加密算法使用Android來復(fù)現(xiàn)一下!
我的環(huán)境
AndroidStudio 2020.3.1版本Jdk 8版本
項目
CryptologyDemo.zip
Hex和Base64
Hex和Base64不是加密,它是一種編碼?。?!
Hex和Base64編碼是加密算法中最常用的編碼,任何加密算法最終都要選擇它的表現(xiàn)形式,而Hex和Base64是最常用的!
添加依賴
api ‘com.squareup.okhttp3:okhttp:3.10.0’
記得點擊Sync Now
Hex
Hex編碼是一種用16個字符(0-9 a-f)表示任意二進制數(shù)據(jù)的方法!
它是一種編碼,而非加密!
Hex主要應(yīng)用在MD5等加密表現(xiàn)形式上。
代碼
//從字符串到hexbyte[] bytes = “zhangsan”.getBytes(StandardCharsets.UTF_8);ByteString of = ByteString.of(bytes);String hex = of.hex();Log.d(TAG, “hex:” + hex);
示例
Base64
Base64是一種用64個字符(A-Z a-z 0-9 + / =)表示任意二進制數(shù)據(jù)的方法。
它是一種編碼,而非加密。
相比較之下,Base64應(yīng)用就廣泛的很多,像圖片,,長密文甚至文件,都采用Base64,因為可承載的數(shù)據(jù)很多!
代碼
//從字符串到base64byte[] 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));
示例
消息摘要算法
消息摘要算法最主要的特征!
密文是不可逆的!
- 就是說,我在客戶端把密碼通過md5加密了,服務(wù)端也得采用相同的方式加密,進行比較。
不定長度輸入,固定長度輸出
- 就是說,不管是123,還是123456…經(jīng)過加密,加密的結(jié)果都是固定的長度!
加密結(jié)果唯一!
MD5
這就是最常用的md5加密,在update時壓入數(shù)據(jù),通過digest獲得加密結(jié)果,md5一般通過hex展示加密結(jié)果!
MD系列算法
算法摘要長度實現(xiàn)MD2128Java6MD5128Java6MD5128Bouncy Castle
代碼
//md5public static String md5(String plainText) throws Exception { MessageDigest md5 = MessageDigest.getInstance(“MD5”); //1. md5加密的數(shù)據(jù)可以直接放在digest中 //2. digest是加密之后的數(shù)據(jù),但是有不可見字符,不要使用hex或base64來展示 md5.update(plainText.getBytes(StandardCharsets.UTF_8)); byte[] digest = md5.digest(); //1. 效果完全同上,update可以壓入數(shù)據(jù),區(qū)別是digest是一次性壓入,update可以分批次壓入 //byte[] digest = md5.digest(plainText.getBytes(StandardCharsets.UTF_8)); //使用hex和base64來表示加密之后的數(shù)據(jù),因為直接加密的有不可見字符 ByteString of = ByteString.of(digest); String hex = of.hex(); String base64 = of.base64(); return hex + “||” + base64;}
示例
SHA
常用的是sha-1算法,所以本次演示的是sha-1算法。
sha-1算法,甚至來說消息摘要算法基本上api都是通用的。
只需要換一個algorithm即可,所以就不廢話了。
SHA系列算法
算法摘要長度實現(xiàn)SHA-1160Java6SHA-256256Java6SHA-384384Java6SHA-512512Java6SHA224224Bouncy Castle
代碼
//SHA-1public 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;}
示例
MAC
mac這個名字聽著挺牛逼的,其實就是比md5和sha算法多了個密鑰而已,不必大驚小怪。
MAC系列算法
算法消息摘要實現(xiàn)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); //壓入數(shù)據(jù) 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;}
示例
對稱加密算法
雖然md5也叫加密算法,但是他是無法解密的,但是對稱加密算法是可以進行加密和解密的,這就nice很多了。
因為加密和解密使用的密鑰相同,所以叫做對稱加密算法,那不同的,就是非對稱咯!
注意了啊,對稱加密算法的密鑰是可以隨便給的,但是有長度要求的,不是亂給的,但是加密的內(nèi)容無限制。
各算法密鑰長度
- RC4 密鑰長度1~256字節(jié)
- DES 密鑰長度8字節(jié)
- 3DES/DESede/TripleDES 密鑰長度24字節(jié)
- AES 密鑰長度16,24,32字節(jié)
根據(jù)密鑰長度不同AES又分為AES-128,AES-192,AES-256
DES
ECB和CBC模式主要區(qū)別在于CBC模式需要一個iv向量!
DES算法
ECB模式加解密代碼//DES ECB 加密 Cipherpublic static String des_encrypt_ECB(String plainText) throws Exception {//生成des所需要的keySecretKeySpec desKey = new SecretKeySpec(“12345678”.getBytes(StandardCharsets.UTF_8), “DES”);//默認(rèn)工作模式就是ECB,填充模式PKCS5Padding,//Cipher instance = Cipher.getInstance(“DES”);//也可以寫全Cipher instance = Cipher.getInstance(“DES/ECB/PKCS5Padding”);//初始化,指定是加密模式還是解密模式和密鑰instance.init(Cipher.ENCRYPT_MODE, desKey);//關(guān)于Cipher的update似乎有些問題,所以用doFinal的多//加密內(nèi)容,返回結(jié)果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結(jié)果為:AtLfLL8jc1n+uVm31GQvyw==byte[] bytes1 = ByteString.decodeBase64(“AtLfLL8jc1n+uVm31GQvyw==”).toByteArray();String s1 = des_decrypt_ECB(bytes1);Log.d(TAG, “des解密,ECP模式:” + s1);示例
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);}
示例
DESede(3DES/TripleDES)
DESede也分CBC和ECB,使用方法同上,這里將他們合二為一!
DESede算法
代碼//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);示例
AES
AES算法是對稱加密算法中最常用的算法!
AES也分CBC和ECB,這里也合二為一的!
AES算法
代碼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);}示例
非堆成加密算法
非堆成加密算法中,最常用最典型的加密算法就是RSA。原來說過,對稱加密算法是因為加密解密用的是同一個密鑰,但是非對稱就不是了。
它需要一堆,稱為公鑰和私鑰,當(dāng)然,密鑰不是隨便寫的!
在線密鑰生成網(wǎng)站:http://web.chacuo.net/netrsakeypair
- 公鑰加密,私鑰解密。
- 私鑰加密,公鑰解密。
- 一般公鑰是公開的,私鑰保密,私鑰包含公鑰。
- 加密安全,但是性能差,加密長度有限制。
- RSA可以用于加密解密,也可以用來數(shù)據(jù)簽名。
- Java中的私鑰必須是pkcs8格式。
RSA
RSA算法
代碼 //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” +”v/R/Vq/8+vB1fp4GnLLmBhH/g343Q5J6/9AVqbflgf9DRgzP/zBUoauRQnvfsUBt” +”6NXKv3t2bkkAkA4ulCqk6+pxW/Zy03LyyADUtkBrDrTfGHqaw6vJSp0qjT56u563″ +”V0nOoUboUmj+AIZRrzNEcwAKa7B1AgMBAAECgYB4oflDCe+mGkzOTys4PIpVRe3o” +”/i84fM+NsD6yPyz1XlS5NlAuIg5qNI63yOCd6nR1dN26mn+tM8159dCUfNcY1W3F” +”JaTvBZKD5+6fDUKQ5UfHhlrd4rVxWKK+kuhdYe67/Y6twrMzL/TE+OXmn7jdxuq2″ +”Au93oa2kxraM6pGJCQJBAN/P+ckCGRl26UraqzP3XwrVPq+yGQUMb8y627MXwVJJ” +”LsE3c9vuoDkm79rYN8jCXbxSkUbBpxopHYfdSxT/Dt8CQQDftlI8PZXDzJLlJAmm” +”LynoC7OO52sdC+PoqndJ04DDjo1rg6fcWaaIXFmOL/WTn5HJt8pa4r7vi54DChZ7″ +”ju8rAkBUBUSVdGctyxk7k6mv4Y7Zh0J4PNjtr0SNTBzMN//IP1cBDCs/hm655ecn” +”dgJDKMx9tVV6hZqQ1JyUc7wLDtFrAkB1s6ZmvXw7jTnIR4KwJeZliSqKyGVJ3gSm” +”WHH0rMv1l93+MEG0JJMC8ZvIvKD3b6Azwng8A0q0HAAh1z/m+FgLAkEA0PahyHnX” +”ZCzB5ic4QvkiKCqZ+SyibYXOGxBGyCXkuirCwqrtaEorrFxgNEssdpHcEmk71+nv” +”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” +”dX6eBpyy5gYR/4N+N0OSev/QFam35YH/Q0YMz/8wVKGrkUJ737FAbejVyr97dm5J” +”AJAOLpQqpOvqcVv2ctNy8sgA1LZAaw603xh6msOryUqdKo0+eruet1dJzqFG6FJo” +”/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);示例
總結(jié)
本文講述的加密算法主要分為三大類,也是最常用的幾個加密算法。
- 消息摘要算法(MD5,SHA1,MAC)
- 對稱加密算法(DES,DESede,AES)
- 非堆成加密算法(RSA)
經(jīng)過比較發(fā)現(xiàn),在Java中加密算法有幾大特點
- 通過MessageDigest類生成的算法有MD5,SHA1
- 通過Mac類生成的算法有MAC
- 通過Cipher生成的算法有DES,DESede,AES,RSA
嗯,似乎你不太懂什么意思,意思就是可以通過類反推算法。
這樣就可以完成自吐算法了,什么算法直接都一把梭哈了,后面再講!
如果在操作過程中有任何問題,記得下面留言,我們看到會第一時間解決問題。
越努力,越幸運。
我是碼農(nóng)星期八,如果覺得還不錯,記得動手點贊一下哈。
感謝你的觀看。
本教程只用于學(xué)習(xí)探討,不允許任何人使用技術(shù)進行違法操作!