使用PKCS#7加密 [英] Encryption using PKCS#7

查看:3379
本文介绍了使用PKCS#7加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Bouncy Castle提供的库来加密,解密,签署和验证签名。
我这样做

1.加密数据

2.签名数据

3.将有符号字节写入文件

4.从文件中读取带符号的字节

5.验证签名

6.解密数据



我已经从开始使用Java



我的问题是在步骤5当我验证数据,我得到


org.bouncycastle.cms.CMSException:message-digest属性值为
与计算值不匹配




我的代码在下面

  import java.io.ByteArrayInputStream; 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertStore;
import java.security.cert.Certificate;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXCertPathBuilderResult;
import java.security.cert.TrustAnchor;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;

import javax.security.auth.x500.X500Principal;
import javax.security.auth.x500.X500PrivateCredential;

import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
import org.bouncycastle.cms.CMSEnvelopedDataParser;
import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.RecipientId;
import org.bouncycastle.cms.RecipientInformation;
import org.bouncycastle.cms.RecipientInformationStore;
import org.bouncycastle.cms.SignerId;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.x509.X509V1CertificateGenerator;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;

public class Test {


private static final char [] KEY_STORE_PASSWORD =123456.toCharArray();
private static final long VALIDITY_PERIOD = 365 * 24 * 60 * 60 * 1000;
private static final char [] KEY_PASSWORD =keyPassword.toCharArray();
public static String ROOT_ALIAS =root;
public static String INTERMEDIATE_ALIAS =intermediate;
public static String END_ENTITY_ALIAS =end;
public static String PLAIN_TEXT =Hello World!123;

public static void main(String [] args){
try {

// CREATE KEY STORE
KeyStore keyStore = createKeyStore

//步骤1. ENCRYPT和SIGN
byte [] step1Data = encryptData(keyStore,PLAIN_TEXT.getBytes());
CMSSignedData cmsSignedData = signData(keyStore,step1Data);
新文件(D:\\pkcs7\\encrypted-file.p7b);
FileOutputStream fileOuputStream = new FileOutputStream(D:\\pkcs7\\encrypted-file.p7b);
fileOuputStream.write(cmsSignedData.getEncoded());
fileOuputStream.flush();
fileOuputStream.close();


//步骤2.读取加密数据并验证签名和解密
文件file =新文件(D:\\pkcs7\\encrypted- file.p7b);
FileInputStream fileInputStream = new FileInputStream(file);
byte [] encryptedAndSignedByte = new byte [(int)file.length()];
fileInputStream.read(encryptedAndSignedByte);
fileInputStream.close();
cmsSignedData = new CMSSignedData(encryptedAndSignedByte);
if(verifyData(keyStore,cmsSignedData)== true){
decryptData(keyStore,encryptedAndSignedByte);
}

} catch(Exception e){
e.printStackTrace();
}


}

/ **
*
*此方法将加密数据
*
private static byte [] encryptData(KeyStore keyStore,byte [] plainData)throws Exception {
PrivateKey key =(PrivateKey)keyStore.getKey(END_ENTITY_ALIAS,
KEY_PASSWORD);
Certificate [] chain = keyStore.getCertificateChain(END_ENTITY_ALIAS);
X509Certificate cert =(X509Certificate)chain [0];

//设置生成器
CMSEnvelopedDataGenerator gen = new CMSEnvelopedDataGenerator();

gen.addKeyTransRecipient(cert);

//创建包络数据对象
CMSProcessable data = new CMSProcessableByteArray(plainData);


CMSEnvelopedData enveloped = gen.generate(data,
CMSEnvelopedDataGenerator.AES128_CBC,BC);

return enveloped.getEncoded();
// recreate

}

private static byte [] decryptData(KeyStore keyStore,byte [] encryptedData)throws Exception {
CMSEnvelopedDataParser envelopedDataParser = new CMSEnvelopedDataParser(new ByteArrayInputStream(encryptedData));

PrivateKey key =(PrivateKey)keyStore.getKey(END_ENTITY_ALIAS,KEY_PASSWORD);
Certificate [] chain = keyStore.getCertificateChain(END_ENTITY_ALIAS);
X509Certificate cert =(X509Certificate)chain [0];


CMSEnvelopedData enveloped = new CMSEnvelopedData(encryptedData);

//查找收件人标识符
RecipientId recId = new RecipientId();

recId.setSerialNumber(cert.getSerialNumber());
recId.setIssuer(cert.getIssuerX500Principal()。getEncoded());

RecipientInformationStore recipients = enveloped.getRecipientInfos();
RecipientInformation recipient = recipients.get(recId);

if(recipient!= null){
//解密数据
byte [] recData = recipient.getContent(key,BC);
System.out.println(-----------------------已恢复的数据-------------- ---------)
System.out.println(new String(recData));
System.out.println(--------------------------------------- -----------------------);
return recData;

} else {
System.out.println(找不到匹配的收件人);
}
return null;
}

私有静态CMSSignedData signData(KeyStore keyStore,byte [] encryptedData)throws异常{
//获取私钥KEY
PrivateKey key =(PrivateKey)keyStore .getKey(END_ENTITY_ALIAS,
KEY_PASSWORD);

证书[] chain = keyStore.getCertificateChain(END_ENTITY_ALIAS);
CertStore certsAndCRLs = CertStore.getInstance(Collection,
new CollectionCertStoreParameters(Arrays.asList(chain)),BC);
X509Certificate cert =(X509Certificate)chain [0];

//设置生成器
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
gen.addSigner(key,cert,CMSSignedDataGenerator.DIGEST_SHA224);
gen.addCertificatesAndCRLs(certsAndCRLs);

//创建签名数据对象
CMSProcessable data = new CMSProcessableByteArray(encryptedData);
CMSSignedData signed = gen.generate(data,BC);

// recreate
signed = new CMSSignedData(data,signed.getEncoded());
// ContentInfo conInf = signed.getContentInfo();
// CMSProcessable sigContent = signed.getSignedContent();
return signed;
}

private static boolean verifyData(KeyStore keyStore,CMSSignedData signed)
throws Exception {
//验证步骤
X509Certificate rootCert =(X509Certificate)keyStore .getCertificate(ROOT_ALIAS);

if(isValidSignature(signed,rootCert)){
System.out.println(verification succeeded);
return true;
} else {
System.out.println(verification failed);
}
return false;
}

/ **
*获取CMS SignedData消息和信任锚,并确定
*消息是否使用来自终端实体的有效签名签名entity
*由信任锚rootCert识别的证书。
* /
private static boolean isValidSignature(CMSSignedData signedData,
X509Certificate rootCert)throws Exception {

boolean [] bArr = new boolean [2]
bArr [0] = true;
CertStore certsAndCRLs = signedData.getCertificatesAndCRLs(
Collection,BC);
SignerInformationStore signers = signedData.getSignerInfos();
迭代器it = signers.getSigners()。iterator();

if(it.hasNext()){
SignerInformation signer =(SignerInformation)it.next();
SignerId signerConstraints = signer.getSID();
signerConstraints.setKeyUsage(bArr);
PKIXCertPathBuilderResult result = buildPath(rootCert,
signer.getSID(),certsAndCRLs);
return signer.verify(result.getPublicKey(),BC);
}

return false;
}

/ **
*使用给定的根作为信任锚并在
* end约束和证书存储中传递的路径。
*< p>
*注:路径是使用撤销检查关闭构建的。
* /
public static PKIXCertPathBuilderResult buildPath(X509Certificate rootCert,
X509CertSelector endConstraints,CertStore certsAndCRLs)
throws Exception {
CertPathBuilder builder = CertPathBuilder.getInstance(PKIX 公元前);
PKIXBuilderParameters buildParams = new PKIXBuilderParameters(
Collections.singleton(new TrustAnchor(rootCert,null)),
endConstraints);

buildParams.addCertStore(certsAndCRLs);
buildParams.setRevocationEnabled(false);

return(PKIXCertPathBuilderResult)builder.build(buildParams);
}

/ **
*创建一个包含具有证书
* chain的私有凭证和一个信任锚的KeyStore。
* /
public static KeyStore createKeyStore()throws Exception {
KeyStore keyStore = KeyStore.getInstance(JKS);
keyStore.load(null,null);

keyStore.load(null,null);

X500PrivateCredential rootCredential = createRootCredential();
X500PrivateCredential interCredential = createIntermediateCredential(
rootCredential.getPrivateKey(),rootCredential.getCertificate());
X500PrivateCredential endCredential = createEndEntityCredential(
interCredential.getPrivateKey(),
interCredential.getCertificate());

keyStore.setCertificateEntry(rootCredential.getAlias(),
rootCredential.getCertificate());
keyStore.setKeyEntry(
endCredential.getAlias(),
endCredential.getPrivateKey(),
KEY_PASSWORD,
new Certificate [] {endCredential.getCertificate(),
interCredential.getCertificate(),
rootCredential.getCertificate()});

keyStore.store(new FileOutputStream(d:\\pkcs7\\KeyStore.jks),
KEY_STORE_PASSWORD);
return keyStore;
}

/ **
*创建随机的1024位RSA密钥对
* /
public static KeyPair generateRSAKeyPair()throws Exception {
KeyPairGenerator kpGen = KeyPairGenerator.getInstance(RSA,BC);
kpGen.initialize(1024,new SecureRandom());
return kpGen.generateKeyPair();
}

/ **
*生成示例V1证书以用作CA根证书
* /
public static X509Certificate generateCertificate(KeyPair pair )
throws Exception {
X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
certGen.setSerialNumber(BigInteger.valueOf(1));
certGen.setIssuerDN(new X500Principal(CN = Test CA Certificate));
certGen.setNotBefore(new Date(System.currentTimeMillis()
- VALIDITY_PERIOD));
certGen.setNotAfter(new Date(System.currentTimeMillis()
+ VALIDITY_PERIOD));
certGen.setSubjectDN(new X500Principal(CN = Test CA Certificate));
certGen.setPublicKey(pair.getPublic());
certGen.setSignatureAlgorithm(SHA1WithRSAEncryption);
return certGen.generateX509Certificate(pair.getPrivate(),BC);
}

/ **
*生成示例V1证书以用作CA根证书
* /
public static X509Certificate generateRootCert )
throws Exception {
X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();

certGen.setSerialNumber(BigInteger.valueOf(1));
certGen.setIssuerDN(new X500Principal(CN = Test CA Certificate));
certGen.setNotBefore(new Date(System.currentTimeMillis()
- VALIDITY_PERIOD));
certGen.setNotAfter(new Date(System.currentTimeMillis()
+ VALIDITY_PERIOD));
certGen.setSubjectDN(new X500Principal(CN = Test CA Certificate));
certGen.setPublicKey(pair.getPublic());
certGen.setSignatureAlgorithm(SHA1WithRSAEncryption);

return certGen.generateX509Certificate(pair.getPrivate(),BC);
}

