Java手动实现完整的加密通信流程
字数 1441 2025-08-22 12:22:48
Java手动实现完整的加密通信流程教学文档
1. RSA加密基础
1.1 RSA算法概述
RSA是一种非对称加密算法,使用公钥加密、私钥解密。核心组成部分:
- 公钥(e, n):用于加密明文
- 私钥(d, n):用于解密密文
- 模数n:两个大质数p和q的乘积
1.2 数学基础
欧拉函数
φ(n) = (p-1)*(q-1)
如果n是质数,则φ(n) = n-1
欧拉定理
x^φ(n) ≡ 1 mod n
扩展欧几里得算法
用于计算两个整数的最大公约数(GCD)并找到整数解x和y,使得:
ax + by = gcd(a,b)
在RSA中用于求解私钥d,满足:
d × e ≡ 1 mod φ(n)
1.3 RSA密钥生成步骤
- 选择两个大质数p和q
- 计算n = p × q
- 计算φ(n) = (p-1)(q-1)
- 选择公钥指数e(通常为65537)
- 使用扩展欧几里得算法计算私钥d
- 公钥为(e, n),私钥为(d, n)
1.4 RSA明文长度限制
RSA加密的明文长度受限于模数n的字节长度:
- 2048位密钥(256字节):
- PKCS#1填充:最大明文245字节
- OAEP填充:最大明文214字节
2. RSA实现代码
2.1 质数生成
public static BigInteger getPrime(int bitLength) {
BigInteger p;
while (!(p = BigInteger.probablePrime(bitLength, random)).isProbablePrime(100)) {
continue;
}
return p;
}
2.2 密钥生成
public static BigInteger[] genRsaKey() {
BigInteger p, q, n, φ, d, e = BigInteger.valueOf(65537);
p = getPrime(200);
q = getPrime(200);
n = p.multiply(q);
φ = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
d = extGcd(e, φ)[0];
BigInteger[] result = new BigInteger[]{n, e, d};
if (d.compareTo(BigInteger.ONE) < 0 || !p.gcd(q).equals(BigInteger.ONE)) {
return genRsaKey();
}
return result;
}
2.3 扩展欧几里得算法
public static BigInteger[] extGcd(BigInteger a, BigInteger b) {
BigInteger[] result = null;
if (b.equals(BigInteger.ZERO)) {
result = new BigInteger[]{BigInteger.ONE, BigInteger.ZERO};
return result;
}
result = extGcd(b, a.mod(b));
BigInteger x = result[1];
BigInteger y = result[0].subtract(a.divide(b).multiply(x));
result = new BigInteger[]{x, y};
return result;
}
2.4 RSA加密/解密
// RSA加密
public static byte[] rsaEncrype(byte[] m, BigInteger n, BigInteger e) {
if (e == null) {
e = BigInteger.valueOf(65537);
}
return new BigInteger(m).modPow(e, n).toByteArray();
}
// RSA解密
public static byte[] rsaDecrype(byte[] c, BigInteger n, BigInteger d) {
return new BigInteger(c).modPow(d, n).toByteArray();
}
3. AES对称加密
3.1 AES概述
AES是一种对称加密算法,使用相同的密钥进行加密和解密。通常与RSA结合使用:
- RSA用于安全分发AES密钥
- AES用于实际通信内容加密
3.2 加密模式和填充方式
常见加密模式
- ECB:最简单的模式,每个块独立加密
- CBC:前一个密文块与当前块异或后再加密
- CFB:类似于CBC,更适合流加密
- OFB:加密器的输出作为下一个块的输入
- GCM:支持认证的加密模式,确保数据完整性
常见填充方式
- PKCS5Padding:缺少的字节填充为与块大小相同的数值
- ISO10126Padding:随机填充,最后一个字节指明填充字节数
- NoPadding:不使用填充,需自行确保数据是正确大小
3.3 AES实现代码
密钥和IV生成
// 随机生成16字节的IV
private static byte[] generateIV() {
byte[] iv = new byte[16]; // AES的IV是16字节
random.nextBytes(iv);
return iv;
}
// 填充或截断字符串以使其为16/32字节
private static String padTo16Bytes(String input) {
StringBuilder paddedInput = new StringBuilder(input);
int padding_le = 16;
if (input.length()>=16 && input.length()<=32 ) {
padding_le =32;
}
else if(input.length()>32)
return input.substring(0,32);
while (paddedInput.length() < padding_le) {
paddedInput.append((char)(random.nextInt(94)+32));
}
return paddedInput.toString();
}
AES加密/解密
private static final String aesMode = "AES/OFB/ISO10126Padding";
public static byte[] aesEncrypt(byte[] s, String k, byte[] iv) {
try {
Cipher c = Cipher.getInstance(aesMode);
c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(k.getBytes(), "AES"), new IvParameterSpec(iv));
return c.doFinal(s);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static byte[] aesDecrypt(byte[] s, String k, byte[] iv) {
try {
Cipher c = Cipher.getInstance(aesMode);
c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(k.getBytes(), "AES"), new IvParameterSpec(iv));
return c.doFinal(s);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
4. 完整加密通信流程
4.1 通信流程设计
-
密钥交换阶段:
- 服务器生成RSA密钥对
- 客户端获取服务器公钥(e, n)
- 客户端生成随机AES密钥
- 客户端用RSA公钥加密AES密钥并发送给服务器
- 服务器用RSA私钥解密获取AES密钥
-
加密通信阶段:
- 双方使用协商好的AES密钥进行对称加密通信
- 每次通信生成随机IV,与密文一起传输
4.2 优势分析
- 避免了AES密钥明文传输的风险
- 结合了RSA的安全密钥分发和AES的高效加密
- 在流量中无法直接获取私钥,提高了安全性
- 适用于后门与客户端的加密通信场景
5. 实际应用示例
5.1 密钥生成与分发
// 生成RSA密钥
BigInteger[] keys = genRsaKey();
BigInteger n = keys[0];
BigInteger privateKey = keys[2];
// 生成并加密AES密钥
String aesKey = "";
aesKey = padTo16Bytes(aesKey);
byte[] encryptedKey = rsaEncrype(aesKey.getBytes(), n, e);
// 解密AES密钥
byte[] decryptedKey = rsaDecrype(encryptedKey, n, privateKey);
5.2 加密通信
// 准备消息
String message = "test shellcode \\xfc\\xe8\\x89\\x00..........";
byte[] iv = generateIV();
// 加密
byte[] ciphertext = aesEncrypt(message.getBytes(), aesKey, iv);
// 解密
byte[] plaintext = aesDecrypt(ciphertext, aesKey, iv);
6. 安全注意事项
- RSA密钥长度应至少2048位
- AES密钥应足够随机且长度适当(128/192/256位)
- 每次加密应使用不同的IV
- 避免密钥硬编码
- 实现完整的错误处理和异常管理
- 考虑前向安全性设计
7. 总结
本文详细介绍了如何使用Java手动实现完整的加密通信流程,包括:
- RSA非对称加密的原理和实现
- AES对称加密的原理和实现
- 两种加密方式的结合使用
- 完整的密钥交换和加密通信流程
- 实际应用示例和安全注意事项
这种加密通信流程可以有效保护通信内容的安全,避免了密钥明文传输的风险,适用于各种需要安全通信的场景。