Add Timestamp in Digital Signature
The process of digitally signing and adding timestamp to a PDF file using a PKCS12 (.p12/.pfx) file will be explained in this guide.
Before you begin
You should get your API key from your UniCloud account.
If this is your first time using UniPDF SDK, follow this guide to set up a local development environment.
Project setup
Clone the project repository
In your terminal, clone the examples repository using the following command: It contains the Go code we will be using for this guide.
git clone https://github.com/unidoc/unipdf-examples.git
Then navigate to the signatures
folder in the unipdf-examples
directory.
cd unipdf-examples/signatures
Configure environment variables
Configure your license key using the following command: Replace the UNIDOC_LICENSE_API_KEY
with your API credentials from your UniCloud account.
Linux/Mac
export UNIDOC_LICENSE_API_KEY=PUT_YOUR_API_KEY_HERE
Windows
set UNIDOC_LICENSE_API_KEY=PUT_YOUR_API_KEY_HERE
How it works
The import
section imports the necessary dependencies.
The init
function loads the API license key from the system environment to authenticate the library request.
The main
function which is defined in lines 39-164
, signs and timestamps the document. The function starts by getting the necessary inputs from the command line arguments. In lines 51-59
, it gets the private key and certificate using the following.
pfxData, err := ioutil.ReadFile(p12Path)
if err != nil {
log.Fatal("Fail: %v\n", err)
}
priv, cert, err := pkcs12.Decode(pfxData, password)
if err != nil {
log.Fatal("Fail: %v\n", err)
}
Then a new model.PdfReader
is created from the input file in lines 62-71
. From the PdfReader
object a new PdfAppender is created which is later used to signed the document. Line 80
creates a new model.SignatureHandler
using sighandler.NewAdobePKCS7Detached(priv.(*rsa.PrivateKey), cert)
. Here the private key and the certificate object are given as arguments in the function call.
In line 86
, a new PdfSignature
object is created using model.NewPdfSignature(handler)
. Then the Name
, Reason
and Date
fields of the PdfSignature
are set in the following 3 lines. Following this, the signature is initialized using signature.Initialize()
in line 91
. This prepares the signature dictionary for signing.
Then a new signature field with a visible appearance is created in lines 100-109
as follows:
field, err := annotator.NewSignatureField(
signature,
[]*annotator.SignatureLine{
annotator.NewSignatureLine("Name", "John Doe"),
annotator.NewSignatureLine("Date", "2019.16.04"),
annotator.NewSignatureLine("Reason", "External signature test"),
},
opts,
)
field.T = core.MakeString("Self signed PDF")
The styles for this appearance are specified in the annotator.SignatureFieldOpts
object defined in lines 96-98
like so.
opts := annotator.NewSignatureFieldOpts()
opts.FontSize = 10
opts.Rect = []float64{10, 25, 75, 60}
After that, the document is signed in line 111
using appender.Sign(1, field)
.
In lines 151-118
, a new PdfReader
is created from the signed document. This is done by first writing the signed document to a data buffer and then creating a new reader from that buffer. In line 125
, a new PdfAppender
is created from the new reader. Then a new signature handler is created using sighandler.NewDocTimeStamp("https://freetsa.org/tsr", crypto.SHA512)
. This handler is used to sign the document with a time stamp. Finally, in line 158
the document is written to file.
Run the code
Run the code using the following command:
go run pdf_sign_timestamp.go <FILE.p12> <PASSWORD> <INPUT_PDF_PATH> <OUTPUT_PDF_PATH>