Skip to content

Instantly share code, notes, and snippets.

@fingerart
Last active May 18, 2023 11:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fingerart/598ed20d90d6a4e1d9f71cd5a58cfc38 to your computer and use it in GitHub Desktop.
Save fingerart/598ed20d90d6a4e1d9f71cd5a58cfc38 to your computer and use it in GitHub Desktop.
Using the iText signature PDF file on Android
dependencies {
compile 'com.itextpdf:itextg:5.5.10'
compile "com.madgag:scprov-jdk15on:1.47.0.2"
compile "com.madgag:scpkix-jdk15on:1.47.0.2"
}
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
import com.itextpdf.text.pdf.security.TSAClient;
import com.itextpdf.text.pdf.security.TSAClientBouncyCastle;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
/**
* @author FingerArt http://fingerart.me
* @date 2017年08月10日 18:46
*/
public class Ut {
static {
Security.insertProviderAt(new BouncyCastleProvider(), 1);
}
/**
* Creates a PDF document.
*
* @param filename the path to the new PDF document
* @throws DocumentException
* @throws IOException
*/
public static void createPdf(String filename, String content) throws IOException, DocumentException {
Document document = null;
PdfWriter writer = null;
try {
document = new Document();
writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
document.open();
document.add(new Paragraph(content));
} finally {
if (document != null) {
document.close();
}
if (writer != null) {
writer.close();
}
}
}
/**
* Manipulates a PDF file src with the file dest as result
*
* @param src the original PDF
* @param dest the resulting PDF
* @param tsaUrl
* @throws GeneralSecurityException
* @throws IOException
* @throws DocumentException
* @throws FileNotFoundException
* @throws KeyStoreException
* @throws Exception
*/
static void signPdf(@NonNull String src, @NonNull String dest, InputStream pdfCerStream, @NonNull String keystorePassword, @NonNull String keyPassword, String reason, String location, @Nullable String signatureImage, String tsaUrl) throws GeneralSecurityException, IOException, DocumentException {
// private key and certificate
KeyStore ks = KeyStore.getInstance("pkcs12", "BC");
ks.load(pdfCerStream, keystorePassword.toCharArray());
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, keyPassword.toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);
// reader and stamper
PdfReader reader = new PdfReader(src);
PdfStamper stamper = PdfStamper.createSignature(reader, new FileOutputStream(dest), '\0');
// appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(new Rectangle(72, 732, 144, 780), reader.getNumberOfPages(), "sign");
appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);
if (signatureImage != null && !signatureImage.isEmpty()) {
appearance.setSignatureGraphic(Image.getInstance(signatureImage));
appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION);
}
// signature
TSAClient tsaClient = new TSAClientBouncyCastle(tsaUrl, null, null, 6500, DigestAlgorithms.SHA256);
ExternalSignature es = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, "BC");
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, es, chain, null, null, tsaClient, 0, MakeSignature.CryptoStandard.CMS);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment