首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用充气城堡签署签名数据?

如何使用充气城堡签署签名数据?
EN

Stack Overflow用户
提问于 2014-08-08 06:20:57
回答 1查看 9K关注 0票数 4
代码语言:javascript
复制
**This is my code to sign a String.</br>**

package my.package;

import java.io.FileInputStream;
import java.security.Key;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.Store;
import sun.misc.BASE64Encoder;

public class SignMessage {
    static final String KEYSTORE_FILE = "keys/certificates.p12";
    static final String KEYSTORE_INSTANCE = "PKCS12";
    static final String KEYSTORE_PWD = "test";
    static final String KEYSTORE_ALIAS = "Key1";

    public static void main(String[] args) throws Exception {

        String text = "This is a message";

        Security.addProvider(new BouncyCastleProvider());

        KeyStore ks = KeyStore.getInstance(KEYSTORE_INSTANCE);
        ks.load(new FileInputStream(KEYSTORE_FILE), KEYSTORE_PWD.toCharArray());
        Key key = ks.getKey(KEYSTORE_ALIAS, KEYSTORE_PWD.toCharArray());

        //Sign
        PrivateKey privKey = (PrivateKey) key;
        Signature signature = Signature.getInstance("SHA1WithRSA", "BC");
        signature.initSign(privKey);
        signature.update(text.getBytes());

        //Build CMS
        X509Certificate cert = (X509Certificate) ks.getCertificate(KEYSTORE_ALIAS);
        List certList = new ArrayList();
        CMSTypedData msg = new CMSProcessableByteArray(signature.sign());
        certList.add(cert);
        Store certs = new JcaCertStore(certList);
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(privKey);
        gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()).build(sha1Signer, cert));
        gen.addCertificates(certs);
        CMSSignedData sigData = gen.generate(msg, false);

        FileOutputStream sigfos = new FileOutputStream("D:\\SBI-DATA\\file\\signature_1.txt");
            sigfos.write(Base64.encodeBase64(sp.getEncoded()));

            sigfos.close();
    }
}

现在,EnvelopedData输出将用于通过这种方式验证签名:

代码语言:javascript
复制
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");
                }
            }
    }    
}  

在signer.verify(..)之前,一切都很好。由于下列例外情况:

代码语言:javascript
复制
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)

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-08 11:05:37

我认为您要签署两次,一次是直接使用Signature,另一次是使用ContentSigner。你只需要签署数据,而不是签名。

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25197158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档