在现代信息安全中,加密算法扮演着至关重要的角色。今天我们来聊聊两种常见的加密算法——RSA和AES,用通俗易懂的语言带大家理解它们的核心原理和优缺点。
核心原理: RSA是一种非对称加密算法,这意味着它使用一对密钥:公钥和私钥。通俗来说,公钥可以公开,用来加密信息;而私钥需要保密,用来解密信息。它的安全性主要依赖于一个数学难题:大整数的质因数分解。具体步骤如下:
优点:
缺点:
核心原理: AES是一种对称加密算法,这意味着它使用同一个密钥进行加密和解密。它基于一种叫做“分组密码”的方法,把数据分成固定大小的块(通常是128位),然后通过多个轮次的处理来加密数据。每轮处理包括以下步骤:
优点:
缺点:
RSA和AES是现代密码学中两种重要的加密算法,各有优缺点。RSA依赖于复杂的数学难题,安全性高但速度较慢;AES则以其高效的加密速度和广泛应用而著称,但在密钥管理上存在挑战。
RSA加密算法在实际应用中常常使用填充模式来确保数据的安全性和算法的有效性。
填充模式是为了使加密数据和公钥长度一致,并增加加密的安全性。
接下来我们看下主要的RSA填充模式:ENCRYPTION_OAEP
、ENCRYPTION_PKCS1
和ENCRYPTION_NONE
,以及常见的填充模式组合。
1. ENCRYPTION_OAEP(Optimal Asymmetric Encryption Padding)
2. ENCRYPTION_PKCS1(PKCS #1 v1.5 Padding)
3. ENCRYPTION_NONE(No Padding)
1. RSA/None/PKCS1Padding
2. RSA/ECB/PKCS1Padding
选择合适的填充模式需要根据具体应用场景来考虑:
RSA加密算法的填充模式是确保数据安全性和算法有效性的关键。ENCRYPTION_OAEP、ENCRYPTION_PKCS1和ENCRYPTION_NONE
各有优缺点和适用场景。在实际应用中,根据具体需求选择合适的填充模式,能够有效提升加密的安全性和性能。
AES(Advanced Encryption Standard)是一种广泛使用的对称加密算法,旨在替代原先的DES和3DES。AES凭借其高效的加密速度和强大的安全性,成为现代数据加密的首选。
接下来我们来看下AES的基本原理、工作模式、填充机制以及密钥和初始化向量(IV)的使用。
主要特点:
主要缺点:
AES加密需要:
AES解密需要:
1. 电码本模式(ECB)
2. 密码分组链接模式(CBC)
3. 计算器模式(CTR)
4. 密码反馈模式(CFB)
5. 输出反馈模式(OFB)
填充模式的必要性: 由于AES是一种块加密算法,处理的数据块必须是固定长度(128位),因此需要填充模式来确保数据长度符合要求。
常见填充模式:
密钥(Key):
初始化向量(IV):
RSA加密算法在Java中有多种实现方式,其中默认的实现方式是RSA/None/PKCS1Padding
。在实际应用中,为了确保安全性和兼容性,需要注意密钥长度、密钥格式以及密钥管理。
默认实现:RSA/None/PKCS1Padding
为什么选择PKCS1Padding?
PKCS1Padding是一种较为常用且广泛支持的填充方式,它通过添加随机填充数据,确保相同的数据每次加密结果不同,从而提高安全性。
推荐使用2048位或更长的密钥
创建RSA密钥对
package com.artisan.jasypt.rsa;
import java.io.UnsupportedEncodingException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;
/**
* @author 小工匠
* @version 1.0
* @mark: show me the code , change the world
*/
public class RsaTest {
/**
* 主程序入口,用于演示如何生成和打印RSA密钥对的公钥和私钥。
*
* @param args 命令行参数(未使用)
* @throws UnsupportedEncodingException 如果编码不被支持
*/
public static void main(String[] args) throws UnsupportedEncodingException {
// 生成2048位的RSA密钥对
KeyPair keyPair = getKeyPair(2048);
// 获取公钥
byte[] publicKey = getPublicKey(keyPair);
// 获取私钥
byte[] privateKey = getPrivateKey(keyPair);
// 打印编码后的公钥和私钥
System.out.println("Private Key: " + Base64.getEncoder().encodeToString(publicKey));
System.out.println("Public Key: " + Base64.getEncoder().encodeToString(privateKey));
}
/**
* 生成RSA算法的密钥对
* @param keyLength 密钥长度,用于初始化密钥生成器
* @return 生成的密钥对,包含公钥和私钥
*/
public static KeyPair getKeyPair(int keyLength) {
try {
// 实例化密钥对生成器,并指定算法为RSA
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
// 初始化密钥对生成器,设置密钥长度
keyPairGenerator.initialize(keyLength);
// 生成密钥对
return keyPairGenerator.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
// 当指定的加密算法不可用时,抛出运行时异常
throw new RuntimeException("生成密钥对时遇到异常" + e.getMessage());
}
}
/**
* 获取公钥
*
* @param keyPair 包含公钥和私钥的密钥对
* @return 公钥的字节数组形式
*/
public static byte[] getPublicKey(KeyPair keyPair) {
// 将密钥对中的公钥转换为RSAPublicKey类型
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
// 获取并返回公钥的编码形式
return rsaPublicKey.getEncoded();
}
/**
* 获取私钥
*
* @param keyPair 包含公钥和私钥的密钥对
* @return 返回私钥的字节数组形式
*/
public static byte[] getPrivateKey(KeyPair keyPair) {
// 将keyPair中的私钥转换为RSAPrivateKey类型
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
// 返回私钥的编码形式
return rsaPrivateKey.getEncoded();
}
}
package com.artisan.jasypt.rsa;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
/**
* @author 小工匠
* @version 1.0
* @mark: show me the code , change the world
*/
public class RSAKeyPairGenerator {
/**
* 主函数用于生成RSA算法的密钥对,并打印出其Base64编码的字符串形式。
*
* @param args 命令行参数(未使用)
* @throws NoSuchAlgorithmException 如果指定的加密算法不可用,则抛出此异常。
*/
public static void main(String[] args) throws NoSuchAlgorithmException {
// 创建RSA算法的密钥对生成器
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 初始化密钥对生成器,设置密钥长度为2048位
keyPairGen.initialize(2048);
// 生成密钥对
KeyPair pair = keyPairGen.generateKeyPair();
// 从密钥对中提取私钥和公钥
PrivateKey privateKey = pair.getPrivate();
PublicKey publicKey = pair.getPublic();
// 打印出私钥和公钥的Base64编码
System.out.println("Private Key: " + Base64.getEncoder().encodeToString(privateKey.getEncoded()));
System.out.println("Public Key: " + Base64.getEncoder().encodeToString(publicKey.getEncoded()));
}
}
密钥生成与存储的流程
密钥格式:DER和PEM
PEM格式的密钥示例
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr8p1oxcLljRG/Qffkh6N
...
-----END PUBLIC KEY-----
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCr8p1oxcLljRG/
...
-----END PRIVATE KEY-----
package com.artisan.jasypt.rsa;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
/**
* @author 小工匠
* @version 1.0
* @mark: show me the code , change the world
*/
public class KeyToPEM {
/**
* 主函数:生成RSA密钥对,并将其转换为PEM格式输出。
*
* @param args 命令行参数(未使用)
* @throws Exception 如果密钥生成或转换过程中发生错误
*/
public static void main(String[] args) throws Exception {
// 生成RSA密钥对,使用2048位长度
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
KeyPair keyPair = keyGen.generateKeyPair();
// 提取公钥和私钥
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 将公钥和私钥转换为PEM格式
String publicKeyPEM = convertToPEMFormat(publicKey.getEncoded(), "PUBLIC KEY");
String privateKeyPEM = convertToPEMFormat(privateKey.getEncoded(), "PRIVATE KEY");
// 输出转换后的PEM格式公钥和私钥
System.out.println(publicKeyPEM);
System.out.println(privateKeyPEM);
}
/**
* 将密钥字节数组转换为PEM格式的字符串。
* PEM(Privacy Enhanced Mail)格式是一种常见的密钥存储格式,以 base64 编码的密钥数据为主要内容,并以“-----BEGIN”和“-----END”为标记。
*
* @param key 密钥的字节数组。
* @param keyType 密钥的类型(如RSA PRIVATE KEY等)。
* @return 转换后的PEM格式密钥字符串。
*/
public static String convertToPEMFormat(byte[] key, String keyType) {
// 将密钥字节数组转换为Base64编码的字符串
String base64EncodedKey = Base64.getEncoder().encodeToString(key);
StringBuilder pemKey = new StringBuilder();
// 添加PEM格式的起始标记
pemKey.append("-----BEGIN ").append(keyType).append("-----\n");
// 将Base64编码的密钥拆分为64字符一组,并添加换行符
for (int i = 0; i < base64EncodedKey.length(); i += 64) {
pemKey.append(base64EncodedKey, i, Math.min(i + 64, base64EncodedKey.length())).append("\n");
}
// 添加PEM格式的结束标记
pemKey.append("-----END ").append(keyType).append("-----");
return pemKey.toString();
}
}
RSA加密在Java中的默认实现是RSA/None/PKCS1Padding
,推荐使用2048位或更长的密钥以确保安全。密钥管理是保证加密系统安全的重要环节,私钥应保存在服务器上,公钥分发给客户端。PEM格式的密钥更易于阅读和传输,通常用于存储和交换密钥。