/ **
*生成样例V3证书以用作终端实体证书
* /
public static X509Certificate generateEndEntityCert(PublicKey entityKey ,
PrivateKey caKey,X509Certificate caCert)throws Exception {
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

certGen.setSerialNumber(BigInteger.valueOf(1));
certGen.setIssuerDN(caCert.getSubjectX500Principal());
certGen.setNotBefore(new Date(System.currentTimeMillis()
- VALIDITY_PERIOD));
certGen.setNotAfter(new Date(System.currentTimeMillis()
+ VALIDITY_PERIOD));
certGen.setSubjectDN(new X500Principal(CN = Test End Certificate));
certificateGen.setPublicKey(entityKey);
certGen.setSignatureAlgorithm(SHA1WithRSAEncryption);

certGen.addExtension(X509Extensions.AuthorityKeyIdentifier,false,
new AuthorityKeyIdentifierStructure(caCert));
certGen.addExtension(X509Extensions.SubjectKeyIdentifier,false,
new SubjectKeyIdentifierStructure(entityKey));
certGen.addExtension(X509Extensions.BasicConstraints,true,
new BasicConstraints(false));
certGen.addExtension(X509Extensions.KeyUsage,true,new KeyUsage(
KeyUsage.digitalSignature | KeyUsage.keyEncipherment));

return certGen.generateX509Certificate(caKey,BC);
}

