《Java加密与解密的艺术》第3章java加密利器
java.security包详解
摘要 Digest
摘要类图
摘要使用示例
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.nio.charset.StandardCharsets;
public class MessageDigestExample {
public static void main(String[] args) {
String input = "Hello, World!";
try {
// 创建 MessageDigest 实例,指定算法为 SHA-256
MessageDigest digest = MessageDigest.getInstance("SHA-256");
// 将输入字符串转换为字节数组并传递给 digest
byte[] hashBytes = digest.digest(input.getBytes(StandardCharsets.UTF_8));
// 将字节数组转换为十六进制字符串
StringBuilder hexString = new StringBuilder();
for (byte b : hashBytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
// 输出哈希值
System.out.println("Input: " + input);
System.out.println("SHA-256 Hash: " + hexString.toString());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
密钥 Key
密钥类图
KeyGenerator使用示例
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class KeyGeneratorExample {
public static void main(String[] args) {
try {
// 1. 获取 KeyGenerator 实例,指定算法为 AES
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
// 2. 初始化 KeyGenerator,指定密钥长度(例如 128 位)
keyGen.init(128); // 也可以是 192 或 256,取决于 JCE 支持
// 3. 生成密钥
SecretKey secretKey = keyGen.generateKey();
// 4. 将密钥转换为字节数组
byte[] keyBytes = secretKey.getEncoded();
// 5. 将字节数组转换为 Base64 编码的字符串(便于显示和存储)
String base64Key = Base64.getEncoder().encodeToString(keyBytes);
// 输出生成的密钥
System.out.println("Generated AES Key (Base64): " + base64Key);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
byte[]还原秘钥Key示例
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class SecretKeyRestoreExample {
public static void main(String[] args) {
try {
// 1. 假设有一个字节数组形式的密钥(例如 AES 密钥)
String keyBase64 = "3q2+7w=="; // Base64 编码的密钥
byte[] keyBytes = Base64.getDecoder().decode(keyBase64);
// 2. 使用 SecretKeySpec 将字节数组还原为 SecretKey
SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");
// 3. 验证还原的密钥
System.out.println("Restored SecretKey Algorithm: " + secretKey.getAlgorithm());
System.out.println("Restored SecretKey Format: " + secretKey.getFormat());
System.out.println("Restored SecretKey (Base64): " +
Base64.getEncoder().encodeToString(secretKey.getEncoded()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
加密算法参数 AlgorithmParameters
AlgorithmParameters
是 Java 中用于管理和传递加密算法参数的类。它提供加密算法参数的不透明表示。它通常与加密算法(如 AES、DES 等)一起使用,用于存储和传递算法的初始化参数(如 IV(初始化向量)、盐值等)。
不透明表示:不可以直接访问参数域
透明表示:可以通过某个“get”来分别访问每个值
加密算法参数与byte[]相互转换示例
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class AlgorithmParametersExample {
public static void main(String[] args) {
try {
// 1. 生成 AES 密钥
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128); // 128 位密钥
SecretKey secretKey = keyGen.generateKey();
// 2. 初始化 AES 加密器(使用 CBC 模式,需要 IV)
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
// 3. 获取 AlgorithmParameters(包含 IV 等参数)
AlgorithmParameters params = cipher.getParameters();
// 4. 将 AlgorithmParameters 编码为字节数组(便于存储或传输)
byte[] encodedParams = params.getEncoded();
System.out.println("Encoded AlgorithmParameters (Base64): " +
Base64.getEncoder().encodeToString(encodedParams));
// 5. 解码 AlgorithmParameters
AlgorithmParameters decodedParams = AlgorithmParameters.getInstance("AES");
decodedParams.init(encodedParams);
// 6. 从 AlgorithmParameters 中提取 IV
IvParameterSpec ivSpec = decodedParams.getParameterSpec(IvParameterSpec.class);
System.out.println("IV (Base64): " +
Base64.getEncoder().encodeToString(ivSpec.getIV()));
// 7. 使用解码后的参数初始化解密器
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
System.out.println("AlgorithmParameters usage completed successfully.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
AlgorithmParameterGenerator 使用示例
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidParameterSpecException;
import java.util.Base64;
public class DESAlgorithmParameterGeneratorExample {
public static void main(String[] args) {
try {
// 1. 生成 DES 密钥
KeyGenerator keyGen = KeyGenerator.getInstance("DES");
SecretKey secretKey = keyGen.generateKey();
// 2. 获取 AlgorithmParameterGenerator 实例,指定算法为 DES
AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator.getInstance("DES");
// 3. 初始化 AlgorithmParameterGenerator(可以指定密钥大小,但 DES 固定为 56 位)
paramGen.init(56); // DES 的密钥大小固定为 56 位
// 4. 生成 AlgorithmParameters
AlgorithmParameters params = paramGen.generateParameters();
// 5. 将 AlgorithmParameters 转换为 IvParameterSpec(获取 IV)
IvParameterSpec ivSpec = params.getParameterSpec(IvParameterSpec.class);
// 6. 输出生成的 IV
System.out.println("Generated IV (Base64): " +
Base64.getEncoder().encodeToString(ivSpec.getIV()));
// 7. 使用密钥和 IV 初始化加密器
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
// 8. 加密数据
String plainText = "Hello, DES!";
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
System.out.println("Encrypted Data (Base64): " +
Base64.getEncoder().encodeToString(encryptedBytes));
// 9. 使用相同的密钥和 IV 初始化解密器
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
// 10. 解密数据
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
String decryptedText = new String(decryptedBytes);
System.out.println("Decrypted Text: " + decryptedText);
} catch (Exception e) {
e.printStackTrace();
}
}
}
密钥对KeyPair
KeyPairGenerator:用于生产新的秘钥对;
KeyFactory:用于转换秘钥数据为key对象
密钥对类图
KeyPairGenerator 使用示例
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class KeyPairGeneratorExample {
public static void main(String[] args) {
try {
// 1. 获取 KeyPairGenerator 实例,指定算法为 RSA
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 2. 初始化 KeyPairGenerator,指定密钥大小为 2048 位
keyPairGen.initialize(2048);
// 3. 生成密钥对
KeyPair keyPair = keyPairGen.generateKeyPair();
// 4. 获取公钥和私钥
byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
// 5. 将公钥和私钥转换为 Base64 编码的字符串(便于显示和存储)
String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKeyBytes);
String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKeyBytes);
// 6. 输出公钥和私钥
System.out.println("Generated RSA Key Pair:");
System.out.println("Public Key (Base64): " + publicKeyBase64);
System.out.println("Private Key (Base64): " + privateKeyBase64);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
KeyFactory 使用示例
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class KeyFactoryExample {
public static void main(String[] args) {
try {
// 1. 生成 RSA 密钥对
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048); // 2048 位密钥
KeyPair keyPair = keyPairGen.generateKeyPair();
// 2. 获取公钥和私钥的编码形式
byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
// 3. 将公钥和私钥编码为 Base64 字符串(便于显示和存储)
String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKeyBytes);
String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKeyBytes);
System.out.println("Original Public Key (Base64): " + publicKeyBase64);
System.out.println("Original Private Key (Base64): " + privateKeyBase64);
// 4. 使用 KeyFactory 还原公钥
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// 还原公钥
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyBase64));
PublicKey restoredPublicKey = keyFactory.generatePublic(publicKeySpec);
// 还原私钥
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyBase64));
PrivateKey restoredPrivateKey = keyFactory.generatePrivate(privateKeySpec);
// 5. 验证还原的密钥
System.out.println("Restored Public Key (Base64): " +
Base64.getEncoder().encodeToString(restoredPublicKey.getEncoded()));
System.out.println("Restored Private Key (Base64): " +
Base64.getEncoder().encodeToString(restoredPrivateKey.getEncoded()));
// 6. 检查还原的密钥是否与原始密钥一致
boolean isPublicKeyEqual = keyPair.getPublic().equals(restoredPublicKey);
boolean isPrivateKeyEqual = keyPair.getPrivate().equals(restoredPrivateKey);
System.out.println("Is Public Key Restored Correctly? " + isPublicKeyEqual);
System.out.println("Is Private Key Restored Correctly? " + isPrivateKeyEqual);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
}
}
}
签名Signature
Signature 使用示例
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import java.security.SignatureException;
public class SignatureDemo {
public static void main(String[] args) {
try {
// 生成密钥对
KeyPair keyPair = generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
// 要签名的数据
String data = "Hello, World!";
byte[] dataBytes = data.getBytes();
// 生成签名
byte[] signatureBytes = SignatureExample.signData(dataBytes, privateKey);
System.out.println("Signature: " + new String(signatureBytes));
// 验证签名
boolean isValid = SignatureExample.verifySignature(dataBytes, signatureBytes, publicKey);
System.out.println("Signature is valid: " + isValid);
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
}
// 生成密钥对
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // 密钥大小为2048位
return keyPairGenerator.generateKeyPair();
}
// 生成签名
public static byte[] signData(byte[] data, PrivateKey privateKey)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
// 验证签名
public static boolean verifySignature(byte[] data, byte[] signatureBytes, PublicKey publicKey)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
signature.update(data);
return signature.verify(signatureBytes);
}
}
时间戳Timestamp
创建Timestamp示例
import java.security.Timestamp;
import java.security.cert.CertPath;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class TimestampExample {
public static void main(String[] args) throws Exception {
// 1. 创建证书链
List<X509Certificate> certList = new ArrayList<>();
// 假设我们已经有一个 X.509 证书
X509Certificate cert = getSampleCertificate(); // 获取示例证书
certList.add(cert);
// 2. 创建 CertPath
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
CertPath certPath = certFactory.generateCertPath(certList);
// 3. 创建 Timestamp
Date timestampDate = new Date(); // 当前时间
Timestamp timestamp = new Timestamp(timestampDate, certPath);
// 4. 输出 Timestamp 信息
System.out.println("Timestamp Date: " + timestamp.getTimestamp());
System.out.println("Signer Cert Path: " + timestamp.getSignerCertPath());
}
// 模拟获取一个示例证书
private static X509Certificate getSampleCertificate() throws Exception {
// 这里可以使用 KeyPair 和自签名证书生成逻辑
// 以下是一个占位符,实际应用中需要从文件或密钥库加载证书
return null;
}
}
验证Timestamp示例
import java.security.Timestamp;
import java.security.cert.CertPath;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class TimestampVerifier {
public static void main(String[] args) throws Exception {
// 1. 创建证书链
List<X509Certificate> certList = new ArrayList<>();
X509Certificate cert = getSampleCertificate(); // 获取示例证书
certList.add(cert);
// 2. 创建 CertPath
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
CertPath certPath = certFactory.generateCertPath(certList);
// 3. 创建 Timestamp
Date timestampDate = new Date(); // 当前时间
Timestamp timestamp = new Timestamp(timestampDate, certPath);
// 4. 验证证书链
boolean isCertValid = verifyCertPath(certPath);
System.out.println("Certificate Chain is valid: " + isCertValid);
// 5. 验证时间戳是否在证书的有效期内
boolean isTimestampValid = verifyTimestamp(timestamp);
System.out.println("Timestamp is valid: " + isTimestampValid);
}
// 验证证书链的有效性
private static boolean verifyCertPath(CertPath certPath) {
// 这里可以添加证书链验证逻辑
// 例如,检查证书是否过期,是否由受信任的 CA 签发等
return true; // 假设证书链有效
}
// 验证时间戳是否在证书的有效期内
private static boolean verifyTimestamp(Timestamp timestamp) {
Date timestampDate = timestamp.getTimestamp();
CertPath certPath = timestamp.getSignerCertPath();
X509Certificate signerCert = (X509Certificate) certPath.getCertificates().get(0);
// 检查时间戳是否在证书的有效期内
return timestampDate.after(signerCert.getNotBefore()) &&
timestampDate.before(signerCert.getNotAfter());
}
// 模拟获取一个示例证书
private static X509Certificate getSampleCertificate() throws Exception {
// 这里可以使用 KeyPair 和自签名证书生成逻辑
// 以下是一个占位符,实际应用中需要从文件或密钥库加载证书
return null;
}
}
密钥库KeyStore
java.security.KeyStore
类用于管理密钥和证书。KeyStore
可以存储以下内容:
-
私钥(Private Key)
-
公钥证书(Public Key Certificate)
-
受信任的证书(Trusted Certificate)
创建 KeyStore 并存储密钥和证书示例
import java.io.FileOutputStream;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Date;
import javax.security.auth.x500.X500Principal;
public class KeyStoreExample {
public static void main(String[] args) throws Exception {
// 1. 创建 KeyStore
KeyStore keyStore = KeyStore.getInstance("JKS"); // JKS 是 Java 默认的 KeyStore 类型
keyStore.load(null, null); // 初始化一个空的 KeyStore
// 2. 生成密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // 2048 位密钥
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
// 3. 创建自签名证书
X509Certificate certificate = generateSelfSignedCertificate(keyPair, "CN=Test Certificate");
// 4. 将私钥和证书存储到 KeyStore
char[] password = "password".toCharArray(); // KeyStore 密码
KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(password);
KeyStore.PrivateKeyEntry privateKeyEntry = new KeyStore.PrivateKeyEntry(privateKey, new Certificate[]{certificate});
KeyStore.Entry entry = privateKeyEntry;
keyStore.setEntry("myPrivateKey", entry, entryPassword);
// 5. 将受信任的证书存储到 KeyStore
keyStore.setCertificateEntry("myTrustedCert", certificate);
// 6. 保存 KeyStore 到文件
try (FileOutputStream fos = new FileOutputStream("myKeystore.jks")) {
keyStore.store(fos, password);
}
System.out.println("KeyStore created and saved to myKeystore.jks");
}
// 生成自签名证书
private static X509Certificate generateSelfSignedCertificate(KeyPair keyPair, String dn) throws Exception {
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
X500Principal principal = new X500Principal(dn);
certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
certGen.setSubjectDN(principal);
certGen.setIssuerDN(principal); // 自签名
certGen.setNotBefore(new Date());
certGen.setNotAfter(new Date(System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000L)); // 1 年有效期
certGen.setPublicKey(keyPair.getPublic());
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
return certGen.generateX509Certificate(keyPair.getPrivate(), "BC"); // 使用 BouncyCastle 提供程序
}
}
从 KeyStore 加载密钥和证书示例
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
public class KeyStoreLoader {
public static void main(String[] args) throws Exception {
// 1. 加载 KeyStore
char[] password = "password".toCharArray(); // KeyStore 密码
KeyStore keyStore = KeyStore.getInstance("JKS");
try (FileInputStream fis = new FileInputStream("myKeystore.jks")) {
keyStore.load(fis, password);
}
// 2. 获取私钥
KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(password);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry("myPrivateKey", entryPassword);
PrivateKey privateKey = privateKeyEntry.getPrivateKey();
System.out.println("Private Key loaded: " + privateKey);
// 3. 获取证书
Certificate certificate = keyStore.getCertificate("myTrustedCert");
System.out.println("Certificate loaded: " + certificate);
}
}
javax.crypto 包详解
安全消息摘要Mac
Mac
类支持以下常见的 HMAC 算法:
-
HmacSHA256
-
HmacSHA512
-
HmacSHA1
-
HmacMD5
生成 HMAC 示例
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import java.util.Base64;
public class MacExample {
public static void main(String[] args) throws Exception {
// 1. 生成密钥
KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA256"); // 使用 HMAC-SHA256 算法
SecretKey secretKey = keyGen.generateKey();
// 2. 创建 Mac 实例
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKey);
// 3. 要计算 HMAC 的消息
String message = "Hello, World!";
byte[] messageBytes = message.getBytes();
// 4. 计算 HMAC
byte[] hmacBytes = mac.doFinal(messageBytes);
String hmacBase64 = Base64.getEncoder().encodeToString(hmacBytes);
System.out.println("HMAC: " + hmacBase64);
}
}
验证 HMAC 示例
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import java.util.Base64;
public class MacVerifier {
public static void main(String[] args) throws Exception {
// 1. 假设我们已经有一个密钥和 HMAC
SecretKey secretKey = getSecretKey(); // 获取密钥
String message = "Hello, World!";
byte[] messageBytes = message.getBytes();
String receivedHmacBase64 = "收到的 HMAC 值";
// 2. 创建 Mac 实例
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKey);
// 3. 计算本地 HMAC
byte[] localHmacBytes = mac.doFinal(messageBytes);
String localHmacBase64 = Base64.getEncoder().encodeToString(localHmacBytes);
// 4. 比较收到的 HMAC 和本地计算的 HMAC
if (receivedHmacBase64.equals(localHmacBase64)) {
System.out.println("HMAC 验证成功!");
} else {
System.out.println("HMAC 验证失败!");
}
}
// 模拟获取密钥
private static SecretKey getSecretKey() throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA256");
return keyGen.generateKey();
}
}
密钥生成器KeyGenerator
密钥协定KeyAgreement
KeyAgreement
类支持以下常见的密钥协商算法:
-
DH
(Diffie-Hellman) -
ECDH
(Elliptic Curve Diffie-Hellman)
生成密钥对示例
import javax.crypto.KeyAgreement;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
public class KeyAgreementExample {
public static void main(String[] args) throws Exception {
// 1. 生成 Alice 的密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
keyPairGenerator.initialize(2048); // 2048 位密钥
KeyPair aliceKeyPair = keyPairGenerator.generateKeyPair();
PrivateKey alicePrivateKey = aliceKeyPair.getPrivate();
PublicKey alicePublicKey = aliceKeyPair.getPublic();
// 2. 生成 Bob 的密钥对
KeyPair bobKeyPair = keyPairGenerator.generateKeyPair();
PrivateKey bobPrivateKey = bobKeyPair.getPrivate();
PublicKey bobPublicKey = bobKeyPair.getPublic();
// 3. Alice 和 Bob 进行密钥协商
byte[] aliceSharedSecret = generateSharedSecret(alicePrivateKey, bobPublicKey);
byte[] bobSharedSecret = generateSharedSecret(bobPrivateKey, alicePublicKey);
// 4. 验证双方生成的共享密钥是否相同
System.out.println("Alice's shared secret: " + bytesToHex(aliceSharedSecret));
System.out.println("Bob's shared secret: " + bytesToHex(bobSharedSecret));
System.out.println("Shared secrets match: " + java.util.Arrays.equals(aliceSharedSecret, bobSharedSecret));
}
// 生成共享密钥
private static byte[] generateSharedSecret(PrivateKey privateKey, PublicKey publicKey) throws Exception {
KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
keyAgreement.init(privateKey);
keyAgreement.doPhase(publicKey, true);
return keyAgreement.generateSecret();
}
// 将字节数组转换为十六进制字符串
private static String bytesToHex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b));
}
return result.toString();
}
}
秘密密钥工厂SecretKeyFactory
KeyGenerator:用于生产新的密钥;
SecretKeyFactory:用于转换密钥数据为key对象
byte[] 还原为密钥
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
public class SecretKeyFactoryExample {
public static void main(String[] args) {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecretKey secretKey1 = keyGenerator.generateKey();
// 1. 假设我们有一个字节数组表示的密钥
byte[] keyBytes = secretKey1.getEncoded();
// 2. 使用 SecretKeySpec 将字节数组转换为 SecretKey
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
System.out.println("SecretKeySpec: " + bytesToHex(secretKeySpec.getEncoded()));
// 3. 使用 SecretKeyFactory 将 SecretKeySpec 转换为 SecretKey
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("AES");
KeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
SecretKey secretKey = keyFactory.generateSecret(keySpec);
System.out.println("SecretKey: " + bytesToHex(secretKey.getEncoded()));
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
}
}
// 将字节数组转换为十六进制字符串
private static String bytesToHex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b));
}
return result.toString();
}
}
加密与解密Cipher
AES 加密和解密示例
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class CipherExample {
public static void main(String[] args) {
try {
// 1. 生成 AES 密钥
SecretKey secretKey = generateAESKey();
System.out.println("AES Key: " + Base64.getEncoder().encodeToString(secretKey.getEncoded()));
// 2. 生成初始化向量 (IV)
byte[] iv = new byte[16]; // AES 块大小为 16 字节
IvParameterSpec ivSpec = new IvParameterSpec(iv);
// 3. 要加密的数据
String plainText = "Hello, World!";
System.out.println("Plain Text: " + plainText);
// 4. 加密数据
byte[] encryptedBytes = encrypt(plainText, secretKey, ivSpec);
String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
System.out.println("Encrypted Text: " + encryptedText);
// 5. 解密数据
String decryptedText = decrypt(encryptedBytes, secretKey, ivSpec);
System.out.println("Decrypted Text: " + decryptedText);
} catch (Exception e) {
e.printStackTrace();
}
}
// 生成 AES 密钥
private static SecretKey generateAESKey() throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128); // 128 位密钥
return keyGen.generateKey();
}
// 加密数据
private static byte[] encrypt(String plainText, SecretKey secretKey, IvParameterSpec ivSpec) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // AES/CBC 模式
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
return cipher.doFinal(plainText.getBytes());
}
// 解密数据
private static String decrypt(byte[] encryptedBytes, SecretKey secretKey, IvParameterSpec ivSpec) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
return new String(decryptedBytes);
}
}
RSA 加密和解密示例
import javax.crypto.Cipher;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
public class CipherRSAExample {
public static void main(String[] args) {
try {
// 1. 生成 RSA 密钥对
KeyPair keyPair = generateRSAKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 2. 要加密的数据
String plainText = "Hello, RSA!";
System.out.println("Plain Text: " + plainText);
// 3. 加密数据
byte[] encryptedBytes = encrypt(plainText, publicKey);
String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
System.out.println("Encrypted Text: " + encryptedText);
// 4. 解密数据
String decryptedText = decrypt(encryptedBytes, privateKey);
System.out.println("Decrypted Text: " + decryptedText);
} catch (Exception e) {
e.printStackTrace();
}
}
// 生成 RSA 密钥对
private static KeyPair generateRSAKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // 2048 位密钥
return keyPairGenerator.generateKeyPair();
}
// 加密数据
private static byte[] encrypt(String plainText, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(plainText.getBytes());
}
// 解密数据
private static String decrypt(byte[] encryptedBytes, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
return new String(decryptedBytes);
}
}
密封对象SealedObject
javax.crypto.SealedObject
类用于将对象加密并封装为一个密封对象。它结合了 Cipher
的加密功能和对象的序列化功能,使得可以将任何可序列化的对象加密存储或传输。SealedObject 只能加密实现了 Serializable 接口的对象。
加密和解密对象示例
import javax.crypto.Cipher;
import javax.crypto.SealedObject;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.io.Serializable;
import java.security.NoSuchAlgorithmException;
public class SealedObjectExample {
public static void main(String[] args) {
try {
// 1. 生成 AES 密钥
SecretKey secretKey = generateAESKey();
System.out.println("AES Key: " + bytesToHex(secretKey.getEncoded()));
// 2. 创建一个可序列化的对象
MyObject myObject = new MyObject("Hello, SealedObject!", 123);
System.out.println("Original Object: " + myObject);
// 3. 加密对象
SealedObject sealedObject = encryptObject(myObject, secretKey);
System.out.println("Sealed Object: " + sealedObject);
// 4. 解密对象
MyObject decryptedObject = decryptObject(sealedObject, secretKey);
System.out.println("Decrypted Object: " + decryptedObject);
} catch (Exception e) {
e.printStackTrace();
}
}
// 生成 AES 密钥
private static SecretKey generateAESKey() throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128); // 128 位密钥
return keyGen.generateKey();
}
// 加密对象
private static SealedObject encryptObject(Serializable object, SecretKey secretKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return new SealedObject(object, cipher);
}
// 解密对象
private static MyObject decryptObject(SealedObject sealedObject, SecretKey secretKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return (MyObject) sealedObject.getObject(cipher);
}
// 将字节数组转换为十六进制字符串
private static String bytesToHex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b));
}
return result.toString();
}
// 定义一个可序列化的对象
static class MyObject implements Serializable {
private String message;
private int number;
public MyObject(String message, int number) {
this.message = message;
this.number = number;
}
@Override
public String toString() {
return "MyObject{" +
"message='" + message + '\'' +
", number=" + number +
'}';
}
}
}
java.security.spec包和javax.crypto.spec包详解
密要规范KeySpec
java.security.cert包详解
证书Certificate
使用 BouncyCastle 创建 X.509 证书
import org.bouncycastle.x509.X509V3CertificateGenerator;
import javax.security.auth.x500.X500Principal;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Date;
public class CreateCertificateExample {
public static void main(String[] args) throws Exception {
// 1. 生成密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // 2048 位密钥
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
// 2. 创建 X.509 证书
X509Certificate certificate = generateSelfSignedCertificate(keyPair, "CN=Test Certificate");
// 3. 使用 CertificateFactory 加载证书
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
byte[] certBytes = certificate.getEncoded();
X509Certificate loadedCertificate = (X509Certificate) certificateFactory.generateCertificate(
new java.io.ByteArrayInputStream(certBytes));
// 4. 输出证书信息
System.out.println("Subject: " + loadedCertificate.getSubjectX500Principal());
System.out.println("Issuer: " + loadedCertificate.getIssuerX500Principal());
System.out.println("Valid From: " + loadedCertificate.getNotBefore());
System.out.println("Valid Until: " + loadedCertificate.getNotAfter());
System.out.println("Serial Number: " + loadedCertificate.getSerialNumber());
System.out.println("Signature Algorithm: " + loadedCertificate.getSigAlgName());
System.out.println("Version: " + loadedCertificate.getVersion());
}
// 生成自签名证书
private static X509Certificate generateSelfSignedCertificate(KeyPair keyPair, String dn) throws Exception {
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
X500Principal principal = new X500Principal(dn);
// 设置证书信息
certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
certGen.setSubjectDN(principal);
certGen.setIssuerDN(principal); // 自签名
certGen.setNotBefore(new Date());
certGen.setNotAfter(new Date(System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000L)); // 1 年有效期
certGen.setPublicKey(keyPair.getPublic());
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
// 使用私钥签名证书
return certGen.generateX509Certificate(keyPair.getPrivate(), "BC"); // 使用 BouncyCastle 提供程序
}
}
将证书保存到文件
import java.io.FileOutputStream;
import java.security.cert.X509Certificate;
public class SaveCertificateExample {
public static void main(String[] args) throws Exception {
// 生成证书(参考前面的代码)
X509Certificate certificate = CreateCertificateExample.generateSelfSignedCertificate(
KeyPairGenerator.getInstance("RSA").generateKeyPair(), "CN=Test Certificate");
// 将证书保存到文件
try (FileOutputStream fos = new FileOutputStream("certificate.cer")) {
fos.write(certificate.getEncoded());
}
System.out.println("Certificate saved to certificate.cer");
}
}
使用 CertificateFactory 加载和解析 X.509 证书
import java.io.FileInputStream;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Date;
public class CertificateFactoryExample {
public static void main(String[] args) {
try {
// 1. 创建 CertificateFactory 实例
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 2. 从文件加载证书
FileInputStream fis = new FileInputStream("certificate.cer"); // 证书文件路径
Certificate certificate = certificateFactory.generateCertificate(fis);
fis.close();
// 3. 将证书转换为 X509Certificate
if (certificate instanceof X509Certificate) {
X509Certificate x509Certificate = (X509Certificate) certificate;
// 4. 输出证书信息
System.out.println("Subject: " + x509Certificate.getSubjectX500Principal());
System.out.println("Issuer: " + x509Certificate.getIssuerX500Principal());
System.out.println("Valid From: " + x509Certificate.getNotBefore());
System.out.println("Valid Until: " + x509Certificate.getNotAfter());
System.out.println("Serial Number: " + x509Certificate.getSerialNumber());
System.out.println("Signature Algorithm: " + x509Certificate.getSigAlgName());
System.out.println("Version: " + x509Certificate.getVersion());
// 5. 验证证书是否有效
Date currentDate = new Date();
if (currentDate.before(x509Certificate.getNotAfter()) && currentDate.after(x509Certificate.getNotBefore())) {
System.out.println("Certificate is valid.");
} else {
System.out.println("Certificate is expired or not yet valid.");
}
} else {
System.out.println("The certificate is not an X.509 certificate.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用 CertificateFactory 加载证书链
import java.io.FileInputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Iterator;
public class CertificateChainExample {
public static void main(String[] args) {
try {
// 1. 创建 CertificateFactory 实例
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 2. 从文件加载证书链
FileInputStream fis = new FileInputStream("certificate-chain.pem"); // 证书链文件路径
Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(fis);
fis.close();
// 3. 遍历证书链
Iterator<? extends Certificate> iterator = certificates.iterator();
int index = 1;
while (iterator.hasNext()) {
Certificate certificate = iterator.next();
if (certificate instanceof X509Certificate) {
X509Certificate x509Certificate = (X509Certificate) certificate;
System.out.println("Certificate #" + index + ":");
System.out.println(" Subject: " + x509Certificate.getSubjectX500Principal());
System.out.println(" Issuer: " + x509Certificate.getIssuerX500Principal());
System.out.println(" Valid From: " + x509Certificate.getNotBefore());
System.out.println(" Valid Until: " + x509Certificate.getNotAfter());
System.out.println(" Serial Number: " + x509Certificate.getSerialNumber());
System.out.println(" Signature Algorithm: " + x509Certificate.getSigAlgName());
System.out.println(" Version: " + x509Certificate.getVersion());
index++;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
证书撤销列表CRL
CRL:证书撤销列表,
X509CRL:标明类型为X.509的CRL
X509CRLEntry:用于表示CRL中已撤销的证书
使用 X509CRL 加载和解析 CRL
import java.io.FileInputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509CRL;
import java.security.cert.X509CRLEntry;
import java.util.Iterator;
import java.util.Set;
public class X509CRLExample {
public static void main(String[] args) {
try {
// 1. 创建 CertificateFactory 实例
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 2. 从文件加载 CRL
FileInputStream fis = new FileInputStream("crl.pem"); // CRL 文件路径
X509CRL crl = (X509CRL) certificateFactory.generateCRL(fis);
fis.close();
// 3. 输出 CRL 信息
System.out.println("Issuer: " + crl.getIssuerX500Principal());
System.out.println("This Update: " + crl.getThisUpdate());
System.out.println("Next Update: " + crl.getNextUpdate());
System.out.println("CRL Number: " + crl.getExtensionValue("2.5.29.20")); // CRL 编号扩展
// 4. 遍历吊销的证书条目
Set<? extends X509CRLEntry> revokedCertificates = crl.getRevokedCertificates();
if (revokedCertificates != null) {
Iterator<? extends X509CRLEntry> iterator = revokedCertificates.iterator();
while (iterator.hasNext()) {
X509CRLEntry entry = iterator.next();
System.out.println("Serial Number: " + entry.getSerialNumber());
System.out.println("Revocation Date: " + entry.getRevocationDate());
System.out.println("Reason: " + entry.getRevocationReason()); // 吊销原因
}
} else {
System.out.println("No revoked certificates in this CRL.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
生成 CRL(使用 BouncyCastle)
import org.bouncycastle.asn1.x509.CRLNumber;
import org.bouncycastle.asn1.x509.CRLReason;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.cert.X509v2CRLBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
import org.bouncycastle.cert.jcajce.JcaX509v2CRLBuilder;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.cert.X509CRL;
import java.util.Date;
public class GenerateCRLExample {
public static void main(String[] args) throws Exception {
// 1. 生成密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); // 2048 位密钥
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
// 2. 创建 CRL 生成器
X509v2CRLBuilder crlBuilder = new JcaX509v2CRLBuilder(
new org.bouncycastle.asn1.x500.X500Name("CN=Example CA, OU=Example CA Org, O=Example CA Org, L=Example CA City, ST=Example CA State, C=US"),
new Date()
);
// 3. 添加 CRL 扩展
crlBuilder.addExtension(Extension.cRLNumber, false, new CRLNumber(BigInteger.ONE));
// 4. 添加吊销的证书条目
crlBuilder.addCRLEntry(
BigInteger.valueOf(1234567890L), // 吊销证书的序列号
new Date(), // 吊销日期
CRLReason.privilegeWithdrawn // 吊销原因
);
// 5. 使用私钥签名 CRL
X509CRL crl = new JcaX509CRLConverter().getCRL(
crlBuilder.build(new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(privateKey))
);
// 6. 输出 CRL 信息
System.out.println("Issuer: " + crl.getIssuerX500Principal());
System.out.println("This Update: " + crl.getThisUpdate());
System.out.println("Next Update: " + crl.getNextUpdate());
System.out.println("CRL Number: " + crl.getExtensionValue("2.5.29.20")); // CRL 编号扩展
// 7. 保存 CRL 到文件
try (java.io.FileOutputStream fos = new java.io.FileOutputStream("generated_crl.pem")) {
fos.write(crl.getEncoded());
}
System.out.println("CRL saved to generated_crl.pem");
}
}
证书链CertPath
构建证书路径
import java.io.FileInputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
public class CertPathExample {
public static void main(String[] args) {
try {
// 1. 创建 CertificateFactory 实例
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 2. 加载证书文件
List<X509Certificate> certificates = new ArrayList<>();
certificates.add(loadCertificate(certificateFactory, "cert1.cer")); // 终端实体证书
certificates.add(loadCertificate(certificateFactory, "cert2.cer")); // 中间 CA 证书
certificates.add(loadCertificate(certificateFactory, "cert3.cer")); // 根 CA 证书
// 3. 构建 CertPath
CertPath certPath = certificateFactory.generateCertPath(certificates);
// 4. 输出 CertPath 信息
System.out.println("CertPath Type: " + certPath.getType());
System.out.println("CertPath Length: " + certPath.getCertificates().size());
for (java.security.cert.Certificate cert : certPath.getCertificates()) {
X509Certificate x509Cert = (X509Certificate) cert;
System.out.println("Subject: " + x509Cert.getSubjectX500Principal());
System.out.println("Issuer: " + x509Cert.getIssuerX500Principal());
System.out.println("Serial Number: " + x509Cert.getSerialNumber());
System.out.println("Valid From: " + x509Cert.getNotBefore());
System.out.println("Valid Until: " + x509Cert.getNotAfter());
System.out.println("-----");
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 从文件加载证书
private static X509Certificate loadCertificate(CertificateFactory certificateFactory, String filePath) throws Exception {
try (FileInputStream fis = new FileInputStream(filePath)) {
return (X509Certificate) certificateFactory.generateCertificate(fis);
}
}
}
验证证书路径
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.*;
import java.util.ArrayList;
import java.util.List;
public class CertPathValidationExample {
public static void main(String[] args) {
try {
// 1. 创建 CertificateFactory 实例
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 2. 加载证书文件
List<X509Certificate> certificates = new ArrayList<>();
certificates.add(loadCertificate(certificateFactory, "cert1.cer")); // 终端实体证书
certificates.add(loadCertificate(certificateFactory, "cert2.cer")); // 中间 CA 证书
certificates.add(loadCertificate(certificateFactory, "cert3.cer")); // 根 CA 证书
// 3. 构建 CertPath
CertPath certPath = certificateFactory.generateCertPath(certificates);
// 4. 加载受信任的根证书
KeyStore keyStore = KeyStore.getInstance("JKS");
try (FileInputStream fis = new FileInputStream("truststore.jks")) {
keyStore.load(fis, "password".toCharArray()); // 信任库密码
}
// 5. 创建 PKIXParameters
PKIXParameters params = new PKIXParameters(keyStore);
params.setRevocationEnabled(false); // 禁用吊销检查(可选)
// 6. 验证 CertPath
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
CertPathValidatorResult result = validator.validate(certPath, params);
System.out.println("CertPath validation succeeded: " + result);
} catch (Exception e) {
e.printStackTrace();
}
}
// 从文件加载证书
private static X509Certificate loadCertificate(CertificateFactory certificateFactory, String filePath) throws Exception {
try (FileInputStream fis = new FileInputStream(filePath)) {
return (X509Certificate) certificateFactory.generateCertificate(fis);
}
}
}
保存 CertPath 到文件
import java.io.FileOutputStream;
import java.security.cert.CertPath;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
public class SaveCertPathExample {
public static void main(String[] args) {
try {
// 1. 创建 CertificateFactory 实例
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 2. 加载证书文件
List<X509Certificate> certificates = new ArrayList<>();
certificates.add(loadCertificate(certificateFactory, "cert1.cer")); // 终端实体证书
certificates.add(loadCertificate(certificateFactory, "cert2.cer")); // 中间 CA 证书
certificates.add(loadCertificate(certificateFactory, "cert3.cer")); // 根 CA 证书
// 3. 构建 CertPath
CertPath certPath = certificateFactory.generateCertPath(certificates);
// 4. 保存 CertPath 到文件
try (FileOutputStream fos = new FileOutputStream("certpath.pem")) {
fos.write(certPath.getEncoded());
}
System.out.println("CertPath saved to certpath.pem");
} catch (Exception e) {
e.printStackTrace();
}
}
// 从文件加载证书
private static X509Certificate loadCertificate(CertificateFactory certificateFactory, String filePath) throws Exception {
try (FileInputStream fis = new FileInputStream(filePath)) {
return (X509Certificate) certificateFactory.generateCertificate(fis);
}
}
}
文件中加载 CertPath
import java.io.FileInputStream;
import java.security.cert.CertPath;
import java.security.cert.CertificateFactory;
public class LoadCertPathExample {
public static void main(String[] args) {
try {
// 1. 创建 CertificateFactory 实例
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 2. 从文件加载 CertPath
try (FileInputStream fis = new FileInputStream("certpath.pem")) {
CertPath certPath = certificateFactory.generateCertPath(fis);
// 3. 输出 CertPath 信息
System.out.println("CertPath Type: " + certPath.getType());
System.out.println("CertPath Length: " + certPath.getCertificates().size());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}