empty keyStore in crypto - java

I'm using wss4j in order to sign a message request.
But when signing the message with this code:
Document d = signer.build(unsignedDoc, crypto, header)
I always get the error
org.apache.ws.security.WSSecurityException: General security error (no certificates for user ... were found for signature)
Searching for the cause I found out, that en empty key store seems to be the reason for this.
This is how I create a crypto instance:
private void createCrypto(){
// reading preferences (keystone-filename, password, etc.) from properties file
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("myprops.properties");
props.load(fis);
// create a crypto instance
Crypto crypto = CryptoFactory.getInstance(props);
// This line always prints "Size:0"
System.out.println("Size:" + crypto.getKeyStore.getSize())
...
But if I load the Keystore the following way, it shows size=1:
private void loadKeystore(){
KeyStore keystore;
try{
// reading and loading keystone file
InputStream is = new FileInputStream("myKeyStore.jks");
keystore.load(is, "password".toCharArray());
// Prints "Size:1"
System.out.println("Size:"+keystore.size());
...
So I wonder, what is wrong with the first example. Why is the keystore empty?
I already checked the properties: keystore and password are set correctly!
But if I remove the keystore-property from the properties-file, the error message is the same.
Can anyone help me with this?

Related

Adding PDF revocation information as an signed attribute pdfRevocationInfoArchival OID 1.2.840.113583.1.1.8

We have added pdfRevocationInfoArchival OID (1.2.840.113583.1.1.8) as a signed attribute while generating signature. While building this attribute we used external CRL file (ca-crl.crl) and builds the OID 1.2.840.113583.1.1.8 as ASN1 object. After signing pdf and timestamping signature, everything works fine. But we are not able to understand the identifier (adbe-revocationInfoArchival) which added is in the PDF is correct and which can be used to verify this PDF by fetching this OID. Also we are not able to check that this attribute is in proper format in which PDF can verify it. Is there any tool or utility available to check this attribute which is inserted as a signed attribute is valid.
If any PDF tool/utility is available to visualize attribute are available in PDF please share.
We have build the issuers CRL info at position [0] is this correct to way add the CRL in this OID? I have share the code below code snippet
The following object identifier identifies Adobe's revocation information attribute:
adbe-revocationInfoArchival OBJECT IDENTIFIER ::=
{ adbe(1.2.840.113583) acrobat(1) security(1) 8 }
Adobe's Revocation Information attribute value has ASN.1 type RevocationInfoArchival:
/**
** RevocationInfoArchival ::= SEQUENCE {
** crl [0] EXPLICIT SEQUENCE of CRLs, OPTIONAL
** ocsp [1] EXPLICIT SEQUENCE of OCSP Responses, OPTIONAL
** otherRevInfo [2] EXPLICIT SEQUENCE of OtherRevInfo, OPTIONAL
}
*/
Adobe's Revocation Information attribute value building using in Java Bouncy Castle API:
private ASN1EncodableVector genPdfInfoArchival(ASN1EncodableVector v) {
ASN1EncodableVector v1 = new ASN1EncodableVector();
List<X509CRL> crls = new ArrayList<X509CRL>();
ASN1InputStream t = null;
try {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
CRL crl = certFactory.generateCRL(new FileInputStream(new File("e://app//esp//crl//NSDLe-GovCA2019-Test-2.crl")));
System.out.println("crl:" + crl);
crls.add((X509CRL)crl);
if (!crls.isEmpty()) {
ASN1EncodableVector v11 = new ASN1EncodableVector();
for (Iterator<X509CRL> i = crls.iterator(); i.hasNext();) {
t = new ASN1InputStream(new ByteArrayInputStream(i.next().getEncoded()));
v11.add(t.readObject());
}
//0 for CRL
v1.add(new DERTaggedObject(true, 0, new DERSequence(v11)));
}
}
return v1;}
After building OID adding it in SignerInforGeneratorBuilder as a signed attribute and generating the signature and then adding this signature in PDF
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
ASN1EncodableVector signedAttr = new ASN1EncodableVector();
String ID_ADBE_REVOCATION = "1.2.840.113583.1.1.8";
//TODO add message digest for sgning - nikhilW
Attribute attr = new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(IOUtils.toByteArray(hashdata))));
signedAttr.add(attr);
//TODO generate pdf info archival and add it as CMS signed attribute - nikhilW
ASN1EncodableVector pdfInfo = genPdfInfoArchival(signedAttr);
Attribute ar = new Attribute(new ASN1ObjectIdentifier(ID_ADBE_REVOCATION), new DERSet (new DERSequence(pdfInfo)));
signedAttr.add(ar);
List<Certificate> certList = new ArrayList<Certificate>();
certList.addAll(Arrays.asList(certificateChain));
Store certs = new JcaCertStore(certList);
DefaultSignedAttributeTableGenerator sa = new DefaultSignedAttributeTableGenerator(new AttributeTable(signedAttr));
SignerInfoGeneratorBuilder builder = new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider());
builder.setSignedAttributeGenerator(sa);
Please find below google drive link contains sample signed pdf file hello_signed_ts_pdfarchivalinfo.pdf
pdf_sample_signed
Any help would be appreciated.
I have checked for the attribute added in pdf using below java source code. Also there is iText Java utility which will debug pdf object tree iText RUP or download it from my google drive link Download iTextRUP Java Jar run it with java -jar jar-name may it will help debuging pdf objects.
Pdf Archival Info Retrieval Source Code Returns CRL stream object at position [0]
private void getPdfRevoInfoArch(SignerInformation signerInform) {
AttributeTable at = signerInform.getSignedAttributes();
ASN1Encodable arch = at.get(new ASN1ObjectIdentifier("1.2.840.113583.1.1.8")).getAttrValues().getObjectAt(0);
//ASN1Encodable arch1 = at.get(new ASN1ObjectIdentifier("1.2.840.113583.1.1.8")).getAttrValues().getObjectAt(1);
System.out.println("arc:" + arch);
System.out.println("archSize:" + at.get(new ASN1ObjectIdentifier("1.2.840.113583.1.1.8")).getAttrValues().size());
}