/ **
*为根实体生成X500PrivateCredential。
* /
public static X500PrivateCredential createRootCredential()throws Exception {
KeyPair rootPair = generateRSAKeyPair();
X509Certificate rootCert = generateRootCert(rootPair);

return new X500PrivateCredential(rootCert,rootPair.getPrivate(),
ROOT_ALIAS);
}

/ **
*为中间实体生成X500PrivateCredential。
* /
public static X500PrivateCredential createIntermediateCredential(
PrivateKey caKey,X509Certificate caCert)throws Exception {
KeyPair interPair = generateRSAKeyPair();
X509Certificate interCert = generateIntermediateCert(
interPair.getPublic(),caKey,caCert);

return new X500PrivateCredential(interCert,interPair.getPrivate(),
INTERMEDIATE_ALIAS);
}

/ **
*为结束实体生成X500PrivateCredential。
* /
public static X500PrivateCredential createEndEntityCredential(
PrivateKey caKey,X509Certificate caCert)throws Exception {
KeyPair endPair = generateRSAKeyPair();
X509Certificate endCert = generateEndEntityCert(endPair.getPublic(),
caKey,caCert);

return new X500PrivateCredential(endCert,endPair.getPrivate(),
END_ENTITY_ALIAS);
}

/ **
*生成示例V3证书以用作中间CA证书
* /
public static X509Certificate generateIntermediateCert(PublicKey intKey ,
PrivateKey caKey,X509Certificate caCert)throws Exception {
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

certGen.setSerialNumber(BigInteger.valueOf(1));
certGen.setIssuerDN(caCert.getSubjectX500Principal());
certGen.setNotBefore(new Date(System.currentTimeMillis()));
certGen.setNotAfter(new Date(System.currentTimeMillis()
+ VALIDITY_PERIOD));
certGen.setSubjectDN(new X500Principal(
CN = Test Intermediate Certificate));
certGen.setPublicKey(intKey);
certGen.setSignatureAlgorithm(SHA1WithRSAEncryption);

certGen.addExtension(X509Extensions.AuthorityKeyIdentifier,false,
new AuthorityKeyIdentifierStructure(caCert));
certGen.addExtension(X509Extensions.SubjectKeyIdentifier,false,
new SubjectKeyIdentifierStructure(intKey));
certGen.addExtension(X509Extensions.BasicConstraints,true,
new BasicConstraints(0));
certGen.addExtension(X509Extensions.KeyUsage,true,new KeyUsage(
KeyUsage.digitalSignature | KeyUsage.keyCertSign
| KeyUsage.cRLSign));

return certGen.generateX509Certificate(caKey,BC);
}


}


