Closed joaofortunato91present closed 6 years ago
This class was introduced in v2.0.3 and this library is currently up to date with v1.8.9, so it will be some time before this library will be caught up. I haven't had a chance to take a look at the code for ExternalSigningSupport yet, but I"ll see what it does and if it can easily be replicated easily.
I believe I've added the functionality you need if that's the only part that's giving you trouble. I've attached an aar with the necessary changes. pdfbox-android-1.8.9.1.aar.zip
Hello Tom! First of all , thanks for the quick response ! I´ve tryed the .aar you uploaded but i have a problem with the implementation. It seems that the methods saveIncrementalForExternalSigning(OutputStream output) and addSignature(PDSignature sigObject) from the PDDocument class do not exist to complete an external signature successfully.
I must have missed PDDocument, Try this one. pdfbox-android-1.8.9.1.aar.zip
Hey Tom, I´ve been around the code for a while and i keep getting an java.lang.ArrayIndexOutOfBoundsException on the COSWriter.doWriteSignature method that the saveIncrementalForExternalSigning(fos) uses. I´ve tryed many things and i think i have nothing wrong with my code.
The code sample i am using is the following:
`package com.example.joao.pdfboxtests2;
import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.os.Bundle;
import com.tom_roush.pdfbox.pdmodel.PDDocument; import com.tom_roush.pdfbox.pdmodel.interactive.digitalsignature.ExternalSigningSupport; import com.tom_roush.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Calendar;
public class MainActivity extends AppCompatActivity { final String signedHashLoc = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/hashSignature-2.sign"; final String pdfToSignLoc = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/pdftosign.pdf"; final String pdfSignedLoc = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/pdfsignedAndroid.pdf"; //PDDocument document; FileInputStream docToSignIS, signedHashIS; FileOutputStream docSignedOS; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
try {
docToSignIS =new FileInputStream(pdfToSignLoc);
signedHashIS =new FileInputStream(signedHashLoc);
docSignedOS =new FileOutputStream(pdfSignedLoc);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//criar o signature dictionary
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName("Example User");
signature.setLocation("Los Angeles, CA");
signature.setReason("Testing");
//data da assinatura
signature.setSignDate(Calendar.getInstance());
System.out.println("Sign externally...");
try {
PDDocument document = PDDocument.load(docToSignIS);
document.addSignature(signature);
ExternalSigningSupport externalSigning =document.saveIncrementalForExternalSigning(docSignedOS);
externalSigning.setSignature(getSignedDigest());
document.save(docSignedOS);
document.close();
docSignedOS.close();
docToSignIS.close();
signedHashIS.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public byte[] getSignedDigest(){
File file = new File(signedHashLoc);
int size = (int) file.length();
byte[] bytes = new byte[size];
try {
BufferedInputStream buf = new BufferedInputStream(signedHashIS);
buf.read(bytes, 0, bytes.length);
buf.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bytes;
}
}`
The error it gives is the following:
In the line:
this.incrementPart[(int)(this.byteRangeOffset + (long)dataToSign - inLength)] = byteRangeBytes[dataToSign];
Meanwhile i´ve tryed to use the following code provided in the samples setup() and happens exactly the same, the arrayIndexOutOfBounds.
// Enable Android-style asset loading (highly recommended) PDFBoxResourceLoader.init(getApplicationContext()); // Find the root of the external storage. root = android.os.Environment.getExternalStorageDirectory(); assetManager = getAssets(); PDDocument document = PDDocument.load(assetManager.open("pdftosign.pdf"));
Thanks in advance
I too get the same error 👍
..
java.lang.RuntimeException:
...
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=20732; index=767721
at com.tom_roush.pdfbox.pdfwriter.COSWriter.doWriteSignature(COSWriter.java:722)
at com.tom_roush.pdfbox.pdfwriter.COSWriter.visitFromDocument(COSWriter.java:1114)
public ExternalSigningSupport saveIncrementalForExternalSigning(OutputStream output) throws IOException { if(this.pdfSource == null) { throw new IllegalStateException("document was not loaded from a file or a stream"); } else { COSWriter writer = new COSWriter(output, this.pdfSource); writer.write(this); ***** this.signingSupport = new SigningSupport(writer); return this.signingSupport; } }
The error is here ** in the write(this)
public void write(PDDocument doc) throws IOException { this.write(doc, (SignatureInterface)null); } is the null correct ?
Seems like this is more difficult than I hoped. Would it be possible for either of you to share a test signature file that fails that I could use for testing?
Hey Tom, Can i have an email to send you the files im using for testing? Some of them are kind of private :)
Never mind, I managed to get the error again with my signature.
Hello Tom,
I have been analyzing the error and i believe i have found the solution by comparing code between the original PDFBox (https://github.com/apache/pdfbox/tree/2bf48eed0223118c22b19c53cff20a2c5ba5fb95) and PDFBox-Android, since i had an external signature solution working on the original one.
By comparing what was added to the original one i have found that by switching the code long inLength = incrementalInput.available();
for long inLength = incrementalInput.length();
at the COSWriter.java
class it seems to work fine.
That's great. I can't check right now, but if everything works as it should, feel free to make a pull request.
Sorry if this is a nub question but I do not find ExternalSigningSupport class when I add this line in build.gradle dependencies -
implementation 'com.tom_roush:pdfbox-android:1.8.10.1'
This class is not available -
import com.tom_roush.pdfbox.pdmodel.interactive.digitalsignature.ExternalSigningSupport;
Why? Does this library still depends on PDFBox below v2.0.3? And can you tell me how to follow these steps to sign PDF using pdfbox-android? I only need this library to digitally sign PDFs. I can generate PDF by PdfDocument class in android.
Hello! I am trying to make a digital signature on PDFs and ive been doing some tests with pdfbox-android. First ive tryed to add a external signature on desktop environment with success using the :
ExternalSigningSupport externalSigning = document.saveIncrementalForExternalSigning(fos); byte[] cmsSignature = Files.readAllBytes(pathToSignedHash); externalSigning.setSignature(cmsSignature);
So this is where the problem comes now, i dont have the required classes on the android pdfbox and i cant seem to find a way around it. Any way to make an external signature work in this actual version of android pdfbox or in any soon release?
By the way great work so far :)