I'm trying to read certificate from smime.p7s file, the certificate chain is:
Baltimora Cyber Trust --> DigitPA --> Aruba PEC
So when i'm trying to extract, I retrieve only the last two certificate, the last like subject and the first like issuer.
What am I wrong?
the code:
private List<CertificateInfo> reading(ASN1InputStream asn1Stream) throws IOException, CMSException, CertificateException {
ArrayList<CertificateInfo> infos = new ArrayList<CertificateInfo>();
ASN1Primitive obj = asn1Stream.readObject();
ContentInfo contentInfo = ContentInfo.getInstance(obj);
CMSSignedData cms = new CMSSignedData(contentInfo);
JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);
Store store = cms.getCertificates();
SignerInformationStore signersInfoStore = cms.getSignerInfos();
Collection<SignerInformation> signers = signersInfoStore.getSigners();
logger.debug("signers num [" + signers.size() + "]");
for (SignerInformation si : signers) {
SignerId sid = si.getSID();
Collection<X509CertificateHolder> holders = store.getMatches(sid);
logger.debug("holders num [" + holders.size() + "]");
for (X509CertificateHolder certholder : holders) {
X509Certificate cert = converter.getCertificate(certholder);
logger.debug("Issuer [" + cert.getPublicKey() + "]");
CertificateInfo certInfo = util.parse(cert);
infos.add(certInfo);
}
}
return infos;
}
I'm using these bouncy castle jar like dependecies:
<dependency>
<groupId>bouncycastle</groupId>
<artifactId>bcprov-jdk15</artifactId>
<version>150</version>
</dependency>
<dependency>
<groupId>bouncycastle</groupId>
<artifactId>bcmail-jdk15</artifactId>
<version>150</version>
</dependency>
<dependency>
<groupId>bouncycastle</groupId>
<artifactId>bcpg-jdk15</artifactId>
<version>150</version>
</dependency>
<dependency>
<groupId>bouncycastle</groupId>
<artifactId>bcpkix-jdk15</artifactId>
<version>150</version>
</dependency>
thanks in advance.
Probably nothing is wrong. PKI works with a tree-like structure. It is possible to trust Aruba PEC using DigitPA. But how can you trust DigitPA? The most common method is to store the root certificate in a trust store. This trust store is e.g. distributed by the application (like the trust store within web browsers).
Now if the Baltimora Cyber Trust is already in the trust store, there is no need to send it within the PKCS#7 container. The certificate chain can be constructed to the trusted root without it.
So you either read the cert from the trust store directly, or you retrieve the root cert from the certificate chain created for verification.
Related
Im using iText 5.5.10 to validate timestamp in pdf file. Can someone explain me, why calling pkcs7.verifyTimestampImprint() method returns false?
Java code is from iText 5 example site,
see C5_02_SignatureInfo.java as input file
use testpdf_timestamp.pdf.
Code:
public static void main(String[] args) throws IOException, GeneralSecurityException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
PdfReader reader = new PdfReader("testpdf_timestamp.pdf");
AcroFields fields = reader.getAcroFields();
ArrayList<String> names = fields.getSignatureNames();
for (String name : names) {
System.out.println("===== " + name + " =====");
System.out.println("Signature covers whole document: " + fields.signatureCoversWholeDocument(name));
System.out.println("Document revision: " + fields.getRevision(name) + " of " + fields.getTotalRevisions());
PdfPKCS7 pkcs7 = fields.verifySignature(name);
System.out.println("Integrity check OK? " + pkcs7.verify());
SimpleDateFormat date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");
System.out.println("Signed on: " + date_format.format(pkcs7.getSignDate().getTime()));
if (pkcs7.getTimeStampDate() != null) {
System.out.println("TimeStamp: " + date_format.format(pkcs7.getTimeStampDate().getTime()));
TimeStampToken ts = pkcs7.getTimeStampToken();
System.out.println("TimeStamp service: " + ts.getTimeStampInfo().getTsa());
// Why pkcs7.verifyTimestampImprint() returns FLASE?
System.out.println("Timestamp verified? " + pkcs7.verifyTimestampImprint());
}
}
}
Maven dependencies:
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.49</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.49</version>
</dependency>
Thanks for a response.
The reason
why calling pkcs7.verifyTimestampImprint() method returns false
is that this method is meant for verifying the imprint of a signature time stamp, it is not meant for verifying the imprint of a document time stamp.
PdfPKCS7 is a class for creating and verifying signatures and for requesting time stamps (for use as signature time stamps) and verifying time stamps (both signature and document). Thus, not all of its methods make sense in every use case. Unfortunately the PdfPKCS7 JavaDocs don't make particularly clear which methods to use when.
In case of a document time stamp the verification of the timestamp imprint already takes place during the verify call.
You reference the code from C5_02_SignatureInfo.java on this site which clearly indicates that "these examples were written in the context of the white paper Digital Signatures for PDF documents."
In that white paper you can see that the code you find in C5_02_SignatureInfo.java is from the chapter 5.2 "Retrieving information from a signature" and the time stamp verified by verifyTimestampImprint() is a signature time stamp.
For document time stamp validation you should look at the code in later chapters.
I want to update my previous self-signed certificate with new one eg: chains which is returned (signed CSR) from TEST CA. My default keystore is: Windows-MY
Step 1: I have created a private-public key pair, self-signed
certifcate and CSR(private key is stored in Windows-MY with
self-signed certificate).
Step 2: sent CSR to CA.
Step 3: CA returns a certificate chain for that public key.
Now I want to replace that self-signed certificate with the CA returned certificate. NB: I have the private key stored in my store.
Key privKey = keyStore.getKey(commonName, keyPass);
System.out.println("invalid private key :" + (privKey == null));
// keyStore.deleteEntry(commonName);
// keyStore.load(null, keyPass);
if (isPrivateKeyAvailable) {
System.out.println("name:" + commonName + " is updatded");
keyStore.setKeyEntry(commonName, privKey, keyPass, chains);
} else {
System.out.println("name:" + commonName + " does not exist");
}
But I am getting these errors:
java.lang.UnsupportedOperationException: Cannot assign the key to the
given alias. at
sun.security.mscapi.KeyStore.engineSetKeyEntry(KeyStore.java:415) at
sun.security.mscapi.KeyStore$MY.engineSetKeyEntry(KeyStore.java:55)
at java.security.KeyStore.setKeyEntry(Unknown Source) at
keygenerator.KeyInstaller.installCertificateInWindowsStore(KeyInstaller.java:284)
at keygenerator.KeyInstaller.doJob(KeyInstaller.java:167) at
keygenerator.KeyGeneration.installCertificate(KeyGeneration.java:171)
at keygenerator.KeyGeneration.main(KeyGeneration.java:68)
Windows keystore (named Windows-MY from Java) is not directly writable. You need to pack the private key and the certificate chain returned by CA into a PKCS#12 file (.p12) and import it using The Windows import tool.
When I try to verify signed pdf document I get RuntimeException:
Exception in thread "main" java.lang.RuntimeException: algorithm identifier 1.2.398.3.10.1.1.1.1 in key not recognised
at org.bouncycastle.jce.provider.JDKKeyFactory.createPublicKeyFromPublicKeyInfo(Unknown Source)
at org.bouncycastle.jce.provider.X509CertificateObject.getPublicKey(Unknown Source)
at com.itextpdf.text.pdf.PdfPKCS7.<init>(PdfPKCS7.java:582)
at com.itextpdf.text.pdf.PdfPKCS7.<init>(PdfPKCS7.java:421)
at com.itextpdf.text.pdf.AcroFields.verifySignature(AcroFields.java:2307)
at Main.verifyPDF(Main.java:62)
at Main.main(Main.java:90)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
my verification piece of code looks like this:
public static boolean verifyPDF(String fileToVerify, KeyStore trustedStore, CRL crl) throws IOException, GeneralSecurityException {
List<CRL> crls = null;
if (crl != null) {
crls = new ArrayList<CRL>(1);
crls.add(crl);
}
boolean result = false;
PdfReader checker = new PdfReader(fileToVerify);
AcroFields af = checker.getAcroFields();
ArrayList<String> names = af.getSignatureNames();
for (int k = 0; k < names.size(); ++k) {
String name = (String) names.get(k);
System.out.println("Signature: " + name);
com.itextpdf.text.pdf.PdfPKCS7 pk = af.verifySignature(name, "KALKAN");
result = pk.verify();
System.out.println("Signer certificate DN: " + pk.getSigningCertificate().getSubjectDN());
Calendar cal = pk.getSignDate();
X509Certificate pkc[] = (X509Certificate[]) pk.getSignCertificateChain();
System.out.println("Document modified: " + !result);
Object fails[] = PdfPKCS7.verifyCertificates(pkc, trustedStore, crls, cal);
if (fails == null)
System.out.println("Certificates verified against the KeyStore");
else
System.out.println("Certificate failed: " + fails[1]);
}
return result;
}
the exception occurs on this string:
com.itextpdf.text.pdf.PdfPKCS7 pk = af.verifySignature(name, "KALKAN");
I use patched iText library. I had to patch it because there was no algorithm like ECGOST34310 and I just added it. Signing is performed in usual way, there is no problem with it.
Please help!
Thanks.
At first glance that OID 1.2.398.3.10.1.1.1.1 seems to be defined by a Kazakh authority (cf. this page), related to GOST 34,310-2.004 represented by the parent OID, without having yet been included in the mainstream BouncyCastle distribution, cf. the BouncyCastle specifications.
Thus, just like you have extended iText to be able to sign using GOST 34,310-2.004
I use patched iText library. I had to patch it because there was no algorithm like ECGOST34310 and I just added it.
you have to extend it (or in this case more exactly the crypto library BouncyCastle used by iText) to be able to verify signatures using GOST 34,310-2.004. Maybe, though, someone else already has done that and comes forth to help?
By the way, it would be great if you shared the results as soon as they work.
That all been said I am not aware of GOST being mentioned in the context of either ISO 32000-1 or PAdES integrated PDF signatures. Using GOST for PDF signatures, therefore, will likely result in very limited interoperability.
So far, I've been working with a certificate which I added to a SoapUI 5.2 project and which gave me access to a pre-production server. However, now that I'm ready to move to a production environment, I'm trying to check the new production certificate with SoapUI, but I'm getting the next error:
WARN:Using fallback method to load keystore/truststore due to: Invalid keystore format
ERROR:An error occurred [java.lang.NullPointerException], see error log for details
And the error log says:
ERROR:Could not load keystore/truststore
ERROR:java.lang.NullPointerException
java.lang.NullPointerException
at org.apache.commons.ssl.KeyStoreBuilder.build(KeyStoreBuilder.java:176)
at org.apache.commons.ssl.KeyStoreBuilder.build(KeyStoreBuilder.java:97)
at org.apache.commons.ssl.KeyStoreBuilder.build(KeyStoreBuilder.java:88)
at com.eviware.soapui.impl.wsdl.support.wss.crypto.KeyMaterialWssCrypto.fallbackLoad(KeyMaterialWssCrypto.java:206)
at com.eviware.soapui.impl.wsdl.support.wss.crypto.KeyMaterialWssCrypto.load(KeyMaterialWssCrypto.java:168)
at com.eviware.soapui.impl.wsdl.support.wss.crypto.KeyMaterialWssCrypto.getStatus(KeyMaterialWssCrypto.java:216)
at com.eviware.soapui.impl.wsdl.panels.project.WSSTabPanel$CryptoTableModel.getValueAt(WSSTabPanel.java:643)
at javax.swing.JTable.getValueAt(Unknown Source)
at javax.swing.JTable.prepareRenderer(Unknown Source)
...
The only difference I found between the pre-production and production certificates was that the latter did not have the CommonName field defined.
I know that field is not mandatory, so how is that possible? How can I solve this problem without asking for a new certificate? That's not an option.
Any suggestion would be appreciated.
I check the pom.xml of SOAPUI project for 5.2 versión, and it use not-yet-commons-ssl versión 0.3.11:
<dependency>
<groupId>commons-ssl</groupId>
<artifactId>not-yet-commons-ssl</artifactId>
<version>0.3.11</version>
</dependency>
And If you check the build method for org.apache.commons.ssl.KeyStoreBuilder class as the exception thrown in your error log you'll see:
public static KeyStore build(byte[] jksOrCerts, byte[] privateKey,
char[] jksPassword, char[] keyPassword)
throws IOException, CertificateException, KeyStoreException,
NoSuchAlgorithmException, InvalidKeyException,
NoSuchProviderException, ProbablyBadPasswordException,
UnrecoverableKeyException {
...
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, jksPassword);
Iterator keysIt = keys.iterator();
Iterator chainsIt = chains.iterator();
int i = 1;
while (keysIt.hasNext() && chainsIt.hasNext()) {
Key key = (Key) keysIt.next();
Certificate[] c = (Certificate[]) chainsIt.next();
X509Certificate theOne = buildChain(key, c);
String alias = "alias_" + i++;
// The theOne is not null, then our chain was probably altered.
// Need to trim out the newly introduced null entries at the end of
// our chain.
if (theOne != null) {
c = Certificates.trimChain(c);
alias = Certificates.getCN(theOne);
/* line 176 */ alias = alias.replace(' ', '_');
}
ks.setKeyEntry(alias, key, keyPassword, c);
}
return ks;
}
}
So seems that you're right and the problem is that your certificate has no common name, so org.apache.commons.ssl.Certificates.getCN(X509Certificate) returns null as alias and then alias.replace is throwing the NPE.
alias = Certificates.getCN(theOne);
/* line 176 */ alias = alias.replace(' ', '_');
I don't see nothing that says that Common Name is mandatory in RFC5280, however various code/software use it for different purposes as not-yet-commons-ssl does.
Your certificate is probably right but you can't use it with SOAPUI 5.2 version to test your environment if it hasn't the CN, so if you want to use SOAPUI to test your environment I think that you've to reissue the certificate generating a CSR with CN. Or you can report the problem to http://juliusdavies.ca/commons-ssl/ and then ask to SOAPUI to include the latest version...
Hope this helps,
Hi i have this certificate(X509Certificate) but i need to get all the issuers of it, for example:
the certification path of the certificate is
-CA NATIONAL ROOT - Costa Rica
--CA NATURAL PERSON POLITICS - Costa Rica
---CA SINPE - NATURAL PERSON
----MARIO XXXXX XXXXXX (SIGN) --->
---> This is what i have, but i need to access the top issuer till reach the root(CA NATIONAL ROOT - Costa Rica), because i need to compare the name of the first issuer and other data, with some parameters. How do i accomplish this or where should i start?
KeyStore ks = KeyStore.getInstance("pkcs12");
//FileInputStream fis = new FileInputStream("C://Users//youtube//Documents//workspace//PublicKey02//archivo//archivo.p12");
//ks.load(fis, "passwordp12file".toCharArray());
ks.load(new FileInputStream("archivo//llave_criptografica.p12"), "su-password".toCharArray());
/*Enumeration<String> e = ks.aliases();
while (e.hasMoreElements()) {
String param = e.nextElement();
System.out.println(param);
}*/
//System.out.println(ks.containsAlias("myKey"));
KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry("2cba9e2d-6ec2-435e-b1bc-5fd9fe5afcac", new KeyStore.PasswordProtection("su-password".toCharArray()));