解决方案

在典型用法中, .p7b 文件仅包含公钥证书,而不包含私钥。它通常用于存储整个证书链,而不是单个证书。 'p7b'名称来自格式,它是PKCS#7 SignedData结构的简并形式。通常,私钥存储在PKCS#12中(通常是具有 .p12 .pfx extension)文件,但其他格式也很常见。



要读取p7b文件中的证书,您可以使用 CertificateFactory 类。 PKCS#12文件可直接用作密钥库。



您经常提及PKCS#7。 PKCS#7是一个非常大和开放式的旧标准。这些天,更常用的标准是称为CMS的PKCS#7的扩展子集。这是一个IETF标准,记录在 RFC 5652 中。 Bouncycastle PKIX / CMS库对CMS规范有广泛的支持。 / p>

I am using Bouncy Castle provided library to encrypt,decrypt,sign and verify sign. I am doing this as
1. Encrypt data
2. Sign data
3. Write signed byte to a file
4. Read signed byte from file
5. Verify signature
6. Decrypt data

I have taken reference from Beginning Cryptography with Java

My problem is in step 5 when i am verifying data i am getting

org.bouncycastle.cms.CMSException: message-digest attribute value does not match calculated value

My code is below

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertStore;
import java.security.cert.Certificate;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXCertPathBuilderResult;
import java.security.cert.TrustAnchor;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;

