常用加解密算法 - RSA

RSA是一种非对称加密算法,在信息安全领域有着广泛的应用。下面将详细介绍其应用场景,并提供Java实现的示例。

一、RSA的主要应用场景

  1. 数据加密

    • 常用于对敏感信息(如用户密码、支付信息)进行加密传输。发送方用接收方的公钥加密数据,接收方用自己的私钥解密,确保数据仅能被指定接收者读取。
    • 例如:HTTPS协议中,客户端与服务器握手时,服务器会发送公钥给客户端,客户端用公钥加密对称加密的密钥,再传输给服务器,保障密钥交换的安全性。
  2. 数字签名

    • 用于验证信息的完整性和发送者的身份。发送方用私钥对信息的哈希值加密(生成签名),接收方用发送方的公钥解密签名并与信息的哈希值比对,若一致则说明信息未被篡改且来自合法发送者。
    • 例如:软件发布时,开发者会对安装包进行数字签名,用户可通过验证签名确认软件未被恶意篡改。
  3. 密钥交换

    • 在对称加密中,用于安全地交换对称密钥。由于对称加密效率高但密钥传输风险大,可先用RSA加密对称密钥,再传输给对方。
  4. 身份认证

    • 结合数字证书(如X.509证书),通过验证公钥与证书的绑定关系,确认实体身份。例如:网银U盾、SSH登录中的密钥认证。

二、Java实现RSA的示例

Java中可通过java.security包下的KeyPairGeneratorCipher等类实现RSA加密和解密。以下是完整示例:

1. 生成RSA密钥对(公钥和私钥)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.security.*;
import java.util.Base64;

public class RSAKeyGenerator {
public static void main(String[] args) throws NoSuchAlgorithmException {
// 初始化RSA密钥生成器,指定密钥长度(常用2048位)
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);

// 生成密钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();

// 转换为Base64编码的字符串,便于存储和传输
String publicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());
String privateKeyStr = Base64.getEncoder().encodeToString(privateKey.getEncoded());

System.out.println("公钥:" + publicKeyStr);
System.out.println("私钥:" + privateKeyStr);
}
}

2. RSA加密与解密工具类

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
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RSAUtil {
// 加密算法名称
private static final String ALGORITHM = "RSA";
// 加密模式和填充方式(需两端保持一致)
private static final String TRANSFORMATION = "RSA/ECB/PKCS1Padding";

/**
* 用公钥加密
* @param data 待加密数据
* @param publicKeyStr Base64编码的公钥
* @return 加密后的Base64字符串
*/
public static String encrypt(String data, String publicKeyStr) throws Exception {
// 解码公钥
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
PublicKey publicKey = keyFactory.generatePublic(keySpec);

// 加密
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedData = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedData);
}

/**
* 用私钥解密
* @param encryptedData 加密后的Base64字符串
* @param privateKeyStr Base64编码的私钥
* @return 解密后的原始数据
*/
public static String decrypt(String encryptedData, String privateKeyStr) throws Exception {
// 解码私钥
byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

// 解密
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedData = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
return new String(decryptedData, StandardCharsets.UTF_8);
}

public static void main(String[] args) throws Exception {
// 示例:使用前面生成的公钥和私钥(实际中需分别传递给发送方和接收方)
String publicKey = "此处替换为生成的公钥字符串";
String privateKey = "此处替换为生成的私钥字符串";

String originalData = "Hello, RSA!";
System.out.println("原始数据:" + originalData);

// 加密
String encrypted = encrypt(originalData, publicKey);
System.out.println("加密后:" + encrypted);

// 解密
String decrypted = decrypt(encrypted, privateKey);
System.out.println("解密后:" + decrypted);
}
}

三、注意事项

  1. 密钥长度:推荐使用2048位或以上(1024位已被认为不安全),密钥长度越长,安全性越高,但加密解密速度越慢。
  2. 填充方式:示例中使用PKCS1Padding,需确保加密和解密端使用相同的填充方式,否则会解密失败。
  3. 性能问题:RSA加密大文件效率低,实际应用中通常先对大文件用对称加密(如AES),再用RSA加密对称密钥。
  4. 密钥管理:私钥需严格保密,公钥可公开但需确保其真实性(避免被篡改),通常通过数字证书验证公钥合法性。

通过以上示例,可实现RSA的基本加密和解密功能,结合实际场景可扩展到数字签名等应用。