我正在使用Bouncy Castle提供的库来加密,解密,签名和验证符号。我这样做是
1.加密数据
2.签名数据
3.将签名字节写入文件
4.从文件读取签名字节
5.验证签名
6.解密数据
我 从使用Java的密码学开始学了 参考 __
我的问题是在第5步中,当我验证数据时
org.bouncycastle.cms.CMSException:消息摘要属性值与计算值不匹配
我的代码如下
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");
}
}
在典型的用法中,.p7b
文件仅包含公钥证书,而不包含私钥。它通常用于存储整个证书链,而不是单个证书。“ p7b”名称来自PKCS#7
SignedData结构的简写形式。通常,私钥存储在PKCS#12(通常是具有a .p12
或.pfx
扩展名的文件)文件中,但其他格式也很常见。
要从p7b文件中读取证书,可以使用CertificateFactory类。PKCS#12文件可直接用作密钥库。
您经常提到PKCS#7。PKCS#7是一个很大的开放式旧标准。如今,更普遍实施的标准是称为CMS的PKCS#7的扩展子集。这是RFC
5652中记录的IETF标准。该BouncyCastle的PKIX
/
CMS库先后为CMS规范的广泛支持。
我试图实现PDFS的签名验证。这是一个很大的主题,所以我一步一步地进行,首先,我试图在我自己签名的PDF中实际返回一个正值,使用当前Acrobat的所有默认值--对于摘要,应该是SHA256和PKCS7分离签名。因此,我破解了openssl,通过读取PDF中给出的字节范围并调用函数,我得到了一个哈希值来进行比较。因此,现在我需要读取证书数据等,并使用函数。这个看起来就是我想要的: 如文档中所示。除
我已经在SO上搜索了很多关于完全加密解密示例的要求。事实上,我有很多链接和示例,但没有一个适用于AES-192-CBC模式和AES-256-CBC。 我有下面的例子,这应该是与所有类型的工作,但它只与AES-128-CBC模式。我是Python的新手。谁能帮我一下我哪里错了? 我在窗户上使用Python 3.4,我无法移动到Python 2.7。 虽然这段代码使用192位和256位加密对数据进行加
我想做的是: 使用证书使用openssl对zip文件进行签名,并创建签名文件(PKCS#7) 我安装了openssl并打开了控制台 我创建了一个rsa密钥(openssl genrsa-out key.pem 2048) 我创建了一个请求(openssl req-batch-sha256-new-key key.pem-out request.pem-subj'/c=../st=../l=../o
问题内容: 在Java中需要有关加密例程的帮助。 给定PKCS#7签名,我想针对受信任的存储验证它包含的所有证书。我假设签名中包含的所有证书均以正确的顺序形成有效的证书路径(或链,无论如何),因此 最上面的(#0)是签名证书; 下一个(#1)是中间证书,用于签署#0; 下一个(#2)是另一个中间证书,用于签署#1; 等等。 最后一个证书(#N)由CA签名。 到目前为止,这是我设法破解的: 所以问题
我正在编写一个fuse文件系统,我有一个问题。 我正在使用CBC AES加密磁盘中的数据。问题是填充。当密码的大小是例如15字节时是没有问题的,因为它额外增加了1字节。问题是,当我尝试加密4096字节时,它也给我添加了16字节的padd,这对我来说是失败的。我不知道为什么要添加padding,因为4096是128的倍数(大小为aes块)。我需要修改我的c代码,比如说openssl,它只在必要时添加
我知道PKCS#7=证书+可选原始数据+PKCS#1格式的签名