Java 如何使用bouncy castle对签名数据进行签名?

Java 如何使用bouncy castle对签名数据进行签名?,java,encryption,cryptography,digital-signature,bouncycastle,Java,Encryption,Cryptography,Digital Signature,Bouncycastle,在签名者之前,一切正常。由于以下异常,请验证(…): import java.security.Security; import java.security.cert.X509Certificate; import java.util.Collection; import java.util.Iterator; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.jcajce.JcaX5

在签名者之前,一切正常。由于以下异常,请验证(…):

import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Iterator;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Store;
import org.bouncycastle.util.encoders.Base64;

public class VerifySignature {
    public static void main(String[] args) throws Exception {
        File p7s = new File("D:\\SBI-DATA\\file\\signature_2.txt") ;
        int size = ((int) p7s.length());
        byte[] sig = new byte[size]; 
        File f = new File("D:\\SBI-DATA\\file\\plain.txt") ;
        int sizecontent = ((int) f.length());
        byte[] Data_Bytes = new byte[sizecontent];  
        Security.addProvider(new BouncyCastleProvider());    
        CMSSignedData signedData = new CMSSignedData(new CMSProcessableByteArray(Data_Bytes), sig);     
            Store store = signedData.getCertificates(); 
            SignerInformationStore signers = signedData.getSignerInfos(); 
            Collection c = signers.getSigners(); 
            Iterator it = c.iterator();
            while (it.hasNext()) { 
                SignerInformation signer = (SignerInformation) it.next(); 
                Collection certCollection = store.getMatches(signer.getSID()); 
                Iterator certIt = certCollection.iterator();
                X509CertificateHolder certHolder = (X509CertificateHolder) certIt.next();
                X509Certificate certFromSignedData = new JcaX509CertificateConverter().setProvider(BC_PROVIDER).getCertificate(certHolder);
                if (signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC_PROVIDER).build(certFromSignedData))) {
                    System.out.println("Signature verified");
                } else {
                    System.out.println("Signature verification failed");
                }
            }
    }    
}  

我真的不知道我做错了什么。有人能告诉我发生了什么事吗?

我想你签了两次,一次直接使用
签名,另一次使用
ContentSigner
。您只需要对数据进行签名,而不需要对签名进行签名


因此,解决方案应该是将
signature.sign()
替换为
text.getBytes()
,或者
text.getBytes(StandardCharsets.UTF_8)
如果您想显式定义
text
的字符集,而不是使用某些系统默认值。

您可以避免使用
,“BC
来显式定义提供程序。Bouncy Castle CMS与Oracle提供程序的效果一样好,您可能希望在将来插入另一个提供程序。尤其是当您有一个包含Base64编解码器的库时!嘿,我也面临同样的问题。。。你解决这个问题了吗???@user3921002I我想要数据签名。任何人都知道如何从签名中分离公钥。你说得对!只要去掉那个讨厌的签名对象,写下“CMSTypedData msg=newcmsprocessablebytearray(theRawBytesofMyFile);”而且它有效!在BC 1.49:D:D:D上测试
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Iterator;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Store;
import org.bouncycastle.util.encoders.Base64;

public class VerifySignature {
    public static void main(String[] args) throws Exception {
        File p7s = new File("D:\\SBI-DATA\\file\\signature_2.txt") ;
        int size = ((int) p7s.length());
        byte[] sig = new byte[size]; 
        File f = new File("D:\\SBI-DATA\\file\\plain.txt") ;
        int sizecontent = ((int) f.length());
        byte[] Data_Bytes = new byte[sizecontent];  
        Security.addProvider(new BouncyCastleProvider());    
        CMSSignedData signedData = new CMSSignedData(new CMSProcessableByteArray(Data_Bytes), sig);     
            Store store = signedData.getCertificates(); 
            SignerInformationStore signers = signedData.getSignerInfos(); 
            Collection c = signers.getSigners(); 
            Iterator it = c.iterator();
            while (it.hasNext()) { 
                SignerInformation signer = (SignerInformation) it.next(); 
                Collection certCollection = store.getMatches(signer.getSID()); 
                Iterator certIt = certCollection.iterator();
                X509CertificateHolder certHolder = (X509CertificateHolder) certIt.next();
                X509Certificate certFromSignedData = new JcaX509CertificateConverter().setProvider(BC_PROVIDER).getCertificate(certHolder);
                if (signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC_PROVIDER).build(certFromSignedData))) {
                    System.out.println("Signature verified");
                } else {
                    System.out.println("Signature verification failed");
                }
            }
    }    
}  
Exception in thread "main" org.bouncycastle.cms.CMSSignerDigestMismatchException: message-digest attribute value does not match calculated value
    at org.bouncycastle.cms.SignerInformation.doVerify(Unknown Source)
    at org.bouncycastle.cms.SignerInformation.verify(Unknown Source)
    at my.package.VerifySignature.main(VerifySignature.java:64)