import javax.security.auth.x500.X500Principal;
import javax.security.auth.x500.X500PrivateCredential;

import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
import org.bouncycastle.cms.CMSEnvelopedDataParser;
import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.RecipientId;
import org.bouncycastle.cms.RecipientInformation;
import org.bouncycastle.cms.RecipientInformationStore;
import org.bouncycastle.cms.SignerId;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.x509.X509V1CertificateGenerator;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;

public class Test {


    private static final char[] KEY_STORE_PASSWORD = "123456".toCharArray();
    private static final long VALIDITY_PERIOD = 365 * 24 * 60 * 60 * 1000;
    private static final char[] KEY_PASSWORD = "keyPassword".toCharArray();
    public static String ROOT_ALIAS = "root";
    public static String INTERMEDIATE_ALIAS = "intermediate";
    public static String END_ENTITY_ALIAS = "end";
    public static String PLAIN_TEXT = "Hello World!123";

    public static void main(String[] args)  {
        try{

        // CREATE KEY STORE
        KeyStore keyStore = createKeyStore();

        // STEP 1. ENCRYPT AND SIGN
        byte[] step1Data = encryptData(keyStore, PLAIN_TEXT.getBytes());
        CMSSignedData cmsSignedData = signData(keyStore,step1Data);
        new File("D:\\pkcs7\\encrypted-file.p7b");
        FileOutputStream fileOuputStream = new FileOutputStream("D:\\pkcs7\\encrypted-file.p7b"); 
        fileOuputStream.write(cmsSignedData.getEncoded());
        fileOuputStream.flush();
        fileOuputStream.close();


        // STEP 2. READ ENCRYPTED DATA AND VERIFY SIGN AND DECRYPT IT
        File file =new File("D:\\pkcs7\\encrypted-file.p7b");
        FileInputStream fileInputStream = new FileInputStream(file);
        byte[] encryptedAndSignedByte = new byte[(int)file.length()];
        fileInputStream.read(encryptedAndSignedByte );
        fileInputStream.close();
        cmsSignedData =  new CMSSignedData(encryptedAndSignedByte);
        if( verifyData(keyStore, cmsSignedData) == true ){
            decryptData(keyStore,encryptedAndSignedByte);
        }

        }catch (Exception e) {
            e.printStackTrace();
        }


    }

    /**
     * 
     * This method will encrypt data
     */
    private static byte[] encryptData(KeyStore keyStore, byte[] plainData) throws Exception {
        PrivateKey key = (PrivateKey) keyStore.getKey(END_ENTITY_ALIAS,
                KEY_PASSWORD);
        Certificate[] chain = keyStore.getCertificateChain(END_ENTITY_ALIAS);
        X509Certificate cert = (X509Certificate) chain[0];

        // set up the generator
        CMSEnvelopedDataGenerator gen = new CMSEnvelopedDataGenerator();

        gen.addKeyTransRecipient(cert);

        // create the enveloped-data object
        CMSProcessable data = new CMSProcessableByteArray(plainData);


        CMSEnvelopedData enveloped = gen.generate(data,
                CMSEnvelopedDataGenerator.AES128_CBC, "BC");

        return  enveloped.getEncoded();
        // recreate

    }

