Java 安全 - 使用 Public 密钥的 X509 证书验证
Java Security - X509 Certificate Verification with Public Key
我正在做的一个项目有很多安全操作。我以前从未遇到过安全问题。因此,我的问题可以是初级水平。
在我的问题中,我得到一个字节数组数据,其中包含证书和一些其他参数。我需要验证此证书及其签名。但是我无法处理签名验证。事实上,我不知道应该使用哪个 public 密钥来验证。
代码如下。
感谢您的帮助..!
public boolean startValidation(PublicKey publicKey) {
CertificateFactory cf;
try {
cf = CertificateFactory.getInstance("X.509");
} catch (CertificateException e) {
e.printStackTrace();
return false;
}
try {
certificate = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(certBytes));
} catch (CertificateException e) {
e.printStackTrace();
setCertError(0);
return false;
}
if (!checkProvider()){
setCertError(1);
return false;
}
boolean[] usages = certificate.getKeyUsage();
boolean usage = usages[0] && usages[2];
if (!usage){
setCertError(2);
}
try {
certificate.checkValidity();
} catch (CertificateNotYetValidException e) {
e.printStackTrace();
setCertError(3);
return false;
} catch (CertificateExpiredException e) {
e.printStackTrace();
setCertError(4);
return false;
}
System.out.println("Sign Algorithm Name " + certificate.getSigAlgName());
//Output is SHA256WithRSAEncryption
// Problem area
try {
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initVerify(publicKey); //Should I use this certificate.getPublicKey() or what ??
if(signature.verify(certificate.getSignature())){
System.out.println("Accepted");
}else System.out.println("Failure");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
System.out.println("Public Key Format " + publicKey.getFormat() + "\nPublic Key Algorithm " + publicKey.getAlgorithm() );
System.out.println("Subject DN -> " + certificate.getSubjectDN().getName());
return true;
}
典型的 PKI 系统使用 Certificate Authorities 向主体颁发证书(通过签名)。通过签署证书颁发机构形成从 CA 到主体证书的链,如果 CA1(根 CA)发出 CA2 的(中间 CA[=31,则该链可以包含多个 CA =]) 证书,它又唱出主题的证书。这在 Internet(对于 SSL/TLS)和数字签名场景中很常见。
因此您很可能至少需要一个 CA 的证书,它是 public 验证主体证书的密钥。您的程序也可以支持多个独立的 CA。您的程序接受的 CA 通常称为 Trust Anchors. Keeping the Trust Anchors in a KeyStore 也很方便。
因此,您最终可能会得到一个包含信任锚和中间 CA 的密钥库。从那里开始,您需要形成链并验证 chin 中从根 CA(信任锚)到您要验证的主题证书的所有证书的签名。
为了正确的证书验证,除了链的签名之外,您还需要检查其他内容,例如密钥使用、基本约束、吊销信息等。所有这些都在证书路径的 RFC5280 中指定验证。
幸运的是,已经有 Java API 形式的 CertPath API 可以帮助您。一个适合您的用例的非常基本的示例是:
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
final X509Certificate certificateToCheck = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(certBytes));
final KeyStore trustStore = KeyStore.getInstance("JKS");
InputStream keyStoreStream = ...
trustStore.load(keyStoreStrem, "your password".toCharArray());
final CertPathBuilder certPathBuilder = CertPathBuilder.getInstance("PKIX");
final X509CertSelector certSelector = new X509CertSelector();
certSelector.setCertificate(certificateToCheck);
final CertPathParameters certPathParameters = new PKIXBuilderParameters(trustStore, certSelector);
final CertPathBuilderResult certPathBuilderResult = certPathBuilder.build(certPathParameters);
final CertPath certPath = certPathBuilderResult.getCertPath();
final CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX");
final PKIXParameters validationParameters = new PKIXParameters(trustStore);
validationParameters.setRevocationEnabled(true); // if you want to check CRL
final X509CertSelector keyUsageSelector = new X509CertSelector();
keyUsageSelector.setKeyUsage(new boolean[] { true, false, true }); // to check digitalSignature and keyEncipherment bits
validationParameters.setTargetCertConstraints(keyUsageSelector);
final PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult) certPathValidator.validate(certPath, validationParameters);
System.out.println(result);
但请注意,有许多 more nuances and details 必须妥善解决才能使实施真正安全。错误的证书路径检查是安全问题的常见原因。
我正在做的一个项目有很多安全操作。我以前从未遇到过安全问题。因此,我的问题可以是初级水平。
在我的问题中,我得到一个字节数组数据,其中包含证书和一些其他参数。我需要验证此证书及其签名。但是我无法处理签名验证。事实上,我不知道应该使用哪个 public 密钥来验证。
代码如下。 感谢您的帮助..!
public boolean startValidation(PublicKey publicKey) {
CertificateFactory cf;
try {
cf = CertificateFactory.getInstance("X.509");
} catch (CertificateException e) {
e.printStackTrace();
return false;
}
try {
certificate = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(certBytes));
} catch (CertificateException e) {
e.printStackTrace();
setCertError(0);
return false;
}
if (!checkProvider()){
setCertError(1);
return false;
}
boolean[] usages = certificate.getKeyUsage();
boolean usage = usages[0] && usages[2];
if (!usage){
setCertError(2);
}
try {
certificate.checkValidity();
} catch (CertificateNotYetValidException e) {
e.printStackTrace();
setCertError(3);
return false;
} catch (CertificateExpiredException e) {
e.printStackTrace();
setCertError(4);
return false;
}
System.out.println("Sign Algorithm Name " + certificate.getSigAlgName());
//Output is SHA256WithRSAEncryption
// Problem area
try {
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initVerify(publicKey); //Should I use this certificate.getPublicKey() or what ??
if(signature.verify(certificate.getSignature())){
System.out.println("Accepted");
}else System.out.println("Failure");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
System.out.println("Public Key Format " + publicKey.getFormat() + "\nPublic Key Algorithm " + publicKey.getAlgorithm() );
System.out.println("Subject DN -> " + certificate.getSubjectDN().getName());
return true;
}
典型的 PKI 系统使用 Certificate Authorities 向主体颁发证书(通过签名)。通过签署证书颁发机构形成从 CA 到主体证书的链,如果 CA1(根 CA)发出 CA2 的(中间 CA[=31,则该链可以包含多个 CA =]) 证书,它又唱出主题的证书。这在 Internet(对于 SSL/TLS)和数字签名场景中很常见。
因此您很可能至少需要一个 CA 的证书,它是 public 验证主体证书的密钥。您的程序也可以支持多个独立的 CA。您的程序接受的 CA 通常称为 Trust Anchors. Keeping the Trust Anchors in a KeyStore 也很方便。
因此,您最终可能会得到一个包含信任锚和中间 CA 的密钥库。从那里开始,您需要形成链并验证 chin 中从根 CA(信任锚)到您要验证的主题证书的所有证书的签名。
为了正确的证书验证,除了链的签名之外,您还需要检查其他内容,例如密钥使用、基本约束、吊销信息等。所有这些都在证书路径的 RFC5280 中指定验证。
幸运的是,已经有 Java API 形式的 CertPath API 可以帮助您。一个适合您的用例的非常基本的示例是:
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
final X509Certificate certificateToCheck = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(certBytes));
final KeyStore trustStore = KeyStore.getInstance("JKS");
InputStream keyStoreStream = ...
trustStore.load(keyStoreStrem, "your password".toCharArray());
final CertPathBuilder certPathBuilder = CertPathBuilder.getInstance("PKIX");
final X509CertSelector certSelector = new X509CertSelector();
certSelector.setCertificate(certificateToCheck);
final CertPathParameters certPathParameters = new PKIXBuilderParameters(trustStore, certSelector);
final CertPathBuilderResult certPathBuilderResult = certPathBuilder.build(certPathParameters);
final CertPath certPath = certPathBuilderResult.getCertPath();
final CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX");
final PKIXParameters validationParameters = new PKIXParameters(trustStore);
validationParameters.setRevocationEnabled(true); // if you want to check CRL
final X509CertSelector keyUsageSelector = new X509CertSelector();
keyUsageSelector.setKeyUsage(new boolean[] { true, false, true }); // to check digitalSignature and keyEncipherment bits
validationParameters.setTargetCertConstraints(keyUsageSelector);
final PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult) certPathValidator.validate(certPath, validationParameters);
System.out.println(result);
但请注意,有许多 more nuances and details 必须妥善解决才能使实施真正安全。错误的证书路径检查是安全问题的常见原因。