密码学基础,算法自吐,非标准加密对抗
1.什么是密码学?
密码学(cryptography)是一种将信息表述为不可读的方式,并使用一种秘密的方法将信息恢复出来的科学。密码学提供的最基本的服务是数据机密性服务,就是使通信双方可以互相发送消息,并且避免他人窃取消息的内容。加密算法是密码学的核心。
明文:原始消息
密文:加密后的消息
加密:从明文到密文的变换过程
解密:从密文到明文的变换过程
密钥:相用来完成加解密等过程的秘密信息

2.常见编码
在android studio中如果无法运行java对gradle文件进行一下修改

1.Base64编码
CyberChef
定义:
Base64是一种用64个字符表示任意二进制数据的方法,是一种编码,并非加密字符编码,由 A-Z a-z 0-9 + / 和补充字符 “=” 组成,Base64编码后的字符数是4的倍数(不足会补”=”)
明文:
密文:
1
| Encoded string: Q0MxMzEzMTEzIQ==
|
逻辑实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import java.util.Base64;
public class Base64Example { public static void main(String[] args) { String text = "CC1313113!";
String encodedString = Base64.getEncoder().encodeToString(text.getBytes()); System.out.println("Encoded string: " + encodedString);
byte[] decodedBytes = Base64.getDecoder().decode(encodedString); String decodedString = new String(decodedBytes); System.out.println("Decoded string: " + decodedString); } }
|

自实现base64:
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| public class Base64Example { private static final String base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
public static void main(String[] args) { String originalInput = "吾爱破解论坛";
String encodedString = encodeBase64(originalInput.getBytes()); System.out.println("Encoded string: " + encodedString);
byte[] decodedBytes = decodeBase64(encodedString); String decodedString = new String(decodedBytes); System.out.println("Decoded string: " + decodedString); }
private static String encodeBase64(byte[] inputBytes) { StringBuilder sb = new StringBuilder(); int paddingCount = (3 - inputBytes.length % 3) % 3;
for (int i = 0; i < inputBytes.length; i += 3) { int b = ((inputBytes[i] & 0xFF) << 16) | ((i + 1 < inputBytes.length ? inputBytes[i + 1] & 0xFF : 0) << 8) | (i + 2 < inputBytes.length ? inputBytes[i + 2] & 0xFF : 0); sb.append(base64Chars.charAt((b >> 18) & 0x3F)).append(base64Chars.charAt((b >> 12) & 0x3F)).append(base64Chars.charAt((b >> 6) & 0x3F)).append(base64Chars.charAt(b & 0x3F)); }
for (int i = 0; i < paddingCount; i++) { sb.setCharAt(sb.length() - i - 1, '='); }
return sb.toString(); }
private static byte[] decodeBase64(String inputString) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); int paddingCount = 0;
for (int i = 0; i < inputString.length(); i += 4) { int b = (base64Chars.indexOf(inputString.charAt(i)) << 18) | (base64Chars.indexOf(inputString.charAt(i + 1)) << 12) | (i + 2 < inputString.length() && inputString.charAt(i + 2) != '=' ? base64Chars.indexOf(inputString.charAt(i + 2)) << 6 : 0) | (i + 3 < inputString.length() && inputString.charAt(i + 3) != '=' ? base64Chars.indexOf(inputString.charAt(i + 3)) : 0); bos.write((b >> 16) & 0xFF); bos.write((b >> 8) & 0xFF); bos.write(b & 0xFF);
if (inputString.charAt(i + 2) == '=') { paddingCount++; }
if (inputString.charAt(i + 3) == '=') { paddingCount++; } }
byte[] result = bos.toByteArray();
if (paddingCount > 0) { byte[] trimmedResult = new byte[result.length - paddingCount]; System.arraycopy(result, 0, trimmedResult, 0, trimmedResult.length); return trimmedResult; } else { return result; } } }
|
2.Hex编码
定义:
hex编码,又称十六进制编码(也称base16),一般用于方便人们查看二进制文件内容,它将字节数据中的每4个bit使用数字(0-9)、字母(A-F)共16个字符等效表示,由于一个字节有8个bit,所以一个字节会被编码为2个hex字符
PS:在 ASCII 编码中,只有0到127之间的数字是表示英文字母、数字和符号的,超出这个范围的字符需要使用其他编码方式,例如汉字就需要使用 UTF-8 或 UTF-16
明文:
密文:
1
| E590BEE788B1E7A0B4E8A7A3E8AEBAE59D9B
|
逻辑实现:
%02X
是一个格式化字符串,其中 %
是转义符,02
是最小宽度,表示输出的字符串至少包含两个字符,不足两个字符时用 0
填充,X
表示输出的字符集为大写的十六进制数。(算是一个特征)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public static void main(String[] args) { String input = "CC1313113!"; StringBuilder output = new StringBuilder(); byte[] bytes = input.getBytes(StandardCharsets.UTF_8); for (byte b : bytes) { output.append(String.format("%02X", b)); } System.out.println(output.toString()); }
public static String hexToString(String input) { byte[] bytes = new byte[input.length() / 2]; for (int i = 0; i < input.length(); i += 2) { bytes[i / 2] = (byte) Integer.parseInt(input.substring(i, i + 2), 16); } return new String(bytes, StandardCharsets.UTF_8); }
|