    private static byte[] decryptData(KeyStore keyStore,byte[] encryptedData) throws Exception{
        CMSEnvelopedDataParser envelopedDataParser = new CMSEnvelopedDataParser(new ByteArrayInputStream(encryptedData));

        PrivateKey key = (PrivateKey) keyStore.getKey(END_ENTITY_ALIAS,KEY_PASSWORD);
        Certificate[] chain = keyStore.getCertificateChain(END_ENTITY_ALIAS);
        X509Certificate cert = (X509Certificate) chain[0];


        CMSEnvelopedData enveloped = new CMSEnvelopedData(encryptedData);

        // look for our recipient identifier
        RecipientId recId = new RecipientId();

        recId.setSerialNumber(cert.getSerialNumber());
        recId.setIssuer(cert.getIssuerX500Principal().getEncoded());

        RecipientInformationStore recipients = enveloped.getRecipientInfos();
        RecipientInformation recipient = recipients.get(recId);

        if (recipient != null) {
            // decrypt the data
            byte[] recData = recipient.getContent(key, "BC");
            System.out.println("----------------------- RECOVERED DATA -----------------------");
            System.out.println(new String(recData));
            System.out.println("--------------------------------------------------------------");
            return recData;

        } else {
            System.out.println("could not find a matching recipient");
        }
        return null;
    }

    private static CMSSignedData signData(KeyStore keyStore,byte[] encryptedData ) throws Exception {
        // GET THE PRIVATE KEY
        PrivateKey key = (PrivateKey) keyStore.getKey(END_ENTITY_ALIAS,
                KEY_PASSWORD);

        Certificate[] chain = keyStore.getCertificateChain(END_ENTITY_ALIAS);
        CertStore certsAndCRLs = CertStore.getInstance("Collection",
                new CollectionCertStoreParameters(Arrays.asList(chain)), "BC");
        X509Certificate cert = (X509Certificate) chain[0];

        // set up the generator
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        gen.addSigner(key, cert, CMSSignedDataGenerator.DIGEST_SHA224);
        gen.addCertificatesAndCRLs(certsAndCRLs);

        // create the signed-data object
        CMSProcessable data = new CMSProcessableByteArray(encryptedData);
        CMSSignedData signed = gen.generate(data, "BC");

        // recreate
        signed = new CMSSignedData(data, signed.getEncoded());
        // ContentInfo conInf = signed.getContentInfo();
        // CMSProcessable sigContent = signed.getSignedContent();
        return signed;
    }

    private static boolean verifyData(KeyStore keyStore, CMSSignedData signed)
            throws Exception {
        // verification step
        X509Certificate rootCert = (X509Certificate) keyStore.getCertificate(ROOT_ALIAS);

        if (isValidSignature(signed, rootCert)) {
            System.out.println("verification succeeded");
            return true;
        } else {
            System.out.println("verification failed");
        }
        return false;
    }

    /**
     * Take a CMS SignedData message and a trust anchor and determine if the
     * message is signed with a valid signature from a end entity entity
     * certificate recognized by the trust anchor rootCert.
     */
    private static boolean isValidSignature(CMSSignedData signedData,
            X509Certificate rootCert) throws Exception {

        boolean[] bArr = new boolean[2];
        bArr[0] = true;
        CertStore certsAndCRLs = signedData.getCertificatesAndCRLs(
                "Collection", "BC");
        SignerInformationStore signers = signedData.getSignerInfos();
        Iterator it = signers.getSigners().iterator();

        if (it.hasNext()) {
            SignerInformation signer = (SignerInformation) it.next();
            SignerId signerConstraints = signer.getSID();
            signerConstraints.setKeyUsage(bArr);
            PKIXCertPathBuilderResult result = buildPath(rootCert,
                    signer.getSID(), certsAndCRLs);
            return signer.verify(result.getPublicKey(), "BC");
        }

        return false;
    }

    /**
     * Build a path using the given root as the trust anchor, and the passed in
     * end constraints and certificate store.
     * <p>
     * Note: the path is built with revocation checking turned off.
     */
    public static PKIXCertPathBuilderResult buildPath(X509Certificate rootCert,
            X509CertSelector endConstraints, CertStore certsAndCRLs)
            throws Exception {
        CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC");
        PKIXBuilderParameters buildParams = new PKIXBuilderParameters(
                Collections.singleton(new TrustAnchor(rootCert, null)),
                endConstraints);

        buildParams.addCertStore(certsAndCRLs);
        buildParams.setRevocationEnabled(false);

        return (PKIXCertPathBuilderResult) builder.build(buildParams);
    }