Invalid keystore format using java

I'm trying to make a post request to one of our clients with certificate as part of their security.
I tried testing it in postman, just like the usual attached the certificate on postman settings and then able to make a post request to their api.
Now my problem is i'm encountering this error when i'm doing the request on our platform built in java
java.base/sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:664)
java.base/sun.security.util.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:222)
java.base/java.security.KeyStore.load(KeyStore.java:1479)
On the test environment they don't require the password hence null.
try (InputStream inputStream = new ByteArrayInputStream(p12Cert))
{
KeyStore keyStore = KeyStore.getInstance("jks");
keyStore.load(inputStream, null);
I traced the engineLoad method from javakeystore.
private static final int MAGIC = 0xfeedfeed;
private static final int VERSION_1 = 0x01;
private static final int VERSION_2 = 0x02;
if (xMagic!=MAGIC ||
(xVersion!=VERSION_1 && xVersion!=VERSION_2)) {
throw new IOException("Invalid keystore format");
}
Can someone elaborate the above?
Able to fix the problem above, first is the p12 cert i am trying to encode in base64 is in utf-8 encoding which is wrong and should be converted from HEXADECIMAL to base64.

Does Apache POI support signing the word twice?

I tried to run the signature code twice , but I found that it just geneneral sig1.xml , not sig1.xml and sig2.xml .
char password[] = "test".toCharArray();
File file = new File("test.pfx");
KeyStore keystore = KeyStore.getInstance("PKCS12");
FileInputStream fis = new FileInputStream(file);
keystore.load(fis, password);
fis.close();
// extracting private key and certificate
String alias = "xyz"; // alias of the keystore entry
Key key = keystore.getKey(alias, password);
X509Certificate x509 = (X509Certificate)keystore.getCertificate(alias);
// filling the SignatureConfig entries (minimum fields, more options are available ...)
SignatureConfig signatureConfig = new SignatureConfig();
signatureConfig.setKey(keyPair.getPrivate());
signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
OPCPackage pkg = OPCPackage.open(..., PackageAccess.READ_WRITE);
signatureConfig.setOpcPackage(pkg);
// adding the signature document to the package
SignatureInfo si = new SignatureInfo();
si.setSignatureConfig(signatureConfig);
si.confirmSignature();
Inside org.apache.poi.poifs.crypt.dsig.SignatureInfo there is a method writeDocument(Document document) that creates the sig1.xml overriding the previous one (if any), that's why if you sign it multiple times you will only see the last signature, altough inside the _xmlsignatures/_rels/origin.sigs.rels of the docx/xlsx you can see a relation to each signature.
if you replace:
sigPartName = PackagingURIHelper.createPartName("/_xmlsignatures/sig1.xml");
with something like:
SignatureInfo si = new SignatureInfo();
si.setSignatureConfig(signatureConfig);
Iterator<?> iterator = si.getSignatureParts().iterator();
int i = 1;
while (iterator.hasNext()) {
iterator.next();
i++;
}
sigPartName = PackagingURIHelper.createPartName("/_xmlsignatures/sig" + i + ".xml");
it will create sig1.xml, sig2.xml, ... and when opening docx/xlsx all signatures will be there.
I've fixed the original issue via #63011, which will be released in POI 4.1.0.
The relevant part of the ticket is.
There's a new config property in SignatureConfig.setAllowMultipleSignatures(true) to allow adding of signatures, which is by default false to stay backward compatible.

iText 7 adding ltv to existing signature

I'm new to iText 7,
I've tried adding ltv information to existing signature by using addLtv() method (code provided below)...If I understand right, this method adds crl or ocsp parameters to existing signatures or timestamps and then timestamps the document, but pdf document that is generated is not ltv enabled. However, I am able to generate ltv enabled signature if I sign document with ocsp or crl list in the first place, that leads me to believe that this issue is not related to some certificate missing or not added properly. So the addLtv() method, for some reason does not work for me. I hope I'm making sense :D
Any help or suggestion is greatly apriciated :)
private void addLtv(String src, String dest, IOcspClient ocsp, ICrlClient crl, ITSAClient tsa) throws Exception {
PdfReader r = new PdfReader(src);
FileOutputStream fos = new FileOutputStream(dest);
PdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(dest));
PdfSigner ps= new PdfSigner(r, fos, true);
LtvVerification v = new LtvVerification(pdfDoc);
SignatureUtil signatureUtil = new SignatureUtil(pdfDoc);
List<String> names = signatureUtil.getSignatureNames();
String sigName = names.get(names.size() - 1);
PdfPKCS7 pkcs7 = signatureUtil.verifySignature(sigName);
if (pkcs7.isTsp()) {
v.addVerification(sigName, ocsp, crl,
LtvVerification.CertificateOption.WHOLE_CHAIN,
LtvVerification.Level.CRL,
LtvVerification.CertificateInclusion.YES);
}
else {
for (String name : names) {
v.addVerification(name, ocsp, crl,
LtvVerification.CertificateOption.WHOLE_CHAIN,
LtvVerification.Level.OCSP,
LtvVerification.CertificateInclusion.YES);
v.merge();
}
}
ps.timestamp(tsa, null);
}
The conceptual issue in your code is that after adding LTV information you want to finalize the process by time stamping. While this is what you would want to do with a PDF which already is in a LTV workflow, it is not what you want to do with a PDF all signatures of which you want Adobe Reader to declare as "LTV-enabled".
(One can consider Adobe's term "LTV-enabled" to mean "ready to enter a LTV workflow," i.e. not yet actually being in a LTV workflow but including all validation information required to enter it without any further ado.)
There are other issues, too, in your method, e.g. you create two separate objects which write to dest, the PdfSigner ps via fos and the PdfDocument pdfDoc via its PdfWriter. Eventually you'll either find the output of only one of these objects in the file or a mish-mash of both.
Thus, here is a working port of my old iText 5 method addLtvNoTS (from this answer) to iText 7:
void addLtvNoTS(InputStream src, OutputStream dest, IOcspClient ocsp, ICrlClient crl, LtvVerification.Level timestampLevel, LtvVerification.Level signatureLevel) throws IOException, GeneralSecurityException
{
PdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(dest), new StampingProperties().useAppendMode());
LtvVerification v = new LtvVerification(pdfDoc);
SignatureUtil signatureUtil = new SignatureUtil(pdfDoc);
List<String> names = signatureUtil.getSignatureNames();
String sigName = names.get(names.size() - 1);
PdfPKCS7 pkcs7 = signatureUtil.verifySignature(sigName);
if (pkcs7.isTsp())
{
v.addVerification(sigName, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN,
timestampLevel, LtvVerification.CertificateInclusion.YES);
}
else
{
for (String name : names)
{
v.addVerification(name, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN,
signatureLevel, LtvVerification.CertificateInclusion.YES);
}
}
v.merge();
pdfDoc.close();
}
(EnableLtv method addLtvNoTS)
As you can see I made the LtvVerification.Level values for time stamps and signatures method parameters.
This is because iText's method LtvVerification.addVerification only adds LTV information for the immediate PDF signatures and document timestamps, not for already embedded or now added OCSP response or CRL signatures.
Often this is no problem, often certificates used for signing OCSP responses are marked in a way that indicates that no revocation checks are required, and certificates used for signing CRLs usually are the implicitly trusted CA certificates themselves.
In case of my test signature, though, the OCSP responses are signed by signatures which do require revocation checks. To make things work without significant additional coding, I used CRLs all over and for that introduced the parameters.
Actually I even had to give the CRL URL explicitly to the CrlClientOnline because of iText by default only using the first CRL distribution point in a certificate and at the same time not supporting LDAP URLs.
The bottom line: You also may have to tweak your code around current iText limits or be the one to improve the iText code itself to reliably produce LTV-enabled PDFs given arbitrary valid input...

Validate when keystore.load() is canceled

I need to write an applet that reads info from smartcards, I based my script on the code example provided by #Jovo Krneta here.
My concern is about this specific piece of code:
keyStore.load(null, null); // opens the windows security window
Enumeration<String> enums = keyStore.aliases(); // looks for local certificates
while (enums.hasMoreElements()) {
this.jComboBox1.addItem((String) enums.nextElement());
}
I'm finding it hard to find a way to validate if the user clicked on Cancel once the window is opened.
My question is if exists something like
keyStore.load(null, null);
if(keyStore.canceled()){
// do nothing
}else{
Enumeration<String> enums = keyStore.aliases(); // looks for local certificates
while (enums.hasMoreElements()) {
this.jComboBox1.addItem((String) enums.nextElement());
}
}

Categories