Getting current LTV of a PDF document with iText7 - java

I am reworking an application which uses iText5 to resign near expiration documents with long term verification. My iText5 implementation looks like this:
//stp represents PdfStamer instance
AcroFields fields = stp.getAcroFields();
List<String> names = fields.getSignatureNames();
boolean result = true;
if ( names.size() == 0 ) {
logger.debug("addVerification(): no signature names");
return result;
}
String sigName = names.get(names.size() - 1);
PdfPKCS7 pkcs7 = fields.verifySignature(sigName);
LtvVerification v = stp.getLtvVerification();
Now, I have most of the code translated into iText7, it looks like so:
SignatureUtil sign = new SignatureUtil(doc);
List<String> names = sign.getSignatureNames();
boolean result = true;
if ( names.size() == 0 ) {
logger.debug("addVerification(): no signature names");
return result;
}
String sigName = names.get(names.size() - 1);
PdfPKCS7 pkcs7 = sign.verifySignature(sigName);
LtvVerification v = stp.getLtvVerification();
LtvVerification v = doc.//what the hell do I do;
I'm stuck on LTV signature. I have document that is already signed and I need to get the current LTV signature. It can be done in iText5 but I didnt find a single method or class that would return me the LTV signature in iText7.
Is there a way to do this?

Related

Accessing a COSArray for PDF fields with Apache PDFBox

I'm trying to access all form fields in a PDF file - so I can use code to fill them in - and this is as far as I've gotten:
PDDocumentCatalog pdCatalog = pdf.getDocumentCatalog();
PDAcroForm pdAcroForm = pdCatalog.getAcroForm();
List<PDField> fieldList = pdAcroForm.getFields(); // fieldList.size() = 1
PDField field = fieldList.get(0);
COSDictionary dictionary = field.getCOSObject();
System.out.println("dictionary size = " + dictionary.size());
// my attempt to iterate through fields
for ( Map.Entry<COSName,COSBase> entry : dictionary.entrySet() )
{
COSName key = entry.getKey();
COSBase val = entry.getValue();
if ( val instanceof COSArray )
{
System.out.println("COSArray size = " + ((COSArray)val).size());
}
System.out.println("key = " + key);
System.out.println("val = " + val);
}
which gives an output of:
dictionary size = 3
COSArray size = 2
key = COSName{Kids}
val = COSArray{[COSObject{110, 0}, COSObject{108, 0}]}
key = COSName{T}
val = COSString{form1[0]}
key = COSName{V}
val = COSString{}
Does anyone know how I can access the two COSObjects in the COSArray? I also don't know what the notation COSObject{x, y} means, and can't find any documentation on this. If those are dictionary or array values elements, I also want to know how to access those.
You get the object with get(index) to get the COSObject (an indirect reference) or getObject(index) to get the dereferenced object referenced by the COSObject.
COSObject{110, 0} is the object number and the generation number (usually 0). Open your PDF file with NOTEPAD++ and look for "110 0 obj" to find it, or "110 0 R" to see who references this object.

Converting string in Base64 and HMAC sha1

I need help with making a signature in swift 3 with HMAC SHA1 for a web request.
I have an example in Java but really do not know how to do it in swift.
Java formula:
signature = Base64.encode(HMAC_SHA1.digest(data,Base64.decode(client_secret))
signature = +t2GOKtZt1hU+C7OGBKZbDOKxds=
swift 3 :
first convert the image into data.Then convert this imageData to base64 string.
imgData = UIImageJPEGRepresentation(image, 0.9)! as Data
strBase64 = imgData.base64EncodedString(options: .lineLength64Characters) as NSString
then use this base64 string wherever you want.
Solution:
extension Data {
func hmacsha1(key: String) -> String? {
guard let keyData = Data(base64Encoded: key, options: .ignoreUnknownCharacters) else {
return nil
}
var digest = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))
self.withUnsafeBytes({ dataBytes in
keyData.withUnsafeBytes({ keyDataBytes in
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA1), keyDataBytes, keyData.count, dataBytes, self.count, &digest)
})
})
return Data(bytes: digest).base64EncodedString()
}
}
Test:
let data = Data("Test".utf8)
let key = Data("Key".utf8).base64EncodedString()
let hmac = data.hmacsha1(key: key)
Result: "xIcCRlnXa+IqFtO+9AF3OqeRdAU="
Problem solved
extension String {
func hmac(algorithm: kCCHmacAlgSHA1, key: NSData) -> String {
let cKey = key
let cData = self.cString(using: String.Encoding.ascii)
var cHMAC = [CC_SHA1_DIGEST_LENGTH]
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA1), cKey.bytes, cKey.length, cData, Int(strlen(cData!)), &cHMAC)
let hmacData:NSData = NSData(bytes: cHMAC, length: cHMAC)
let hmacBase64 = hmacData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
return String(hmacBase64)
}
}
let hmacResult: String = cData.hmac(algorithm: HMACAlgorithm.SHA1, key: keyData)