    /**
     * Create a KeyStore containing the a private credential with certificate
     * chain and a trust anchor.
     */
    public static KeyStore createKeyStore() throws Exception {
        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(null, null);

        keyStore.load(null, null);

        X500PrivateCredential rootCredential = createRootCredential();
        X500PrivateCredential interCredential = createIntermediateCredential(
                rootCredential.getPrivateKey(), rootCredential.getCertificate());
        X500PrivateCredential endCredential = createEndEntityCredential(
                interCredential.getPrivateKey(),
                interCredential.getCertificate());

        keyStore.setCertificateEntry(rootCredential.getAlias(),
                rootCredential.getCertificate());
        keyStore.setKeyEntry(
                endCredential.getAlias(),
                endCredential.getPrivateKey(),
                KEY_PASSWORD,
                new Certificate[] { endCredential.getCertificate(),
                        interCredential.getCertificate(),
                        rootCredential.getCertificate() });

        keyStore.store(new FileOutputStream("d:\\pkcs7\\KeyStore.jks"),
                KEY_STORE_PASSWORD);
        return keyStore;
    }

    /**
     * Create a random 1024 bit RSA key pair
     */
    public static KeyPair generateRSAKeyPair() throws Exception {
        KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");
        kpGen.initialize(1024, new SecureRandom());
        return kpGen.generateKeyPair();
    }

    /**
     * Generate a sample V1 certificate to use as a CA root certificate
     */
    public static X509Certificate generateCertificate(KeyPair pair)
            throws Exception {
        X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
        certGen.setSerialNumber(BigInteger.valueOf(1));
        certGen.setIssuerDN(new X500Principal("CN=Test CA Certificate"));
        certGen.setNotBefore(new Date(System.currentTimeMillis()
                - VALIDITY_PERIOD));
        certGen.setNotAfter(new Date(System.currentTimeMillis()
                + VALIDITY_PERIOD));
        certGen.setSubjectDN(new X500Principal("CN=Test CA Certificate"));
        certGen.setPublicKey(pair.getPublic());
        certGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
        return certGen.generateX509Certificate(pair.getPrivate(), "BC");
    }

    /**
     * Generate a sample V1 certificate to use as a CA root certificate
     */
    public static X509Certificate generateRootCert(KeyPair pair)
            throws Exception {
        X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();

        certGen.setSerialNumber(BigInteger.valueOf(1));
        certGen.setIssuerDN(new X500Principal("CN=Test CA Certificate"));
        certGen.setNotBefore(new Date(System.currentTimeMillis()
                - VALIDITY_PERIOD));
        certGen.setNotAfter(new Date(System.currentTimeMillis()
                + VALIDITY_PERIOD));
        certGen.setSubjectDN(new X500Principal("CN=Test CA Certificate"));
        certGen.setPublicKey(pair.getPublic());
        certGen.setSignatureAlgorithm("SHA1WithRSAEncryption");

        return certGen.generateX509Certificate(pair.getPrivate(), "BC");
    }

