使用过期的公共证书验证Java中的数字签名(PKCS#7)时出现问题。 有关更多详细信息,可以在.NET中签名数据然后在Java中验证,但在使用Java签名数据时会出现证书过期错误,并且在Java中验证< / strong>即可。在这两种情况下,我都使用相同的验证方法,相同的私钥和公共证书。
请告诉我原因?如果我想在验证数字签名时绕过证书过期验证,该怎么办?
谢谢,
C#.NET中的签名方法
private static string SignData(byte[] data, string pkcs12FileUrl, string pkcs12Password)
{
X509Certificate2 signerCert = new X509Certificate2(pkcs12FileUrl, pkcs12Password);
ContentInfo content = new ContentInfo(data);
SignedCms signed = new SignedCms(content, true);
CmsSigner signer = new CmsSigner(signerCert);
signer.IncludeOption = X509IncludeOption.None;
signed.ComputeSignature(signer);
return Convert.ToBase64String(signed.Encode());
}
Java中的Sign方法
public static String SignData(byte[] data, String pkcs12File, String pkcs12Password)
throws Exception
{
if(Security.getProvider("BC")==null)
{
Security.addProvider(new BouncyCastleProvider());
}
KeyStore keyStore = getPkcs12Info(pkcs12File, pkcs12Password);
Enumeration<String> aliasesList = keyStore.aliases();
String aliasName = "";
while (aliasesList.hasMoreElements())
{
aliasName = aliasesList.nextElement().toString();
}
X509Certificate signerCert = (X509Certificate) keyStore.getCertificate(aliasName);
PrivateKey privateKey = (PrivateKey) keyStore.getKey(aliasName,pkcs12Password.toCharArray());
CMSSignedDataGenerator Signer = new CMSSignedDataGenerator();
Signer.addSigner(privateKey, signerCert, CMSSignedDataGenerator.DIGEST_SHA1);
CMSProcessableByteArray digestContent = new CMSProcessableByteArray(data);
CMSSignedData Signed = Signer.generate(digestContent, false, "BC");
return Base64.encode(Signed.getEncoded());
}
private static KeyStore getPkcs12Info(String pkcs12File, String pkcs12Password) throws Exception
{
//KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(pkcs12File), pkcs12Password.toCharArray());
return keyStore;
}
验证Java中的方法
public static boolean VerifySignature(byte[] data, String digitalSignature, InputStream publicCertFile) throws Exception
{
if(Security.getProvider("BC")==null)
{
Security.addProvider(new BouncyCastleProvider());
}
CertificateFactory factory = CertificateFactory.getInstance("X509","BC");
X509Certificate publicCert = (X509Certificate)factory.generateCertificate(publicCertFile);
CMSProcessableByteArray digestContent = new CMSProcessableByteArray(data);
CMSSignedData Signed = new CMSSignedData(digestContent,Base64.decode(digitalSignature));
SignerInformation Signer=(SignerInformation)Signed.getSignerInfos().getSigners().iterator().next();
return Signer.verify(publicCert, "BC");
}
答案 0 :(得分:1)
如果您签署的证书已经过期,那么它已经毫无意义。证书已过期,不应用于新用途。验证签名证书已过期的文档是有意义的,因为至少您知道证书在签署文档时有效。除非它显然是由.NET签署的。听起来像.NET中的一个bug给我。
答案 1 :(得分:1)
我发现了这个主题Java implementation of C# SignedCms并尝试用Java更改我的Sign方法的代码。最后,它运作良好。这是我在Java中更新的代码
public static String SignData(byte[] data, String pkcs12File, String pkcs12Password)
throws Exception
{
ByteArrayOutputStream byteArrOut = new ByteArrayOutputStream();
DEROutputStream derOut = new DEROutputStream(byteArrOut);
try
{
if(Security.getProvider("BC")==null)
{
Security.addProvider(new BouncyCastleProvider());
}
KeyStore keyStore = getPkcs12Info(pkcs12File, pkcs12Password);
Enumeration<String> aliasesList = keyStore.aliases();
String aliasName = "";
while (aliasesList.hasMoreElements())
{
aliasName = aliasesList.nextElement().toString();
}
X509Certificate signerCert = (X509Certificate) keyStore.getCertificate(aliasName);
PrivateKey privateKey = (PrivateKey) keyStore.getKey(aliasName, pkcs12Password.toCharArray());
List certList = new ArrayList();
Store certs = new JcaCertStore(certList);
JcaSimpleSignerInfoGeneratorBuilder builder = new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setDirectSignature(true);
CMSSignedDataGenerator signer = new CMSSignedDataGenerator();
signer.addSignerInfoGenerator(builder.build("SHA1withRSA", privateKey, signerCert));
signer.addCertificates(certs);
CMSTypedData msg = new CMSProcessableByteArray(data);
CMSSignedData signed = signer.generate(msg, false);
derOut.writeObject(signed.toASN1Structure().toASN1Primitive());
return Base64.encode(byteArrOut.toByteArray());
}
catch(Exception ex)
{
throw ex;
}
finally
{
derOut.close();
byteArrOut.close();
}
}