3.Unicode编码
定义:
Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。
明文:
密文:
1
| \u543E\u7231\u7834\u89E3\u8BBA\u575B
|
逻辑实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static String stringToUnicode(String input) { StringBuilder output = new StringBuilder(); for (int i = 0; i < input.length(); i++) { output.append(String.format("\\u%04X", (int) input.charAt(i))); } return output.toString(); }
public static String unicodeToString(String input) { StringBuilder output = new StringBuilder(); for (int i = 0; i < input.length(); i += 6) { String str = input.substring(i + 2, i + 6); output.append((char) Integer.parseInt(str, 16)); } return output.toString(); }
|

有些编译器可以将Unicode编码直接反编译出来,当然我的jeb显然没有自己还原编码(叹气,害)。

4.Byte数组
PS:常用于字符串加密
明文:
密文:
1
| [67, 67, 49, 51, 49, 51, 49, 49, 51, 33]
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.cc.xoseddemo1;
import java.nio.charset.StandardCharsets; import java.util.Arrays;
public class text { public static void main(String[] args) { String originalInput = "CC1313113!"; byte[] bytes = originalInput.getBytes(); System.out.println(Arrays.toString(bytes));
byte[] byteArray = new byte[]{67, 67, 49, 51, 49, 51, 49, 49, 51, 33}; String str = new String(byteArray); System.out.println(str); } }
|

3.加密算法
1.消息摘要算法&单向散列函数&哈希算法
定义:
单向散列函数算法也称Hash(哈希)算法(消息摘要算法),是一种将任意长度的消息压缩到某一固定长度(消息摘要)的函数(该过程不可逆)。 Hash函数可用于数字签名、 消息的完整性检测、消息起源的认证检测等。
常见的算法:MD5、HMAC、SHA-X(SHA-1,SHA-2)
MD5摘要
特性:
- 压缩性:无论数据长度是多少,计算出来的MD5值长度相同(16位、32位)
- 抗修改性:即便修改一个字节,计算出来的MD5值也会巨大差异

- 抗碰撞性:知道数据和MD5值,很小概率找到相同MD5值相同的原数据
- 易计算性:由原数据容易计算出MD5值(逆推)
明文:
密文:
1
| f80ca4900ca4b8a6e9b676bcc203d0d9
|
逻辑实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public static void main(String[] args) throws NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("MD5"); md.update("CC313113!".getBytes()); byte[] res = md.digest(); System.out.println(byteToHexString(res)); } public static String byteToHexString(byte[] by) { StringBuilder SB = new StringBuilder(); for (int k : by) { int j = k; if (k < 0) { j = k + 256; } if (j < 16) { SB.append("0"); } SB.append(Integer.toHexString(j)); } return SB.toString(); }
|

2.对称加密算法
定义:
加密和解密使用相同密钥的密码算法叫对称加解密算法,简称对称算法。对称算法速度快,通常在需要加密大量数据时使用。所谓对称,就是采用这种密码方法的双方使用同样的密钥进行加密和解密。

