非对称加密通常以RSA算法为代表。对称加密的加密密钥和解密密钥相同, 而非对称加密的加密密钥和解密密钥不同,加密密钥可以公开而解密密钥需要保密。
RSA(非对称加密):RSA是一种常用的非对称加密算法,用于加密和解密敏感信息。Java中可以使用java.security包下的相关类进行RSA加密和解密操作。
RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,广泛用于数据加密和数字签名。RSA算法依赖于两个大质数的数学难题,即质因数分解的困难性。以下是RSA算法的详解以及在Java中的实现示例。
RSA的安全性:RSA算法的安全性依赖于大整数分解的困难性。使用较大的密钥长度(如2048位或以上)是保证安全的重要因素。
Java实现:Java的java.security包提供了方便的API用于RSA的密钥生成、加密解密和签名验证。
这个示例提供了一个基础的RSA算法的使用案例,你可以根据实际需求进行调整和扩展。
密钥长度:我们使用了2048位的密钥长度。密钥长度越长,安全性越高,但性能也会有所下降。
填充模式:在实际应用中,可能需要考虑使用不同的填充模式(如RSA/ECB/PKCS1Padding),以避免某些安全漏洞。
异常处理:示例代码中简化了异常处理,实际使用中应更全面地处理可能出现的异常。
性能:RSA加密和解密操作相对较慢,特别是对于大量数据的加密。通常,RSA用于加密较小的数据块(如密钥、签名等),而较大的数据块则使用对称加密算法(如AES)进行加密,RSA仅用于加密对称加密的密钥
- RSA算法的基本原理
1.1. 密钥生成
选择两个大质数 ( p ) 和 ( q )。
计算模数 ( n = p \times q )。( n ) 将用于生成公钥和私钥。
计算欧拉函数 ( \phi(n) = (p-1) \times (q-1) )。
选择公钥指数 ( e ),通常选择65537,它与 ( \phi(n) ) 互质,且计算效率高。
计算私钥指数 ( d ),使得 ( e \times d \equiv 1 \mod \phi(n) ),即 ( d ) 是 ( e ) 在模 ( \phi(n) ) 下的乘法逆元。
公钥:( (e, n) )
私钥:( (d, n) )
1.2. 加密和解密
加密:加密过程使用公钥,将明文 ( m ) 转换为密文 ( c ):
[
c = m^e \mod n
]
解密:解密过程使用私钥,将密文 ( c ) 转换回明文 ( m ):
[
m = c^d \mod n
]
1.3. 数字签名
签名:使用私钥对消息 ( m ) 生成签名 ( s ):
[
s = m^d \mod n
]
验证签名:使用公钥验证签名 ( s ) 是否由消息 ( m ) 生成:
[
m = s^e \mod n
]
2. Java中的RSA实现
2.1. Java生成RSA密钥对
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
public class RSAExample {
public static void main(String[] args) throws Exception {
// 初始化密钥对生成器
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048); // 密钥长度一般为2048位
// 生成密钥对
KeyPair keyPair = keyPairGen.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 输出公钥和私钥
System.out.println("Public Key: " + bytesToHex(publicKey.getEncoded()));
System.out.println("Private Key: " + bytesToHex(privateKey.getEncoded()));
}
// 辅助方法:将字节数组转换为十六进制字符串
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}
2.2. RSA加密和解密
import javax.crypto.Cipher;
public class RSAEncryptionDecryption {
public static void main(String[] args) throws Exception {
// 假设已经生成密钥对并取得publicKey和privateKey
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048);
KeyPair keyPair = keyPairGen.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 原始消息
String message = "Hello, RSA!";
// 加密
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedMessage = encryptCipher.doFinal(message.getBytes());
System.out.println("Encrypted Message: " + bytesToHex(encryptedMessage));
// 解密
Cipher decryptCipher = Cipher.getInstance("RSA");
decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedMessage = decryptCipher.doFinal(encryptedMessage);
System.out.println("Decrypted Message: " + new String(decryptedMessage));
}
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}
2.3. RSA签名和验证
import java.security.Signature;
public class RSASignatureExample {
public static void main(String[] args) throws Exception {
// 假设已经生成密钥对并取得publicKey和privateKey
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048);
KeyPair keyPair = keyPairGen.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 原始消息
String message = "Hello, RSA!";
// 签名
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initSign(privateKey);
sign.update(message.getBytes());
byte[] signature = sign.sign();
System.out.println("Signature: " + bytesToHex(signature));
// 验证签名
Signature verifySign = Signature.getInstance("SHA256withRSA");
verifySign.initVerify(publicKey);
verifySign.update(message.getBytes());
boolean isCorrect = verifySign.verify(signature);
System.out.println("Signature Verified: " + isCorrect);
}
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}