docx4j copy image to a new document

I am trying to use docx4j to make partial copy of the document to a new document. I am able to copy most part - text, format etc. However, in case of image, I am not able to copy. Doing a deep copy for inline images leave the document incorrectly formatted, and same happens for linked images.
I am attaching code used to make copy
word = WordprocessingMLPackage.load(new File("C:\\Users\\prerak\\Documents\\Projects\\EME\\Exam System\\Documents\\T.docx"));
//newDoc = WordprocessingMLPackage.createPackage();
newDoc = WordprocessingMLPackage.load(new File("C:\\Users\\prerak\\Documents\\Projects\\EME\\Exam System\\Documents\\T.docx"));
MainDocumentPart mdp = word.getMainDocumentPart();
newDoc.getMainDocumentPart().getContent().clear();
Document contents = mdp.getContents();
Body body = contents.getBody();
List<Object> content = body.getContent();
ArrayList<ArrayList<Object>> allQ = new ArrayList<>();
ArrayList<Object> next = null;
for (Object o : content) {
if (o instanceof P) {
P p = (P) o;
List<Object> rs = DocxUtils.getAllElementFromObject(p, R.class);
for(Object d:rs){
R tt = (R) d;
List<Object> ds = tt.getContent();
for(Object dd:ds){
System.out.println(dd.getClass().getName());;
}
}
PPr ppr = (PPr) p.getPPr();
if (ppr != null && ppr.getPStyle() != null) {
System.out.println("Style: " + ppr.getPStyle().getVal());
if (ppr.getPStyle().getVal().equals("Heading1")) {
//System.out.println(o.toString());
}
}
}
if (o.toString().startsWith("##")) {
next = new ArrayList<>();
allQ.add(next);
}
if (next != null) {
next.add(o);
}
}
//System.out.println("Total number of questions " + allQ.size());
for (Object o : allQ.get(0)) {
newDoc.getMainDocumentPart().getContent().add(XmlUtils.deepCopy(o));
}
//System.out.println(DocxUtils.paraToHtml(allQ.get(0)));
newDoc.save(new File("C:\\Users\\prerak\\Documents\\Projects\\EME\\Exam System\\Documents\\newt90.docx"));
Do I have to do anything more than making a deep copy?
Your help is greatly appreciated.
Thanks
See http://www.docx4java.org/blog/2010/11/merging-word-documents/ regarding referential integrity.
The "brute force" approach is to make a copy of the WordprocessingMLPackage using WordprocessingMLPackage's clone() method, then delete the content you don't want. That'll leave the image reference and its corresponding part, but also other images etc which you aren't using anymore. Depending on your circumstances that may or may not be ok. If it isn't, the commercial MergeDocx code is one solution.
Alternatively, if you know the only references you have are say, images (as opposed to comments, footnotes etc etc), you could handle those specifically in your code.

Using pdfbox to get form field values