对称加密算法可以分为以下几种类型:
- DES(数据加密标准):DES是一种对称加密算法,使用56位密钥,将数据分成64位块,然后进行加密。由于DES的密钥长度比较短,易受到暴力破解攻击。
- 3DES(三重DES):3DES是基于DES算法的改进版本,使用三个56位的密钥,对数据进行三次加密,从而增加了加密强度。3DES比DES更加安全,但是加密速度较慢。
- AES(高级加密标准):AES是一种高级的对称加密算法,使用128、192或256位密钥,可以对不同长度的数据块进行加密。AES比DES和3DES更加安全,且加密速度更快。
- RC4:RC4是一种流加密算法,使用相同的密钥对数据进行加密和解密。RC4的密钥长度可以是40位、64位、128位等不同长度。RC4在实际应用中已经被证明存在漏洞,不再被推荐使用。
(1)AES加解密
明文:
密文:
1
| j94q+kL0+SlVpeGPYjAztA==
|
逻辑实现:
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
| import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class AES private static final String ALGORITHM = "AES"; private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding"; private static final String SECRET_KEY = "CC13131234567890";
public static void main(String[] args) throws Exception { String originalMessage = "CC1313113!"; byte[] encryptedMessage = encrypt(originalMessage); System.out.println("加密结果: " + Base64.getEncoder().encodeToString(encryptedMessage)); String decryptedMessage = decrypt(encryptedMessage); System.out.println("解密结果: " + decryptedMessage); }
private static byte[] encrypt(String message) throws Exception { SecretKeySpec key = new SecretKeySpec(SECRET_KEY.getBytes(), ALGORITHM); Cipher cipher = Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.ENCRYPT_MODE, key); return cipher.doFinal(message.getBytes()); }
private static String decrypt(byte[] encryptedMessage) throws Exception { SecretKeySpec key = new SecretKeySpec(SECRET_KEY.getBytes(), ALGORITHM); Cipher cipher = Cipher.getInstance(TRANSFORMATION);cipher.init(Cipher.DECRYPT_MODE, key); return new String(cipher.doFinal(encryptedMessage)); } }
|

(2)DES加解密
明文:
密文:
1
| 43N9cLCP1sTHGJRnh62iDw==
|
逻辑实现:
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
| import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class DES { private static final String ALGORITHM = "DES"; private static final String TRANSFORMATION = "DES/ECB/PKCS5Padding"; private static final String SECRET_KEY = "CC123456";
public static void main(String[] args) throws Exception { String originalMessage = "CC1313113!"; byte[] encryptedMessage = encrypt(originalMessage); System.out.println("加密结果: " + Base64.getEncoder().encodeToString(encryptedMessage)); String decryptedMessage = decrypt(encryptedMessage); System.out.println("解密结果: " + decryptedMessage); }
private static byte[] encrypt(String message) throws Exception { SecretKeySpec key = new SecretKeySpec(SECRET_KEY.getBytes(), ALGORITHM); Cipher cipher = Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.ENCRYPT_MODE, key); return cipher.doFinal(message.getBytes()); }
private static String decrypt(byte[] encryptedMessage) throws Exception { SecretKeySpec key = new SecretKeySpec(SECRET_KEY.getBytes(), ALGORITHM); Cipher cipher = Cipher.getInstance(TRANSFORMATION); cipher.init(Cipher.DECRYPT_MODE, key); return new String(cipher.doFinal(encryptedMessage)); } }
|

3.非对称加密算法
定义:
非对称加密,也称为公钥加密,使用两个不同的密钥进行加密和解密,这两个密钥是一对,一个被称为公钥,一个被称为私钥。公钥可以随意分发给任何需要通信的人,而私钥则只能由密钥持有者保留。在非对称加密中,公钥用于加密消息,而私钥用于解密消息,这使得非对称加密更加安全,因为即使公钥被泄露,也无法破解密文。
常见的非对称加密:RSA
RSA加解密
定义:
RSA是最具代表性的公钥密码体制。由于算法完善(既可用于数据加密又可用于数字签名)、安全性良好、易于实现和理解,RSA已成为一种应用极广的公钥密码体制,也是目前世界上唯一被广泛使用的公钥密码。在广泛的应用中,它不仅实现技术日趋成熟而且安全性逐渐得到证明。由此人们越发对RSA偏爱有加,并提出了许多基于RSA的加强或变形公钥密码体制。根据不同的应用需要,人们基于RSA算法开发了大量的加密方案与产品。