    /**
     * Generate a sample V3 certificate to use as an end entity certificate
     */
    public static X509Certificate generateEndEntityCert(PublicKey entityKey,
            PrivateKey caKey, X509Certificate caCert) throws Exception {
        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

        certGen.setSerialNumber(BigInteger.valueOf(1));
        certGen.setIssuerDN(caCert.getSubjectX500Principal());
        certGen.setNotBefore(new Date(System.currentTimeMillis()
                - VALIDITY_PERIOD));
        certGen.setNotAfter(new Date(System.currentTimeMillis()
                + VALIDITY_PERIOD));
        certGen.setSubjectDN(new X500Principal("CN=Test End Certificate"));
        certGen.setPublicKey(entityKey);
        certGen.setSignatureAlgorithm("SHA1WithRSAEncryption");

        certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
                new AuthorityKeyIdentifierStructure(caCert));
        certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,
                new SubjectKeyIdentifierStructure(entityKey));
        certGen.addExtension(X509Extensions.BasicConstraints, true,
                new BasicConstraints(false));
        certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(
                KeyUsage.digitalSignature | KeyUsage.keyEncipherment));

        return certGen.generateX509Certificate(caKey, "BC");
    }

    /**
     * Generate a X500PrivateCredential for the root entity.
     */
    public static X500PrivateCredential createRootCredential() throws Exception {
        KeyPair rootPair = generateRSAKeyPair();
        X509Certificate rootCert = generateRootCert(rootPair);

        return new X500PrivateCredential(rootCert, rootPair.getPrivate(),
                ROOT_ALIAS);
    }

    /**
     * Generate a X500PrivateCredential for the intermediate entity.
     */
    public static X500PrivateCredential createIntermediateCredential(
            PrivateKey caKey, X509Certificate caCert) throws Exception {
        KeyPair interPair = generateRSAKeyPair();
        X509Certificate interCert = generateIntermediateCert(
                interPair.getPublic(), caKey, caCert);

        return new X500PrivateCredential(interCert, interPair.getPrivate(),
                INTERMEDIATE_ALIAS);
    }

    /**
     * Generate a X500PrivateCredential for the end entity.
     */
    public static X500PrivateCredential createEndEntityCredential(
            PrivateKey caKey, X509Certificate caCert) throws Exception {
        KeyPair endPair = generateRSAKeyPair();
        X509Certificate endCert = generateEndEntityCert(endPair.getPublic(),
                caKey, caCert);

        return new X500PrivateCredential(endCert, endPair.getPrivate(),
                END_ENTITY_ALIAS);
    }

    /**
     * Generate a sample V3 certificate to use as an intermediate CA certificate
     */
    public static X509Certificate generateIntermediateCert(PublicKey intKey,
            PrivateKey caKey, X509Certificate caCert) throws Exception {
        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

        certGen.setSerialNumber(BigInteger.valueOf(1));
        certGen.setIssuerDN(caCert.getSubjectX500Principal());
        certGen.setNotBefore(new Date(System.currentTimeMillis()));
        certGen.setNotAfter(new Date(System.currentTimeMillis()
                + VALIDITY_PERIOD));
        certGen.setSubjectDN(new X500Principal(
                "CN=Test Intermediate Certificate"));
        certGen.setPublicKey(intKey);
        certGen.setSignatureAlgorithm("SHA1WithRSAEncryption");

        certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
                new AuthorityKeyIdentifierStructure(caCert));
        certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,
                new SubjectKeyIdentifierStructure(intKey));
        certGen.addExtension(X509Extensions.BasicConstraints, true,
                new BasicConstraints(0));
        certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(
                KeyUsage.digitalSignature | KeyUsage.keyCertSign
                        | KeyUsage.cRLSign));

        return certGen.generateX509Certificate(caKey, "BC");
    }


}

解决方案

In typical usage a .p7b file contains only public key certificates and never a private key. It is often used to store an entire chain of certificates rather than a single certificate. The 'p7b' name comes from the format which is the degenerate form of PKCS#7 SignedData structure. Typically, private keys are stored in a PKCS#12 (often a file that has either a .p12 or a .pfx extension) file but other formats are also common.

To read in the certificates from a p7b file you can use the CertificateFactory class. A PKCS#12 file is directly usable as a keystore.

You mention PKCS#7 frequently. PKCS#7 is an old standard that is extremely large and open ended. These days the standard that is more commonly implemented is an extended subset of PKCS#7 called CMS. It's an IETF standard documented in RFC 5652. The Bouncycastle PKIX/CMS library has extensive support for the CMS specification.

这篇关于使用PKCS#7加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