使用Java添加外部PKCS#1生成有效的CMS签名文件
基于此,我正在使用外部PKCS#1生成CMS签名文件使用Java添加外部PKCS#1生成有效的CMS签名文件,java,digital-signature,bouncycastle,pkcs#7,pkcs#1,Java,Digital Signature,Bouncycastle,Pkcs#7,Pkcs#1,基于此,我正在使用外部PKCS#1生成CMS签名文件 第一步是从要在外部应用程序中签名的原始文件中获取签名属性,该应用程序返回PKCS#1字节数组 然后使用原始文件散列、签名数据(PKCS#1)和证书构建标准org.bouncycastle.cms.SignerInfoGenerator以添加到cms,最后创建附加的签名 但当我尝试使用以下代码验证它时: String originalFile = "aG9sYQ0KYXNkYXMNCg0KYWZzDQo="; S
第一步是从要在外部应用程序中签名的原始文件中获取签名属性,该应用程序返回PKCS#1字节数组 然后使用原始文件散列、签名数据(PKCS#1)和证书构建标准org.bouncycastle.cms.SignerInfoGenerator以添加到cms,最后创建附加的签名 但当我尝试使用以下代码验证它时:
String originalFile = "aG9sYQ0KYXNkYXMNCg0KYWZzDQo=";
String cmsSignedFile = "MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBg...j2Dwytp6kzQNwtXGO8QbWty1lOo8oYm+6LR8EWba3ikO/m9ol/G808vit9gAAAAAAAA==";
byte[] signedByte = DatatypeConverter.parseBase64Binary(cmsSignedFile);
Security.addProvider(new BouncyCastleProvider());
CMSSignedData s = new CMSSignedData(new CMSProcessableByteArray(DatatypeConverter.parseBase64Binary(originalFile)), signedByte);
SignerInformationStore signers = s.getSignerInfos();
SignerInformation signerInfo = (SignerInformation)signers.getSigners().iterator().next();
FileInputStream fis = new FileInputStream("C:/myCertificate.cer");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificates(fis).iterator().next();
boolean result = signerInfo.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert.getPublicKey()));
System.out.println("Verified: "+result);
我得到验证:错误 我正在添加内容类型、签名时间、消息摘要和OCSP作为签名属性,TSP令牌作为未签名属性(我不确定这是否正确) 我还尝试使用以下代码从CMS签名恢复数据:
//load cms signed file with attached data
CMSSignedData cms = new CMSSignedData(FileUtils.readFileToByteArray(new File("C:/tmp/tempFile1864328163858309463.cms")));
System.out.println(cms.getSignerInfos().getSigners().iterator().next().getDigestAlgorithmID().getAlgorithm().getId());
System.out.println(Hex.encodeHexString(cms.getSignerInfos().getSigners().iterator().next().getSignature()));
//recover signer certificate info
Store certs = cms.getCertificates();
Collection<X509CertificateHolder> col = certs.getMatches(null);
X509CertificateHolder []h1 = col.toArray(new X509CertificateHolder[col.size()]);
X509CertificateHolder firmante = h1[0];
System.out.println(firmante.getSubject());
System.out.println(h1[1].getSubject());
SignerInformation sinfo = cms.getSignerInfos().getSigners().iterator().next();
//recover OCSP information
//THIS FAILS :(
// Store infocspbasic = cms.getOtherRevocationInfo(OCSPObjectIdentifiers.id_pkix_ocsp_basic);
// Object basic = infocspbasic.getMatches(null).iterator().next();
//recover signing time
if (sinfo.getSignedAttributes() != null) {
Attribute timeStampAttr = sinfo.getSignedAttributes().get(PKCSObjectIdentifiers.pkcs_9_at_signingTime);
ASN1Encodable attrValue = timeStampAttr.getAttrValues().getObjectAt(0);
final Date signingDate;
if (attrValue instanceof ASN1UTCTime) {
ASN1UTCTime time = ASN1UTCTime.getInstance(attrValue);
Date d = time.getDate();
System.out.println("ASN1UTCTime:" + d);
} else if (attrValue instanceof Time) {
signingDate = ((Time) attrValue).getDate();
} else if (attrValue instanceof ASN1GeneralizedTime) {
System.out.println("ASN1GeneralizedTimeASN1GeneralizedTime");
} else {
signingDate = null;
}
}
//recover timestamp TOken
//unsigned attributes are null :(
if (sinfo.getUnsignedAttributes() != null) {
Attribute timeStampAttr = sinfo.getUnsignedAttributes().get(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken);
for (ASN1Encodable value : timeStampAttr.getAttrValues().toArray()) {
TimeStampToken token = new TimeStampToken(new CMSSignedData(value.toASN1Primitive().getEncoded()));
System.out.println(token.getTimeStampInfo().getGenTime());
}
}
//加载带有附加数据的cms签名文件
CMSSignedData cms=新的CMSSignedData(FileUtils.readFileToByteArray(新文件(“C:/tmp/tempFile1864328163858309463.cms”));
System.out.println(cms.getSignerInfos().getSigners().iterator().next().getDigestAlgorithmID().getAlgorithm().getId());
System.out.println(十六进制编码HexString(cms.getSignerInfos().getSigners().iterator().next().getSignature());
//恢复签名者证书信息
存储证书=cms.getCertificates();
Collection col=certs.getMatches(null);
X509CertificateHolder[]h1=col.toArray(新X509CertificateHolder[col.size()]);
X509CertificateHolder firmante=h1[0];
System.out.println(firmante.getSubject());
System.out.println(h1[1].getSubject());
SignerInformation sinfo=cms.getSignerInfos().getSigners().iterator().next();
//恢复OCSP信息
//这失败了:(
//Store infocspbasic=cms.getOtherRevocationInfo(OCSPObjectIdentifiers.id\u pkix\u ocsp\u basic);
//Object basic=infocspbasic.getMatches(null.iterator().next();
//恢复签名时间
if(sinfo.getSignedAttribute()!=null){
属性timeStampAttr=sinfo.getSignedAttributes().get(PKCSObjectIdentifiers.pkcs_9_at_signingTime);
ASN1Encodable attrValue=timeStampAttr.getAttrValues().getObjectAt(0);
最终签署日期;
if(ASN1UTCTime的属性值实例){
ASN1UTCTime time=ASN1UTCTime.getInstance(attrValue);
Date d=time.getDate();
System.out.println(“ASN1UTCTime:+d”);
}else if(属性值instanceof Time){
signingDate=((时间)属性值).getDate();
}else if(ASN1GeneralizedTime的属性值实例){
System.out.println(“ASN1GeneralizedTimeASN1GeneralizedTime”);
}否则{
signingDate=null;
}
}
//恢复时间戳令牌
//未签名的属性为空:(
if(sinfo.getUnsignedAttributes()!=null){
属性timeStampAttr=sinfo.getUnsignedAttributes().get(PKCSObjectIdentifiers.id\u aa\u signatureTimeStampToken);
for(asn1可编码值:timestattr.getAttrValues().toArray()){
TimeStampToken token=新的TimeStampToken(新的CMSSignedData(value.toASN1Primitive().getEncoded());
System.out.println(token.getTimeStampInfo().getGenTime());
}
}
但我无法检索OCSP响应或TSP令牌信息。此外,我下载了以下内容以帮助验证:
任何帮助都将不胜感激。我发现了一个名为的项目,该项目使用外部PKCS 1实现CMS签名。该链接将转到该项目的论坛,在那里我发布了使用其类的代码示例和最终更正,以使验证生效