首个版本
This commit is contained in:
commit
ccf16c927d
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
7
.idea/encodings.xml
Normal file
7
.idea/encodings.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
5
.idea/inspectionProfiles/Project_Default.xml
Normal file
5
.idea/inspectionProfiles/Project_Default.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
</profile>
|
||||
</component>
|
14
.idea/misc.xml
Normal file
14
.idea/misc.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
64
pom.xml
Normal file
64
pom.xml
Normal file
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.sunyard.security</groupId>
|
||||
<artifactId>sm2-crl-checker</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
<version>1.70</version> <!-- 使用最新版本 -->
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- 编译插件 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- 打包所有依赖的插件 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.sunyard.security.Main</mainClass> <!-- 替换为你的主类 -->
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
145
src/main/java/com/sunyard/security/CRLValidator.java
Normal file
145
src/main/java/com/sunyard/security/CRLValidator.java
Normal file
@ -0,0 +1,145 @@
|
||||
package com.sunyard.security;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1InputStream;
|
||||
import org.bouncycastle.asn1.ASN1Integer;
|
||||
import org.bouncycastle.asn1.ASN1OctetString;
|
||||
import org.bouncycastle.asn1.x509.CRLNumber;
|
||||
import org.bouncycastle.asn1.x509.Extension;
|
||||
import org.bouncycastle.cert.X509CRLHolder;
|
||||
import org.bouncycastle.cert.X509CertificateHolder;
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.openssl.PEMParser;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileReader;
|
||||
import java.security.Security;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509CRL;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Date;
|
||||
|
||||
public class CRLValidator {
|
||||
|
||||
static {
|
||||
// 添加Bouncy Castle作为安全提供者
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 读取PEM格式的根证书
|
||||
*/
|
||||
/**
|
||||
* 读取证书文件,支持PEM和DER格式
|
||||
*/
|
||||
static X509Certificate readRootCertificate(String certPath) throws Exception {
|
||||
try (FileInputStream fis = new FileInputStream(certPath)) {
|
||||
// 首先尝试作为PEM文件读取
|
||||
if (certPath.toLowerCase().endsWith(".pem")) {
|
||||
try (FileReader reader = new FileReader(certPath);
|
||||
PEMParser pemParser = new PEMParser(reader)) {
|
||||
|
||||
Object obj = pemParser.readObject();
|
||||
if (obj instanceof X509CertificateHolder) {
|
||||
return new JcaX509CertificateConverter().getCertificate((X509CertificateHolder) obj);
|
||||
}
|
||||
throw new IllegalArgumentException("PEM文件不包含有效的X.509证书");
|
||||
}
|
||||
}
|
||||
// 否则作为DER格式二进制文件读取
|
||||
else {
|
||||
// 方法1:使用Java标准CertificateFactory(需要BC提供者)
|
||||
CertificateFactory certFactory = CertificateFactory.getInstance("X.509", "BC");
|
||||
return (X509Certificate) certFactory.generateCertificate(fis);
|
||||
|
||||
// 方法2:使用Bouncy Castle的X509CertificateHolder
|
||||
// fis.getChannel().position(0); // 重置流
|
||||
// X509CertificateHolder certificateHolder = new X509CertificateHolder(Streams.readAll(fis));
|
||||
// return new JcaX509CertificateConverter().getCertificate(certificateHolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取CRL文件
|
||||
*/
|
||||
public static X509CRL readCRLFile(String crlPath) throws Exception {
|
||||
try (FileInputStream fis = new FileInputStream(crlPath)) {
|
||||
// 对于PEM格式的CRL
|
||||
if (crlPath.endsWith(".pem")) {
|
||||
try (FileReader reader = new FileReader(crlPath);
|
||||
PEMParser pemParser = new PEMParser(reader)) {
|
||||
|
||||
Object obj = pemParser.readObject();
|
||||
if (obj instanceof X509CRLHolder) {
|
||||
return new JcaX509CRLConverter().getCRL((X509CRLHolder) obj);
|
||||
}
|
||||
throw new IllegalArgumentException("文件不包含有效的CRL");
|
||||
}
|
||||
}
|
||||
// 对于DER格式的CRL
|
||||
else if (crlPath.endsWith(".crl") || crlPath.endsWith(".der")) {
|
||||
return new JcaX509CRLConverter().getCRL(new X509CRLHolder(fis));
|
||||
} else {
|
||||
throw new IllegalArgumentException("不支持的CRL文件格式");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证CRL签名
|
||||
*/
|
||||
public static void verifyCRLSignature(X509Certificate issuerCert, X509CRL crl) throws Exception {
|
||||
try {
|
||||
crl.verify(issuerCert.getPublicKey());
|
||||
System.out.println("CRL签名验证成功");
|
||||
} catch (Exception e) {
|
||||
throw new SecurityException("CRL签名验证失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查CRL是否有效(未过期)
|
||||
*/
|
||||
public static void checkCRLValidity(X509CRL crl) {
|
||||
Date now = new Date();
|
||||
if (crl.getNextUpdate().before(now)) {
|
||||
throw new SecurityException("CRL已过期");
|
||||
}
|
||||
if (now.before(crl.getThisUpdate())) {
|
||||
throw new SecurityException("CRL尚未生效");
|
||||
}
|
||||
System.out.println("CRL在有效期内");
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印CRL信息
|
||||
*/
|
||||
public static void printCRLInfo(X509CRL crl) {
|
||||
System.out.println("CRL信息:");
|
||||
System.out.println("颁发者: " + crl.getIssuerX500Principal());
|
||||
System.out.println("本次更新时间: " + crl.getThisUpdate());
|
||||
System.out.println("下次更新时间: " + crl.getNextUpdate());
|
||||
|
||||
// 获取CRL编号(如果有)
|
||||
byte[] crlNumberExt = crl.getExtensionValue(Extension.cRLNumber.getId());
|
||||
if (crlNumberExt != null) {
|
||||
try {
|
||||
// 正确解析CRL编号扩展
|
||||
ASN1InputStream asn1In = new ASN1InputStream(crlNumberExt);
|
||||
ASN1OctetString octetString = (ASN1OctetString) asn1In.readObject();
|
||||
|
||||
ASN1InputStream asn1In2 = new ASN1InputStream(octetString.getOctets());
|
||||
ASN1Integer crlNumber = ASN1Integer.getInstance(asn1In2.readObject());
|
||||
|
||||
System.out.println("CRL编号: " + crlNumber.getPositiveValue());
|
||||
} catch (Exception e) {
|
||||
System.err.println("解析CRL编号时出错: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("吊销证书数量: " + crl.getRevokedCertificates().size());
|
||||
}
|
||||
}
|
40
src/main/java/com/sunyard/security/Main.java
Normal file
40
src/main/java/com/sunyard/security/Main.java
Normal file
@ -0,0 +1,40 @@
|
||||
package com.sunyard.security;
|
||||
|
||||
import java.security.cert.X509CRL;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
if ( args.length < 2 ) {
|
||||
System.out.println("用法: java -jar sm2-crl-checker-1.0-jar-with-dependencies <根证书路径> <CRL文件路径>");
|
||||
return;
|
||||
}
|
||||
|
||||
String rootCertPath = args[0];
|
||||
String crlFilePath = args[1];
|
||||
|
||||
|
||||
System.out.println("根证书路径: " + rootCertPath);
|
||||
System.out.println("CRL文件路径: " + crlFilePath);
|
||||
System.out.println("开始验证CRL...");
|
||||
|
||||
|
||||
// 1. 读取根证书
|
||||
X509Certificate rootCert = CRLValidator.readRootCertificate(rootCertPath);
|
||||
|
||||
// 2. 读取CRL文件
|
||||
X509CRL crl = CRLValidator.readCRLFile(crlFilePath);
|
||||
|
||||
// 3. 验证CRL签名
|
||||
CRLValidator.verifyCRLSignature(rootCert, crl);
|
||||
|
||||
// 4. 检查CRL是否有效(未过期)
|
||||
CRLValidator.checkCRLValidity(crl);
|
||||
|
||||
// 5. 可选:打印CRL信息
|
||||
CRLValidator.printCRLInfo(crl);
|
||||
|
||||
System.out.println("CRL验证结束!");
|
||||
}
|
||||
}
|
BIN
test/sm2Root_67B599D6E4B0C757A77D4886.cer
Normal file
BIN
test/sm2Root_67B599D6E4B0C757A77D4886.cer
Normal file
Binary file not shown.
BIN
test/sm2crl.crl
Normal file
BIN
test/sm2crl.crl
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user