I'm using pdfbox for the first time. Now I'm reading something on the website Pdf
Summarizing I have a pdf like this:
only that my file has many and many different component(textField,RadionButton,CheckBox). For this pdf I have to read these values : Mauro,Rossi,MyCompany. For now I wrote the following code:
PDDocument pdDoc = PDDocument.loadNonSeq( myFile, null );
PDDocumentCatalog pdCatalog = pdDoc.getDocumentCatalog();
PDAcroForm pdAcroForm = pdCatalog.getAcroForm();
for(PDField pdField : pdAcroForm.getFields()){
System.out.println(pdField.getValue())
}
Is this a correct way to read the value inside the form component?
Any suggestion about this?
Where can I learn other things on pdfbox?
The code you have should work. If you are actually looking to do something with the values, you'll likely need to use some other methods. For example, you can get specific fields using pdAcroForm.getField(<fieldName>):
PDField firstNameField = pdAcroForm.getField("firstName");
PDField lastNameField = pdAcroForm.getField("lastName");
Note that PDField is just a base class. You can cast things to sub classes to get more interesting information from them. For example:
PDCheckbox fullTimeSalary = (PDCheckbox) pdAcroForm.getField("fullTimeSalary");
if(fullTimeSalary.isChecked()) {
log.debug("The person earns a full-time salary");
} else {
log.debug("The person does not earn a full-time salary");
}
As you suggest, you'll find more information at the apache pdfbox website.
The field can be a top-level field. So you need to loop until it is no longer a top-level field, then you can get the value. Code snippet below loops through all the fields and outputs the field names and values.
{
//from your original code
PDDocument pdDoc = PDDocument.loadNonSeq( myFile, null );
PDDocumentCatalog pdCatalog = pdDoc.getDocumentCatalog();
PDAcroForm pdAcroForm = pdCatalog.getAcroForm();
//get all fields in form
List<PDField> fields = acroForm.getFields();
System.out.println(fields.size() + " top-level fields were found on the form");
//inspect field values
for (PDField field : fields)
{
processField(field, "|--", field.getPartialName());
}
...
}
private void processField(PDField field, String sLevel, String sParent) throws IOException
{
String partialName = field.getPartialName();
if (field instanceof PDNonTerminalField)
{
if (!sParent.equals(field.getPartialName()))
{
if (partialName != null)
{
sParent = sParent + "." + partialName;
}
}
System.out.println(sLevel + sParent);
for (PDField child : ((PDNonTerminalField)field).getChildren())
{
processField(child, "| " + sLevel, sParent);
}
}
else
{
//field has no child. output the value
String fieldValue = field.getValueAsString();
StringBuilder outputString = new StringBuilder(sLevel);
outputString.append(sParent);
if (partialName != null)
{
outputString.append(".").append(partialName);
}
outputString.append(" = ").append(fieldValue);
outputString.append(", type=").append(field.getClass().getName());
System.out.println(outputString);
}
}

javax.xml.crypto.dsig validation using the public key in the xml

Using javax.xml.crypto.dsig, how do I unmarshal and validate an XMLSignature without specifying the public key? The public key appears to be in the signed xml, but I can't figure out a way to get it.
DOMValidateContext valContext = new DOMValidateContext(key,signatureNode);
XMLSignature signature = fac.unmarshalXMLSignature(valContext);
boolean coreValidity = signature.validate(valContext);
As far as I can tell it's necessary to pass a KeySelector instead of a Key to the DOMValidateContext. However, I can't figure out how to implement a KeySelector.
Here is the only example I've found about how to implement a KeySelector:
http://download.oracle.com/javase/6/docs/technotes/guides/security/xmldsig/XMLDigitalSignature.html
Unfortunately it doesn't work. In that implementation it does the following but always fails because there are no KeyValue elements (it appears that instead of KeyValue elements they are org.jcp.xml.dsig.internal.dom.DOMX509Data elements which don't have a way to ge the key from them).
List list = keyInfo.getContent();
for (int i = 0; i < list.size(); i++) {
XMLStructure xs = (XMLStructure) list.get(i);
if(xs instanceof KeyValue) {
PublicKey pk = null;
try {
pk = ((KeyValue) xs).getPublicKey();
} catch (KeyException ke) {
throw new KeySelectorException(ke);
}
// make sure algorithm is compatible with method
if (algEquals(sm.getAlgorithm(), pk.getAlgorithm())) {
return new SimpleKeySelectorResult(pk);
}
}
}
throw new KeySelectorException("No KeyValue element found!");
So, is there a way to do this? I want to be able to validate the signature of an xml file without having to have the public key. I just want to get the public key from the xml.
Extend the if () condition you have checking to see if xs is an instance of KeyValue to also check instance of X509Data as follows:
else if (xs instanceof X509Data) {
for (Object data : ((X509Data) xs).getContent()) {
if (data instanceof X509Certificate) {
pk = ((X509Certificate) data).getPublicKey();
}
}
}
just include xmldsig.jar to your build path and check the JDK of yours for 1.5 you have to add to your build path
for 1.6 they have inbuilt in it so no need to add for reference
http://java.sun.com/developer/technicalArticles/xml/dig_signature_api/

Categories