PS:RSA公钥加密的每次结果都不一样
明文:
密文:
1 2
| HNXogsqfIl4n0e2Tlk7iYi4AfDRD1kVIRBhBUjz0XxYrSqUixrDZ5Oox
|
逻辑实现:
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
| public class RSA { public static final String KEY_ALGORITHM = "RSA";
private static final String PUBLIC_KEY = "RSAPublicKey";
private static final String PRIVATE_KEY = "RSAPrivateKey";
private static final int MAX_ENCRYPT_BLOCK = 117;
private static final int MAX_DECRYPT_BLOCK = 128;
public static Map<String, Object> initKey(int keysize) throws Exception { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); keyPairGen.initialize(keysize); KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); Map<String, Object> keyMap = new HashMap<>(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; }
public static String getPublicKeyStr(Map<String, Object> keyMap) { Key key = (Key) keyMap.get(PUBLIC_KEY); return encryptBASE64(key.getEncoded()); }
public static String getPrivateKeyStr(Map<String, Object> keyMap) { Key key = (Key) keyMap.get(PRIVATE_KEY); return encryptBASE64(key.getEncoded()); }
public static PublicKey getPublicKey(String publicKeyString) throws NoSuchAlgorithmException, InvalidKeySpecException { byte[] publicKeyByte = Base64.getDecoder().decode(publicKeyString); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyByte); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); return keyFactory.generatePublic(keySpec); }
public static PrivateKey getPrivateKey(String privateKeyString) throws Exception { byte[] privateKeyByte = Base64.getDecoder().decode(privateKeyString); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyByte); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); return keyFactory.generatePrivate(keySpec); }
public static String encryptBASE64(byte[] key) { return new String(Base64.getEncoder().encode(key)); }
public static byte[] decryptBASE64(String key) { return Base64.getDecoder().decode(key); }
public static String encrypt1(String text, String publicKeyStr) { try {
System.out.println("明文字符串为:"+text); Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKeyStr)); byte[] tempBytes = cipher.doFinal(text.getBytes("UTF-8")); return Base64.getEncoder().encodeToString(tempBytes); } catch (Exception e) { throw new RuntimeException("加密字符串[" + text + "]时遇到异常", e); } }
public static String decrypt1(String secretText, String privateKeyStr) { try { Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKeyStr)); byte[] secretTextDecoded = Base64.getDecoder().decode(secretText.getBytes("UTF-8")); byte[] tempBytes = cipher.doFinal(secretTextDecoded); return new String(tempBytes); } catch (Exception e) { throw new RuntimeException("解密字符串[" + secretText + "]时遇到异常", e); } }
public static void main(String[] args) throws Exception { Map<String, Object> keyMap; String cipherText; String content = "CC1313113!";
keyMap = initKey(1024); String publicKey = getPublicKeyStr(keyMap); System.out.println("公钥:"+publicKey); String privateKey = getPrivateKeyStr(keyMap); System.out.println("私钥:"+privateKey);
cipherText = encrypt1(content, publicKey); System.out.println("加密后的密文:"+cipherText);
String plainText = decrypt1(cipherText, privateKey); System.out.println("解密后明文:"+plainText); }
}
|

RSA每一次跑出来的密文结果都不相同

总的来说,非对称加密比对称加密更加安全,但同时也更加计算密集和复杂,因此在实际应用中需要根据具体情况来选择合适的加密方式。常见的做法是使用对称加密算法加密数据,然后使用非对称加密算法加密对称加密算法使用的密钥,这样既保证了数据的安全性,又避免了非对称加密算法的资源消耗。
4.算法自吐
4.非标准加密算法
遇到不是常规的加密怎么办?
方法一:主动调用
方法二:扣算法
方法三:问问神奇的ChatGPT
推荐书目:
加密与解密(第4版)
Java加密与解密的艺术(第2版)
密码学原理与Java实现
文档:
安卓逆向中关于密码学、NDK开发(JNI调用)以及Java层逆向基础知识思维导图
密码学原理与Java实现
MD5加密概述,原理及实现
RSA 加解密(Java 实现)
密码学:RSA加密算法详解