Creating PAdES B-LT Signature
This guide will demonstrate the process of applying PAdES B-LT signature to a PDF document using UniPDF.
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 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 following section will explain the example code line by line.
The import
section in lines 8-26
, imports the necessary dependencies.
Then in lines 28-35
, the license key is loaded and set to authenticate library request.
In line 37
a usage message is defined. This holds the information to be displayed to the user when the code is run.
The main
function starts in line 39
. In the beginning section of this function, i.e. in line 39-49
, the necessary values are obtained from the command line arguments.
In line 52-60
, The private key and X509 certificate are decoded from the PFX file using:
pfxData, err := ioutil.ReadFile(pfxPath)
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)
}
The PEM file, whose path is provided via the command line arguments, is decoded to get a CA Certificate in lines 63-75
. The following code accomplishes the decoding process.
caCertF, err := ioutil.ReadFile(pemPath)
if err != nil {
log.Fatal("Fail: %v\n", err)
}
certDERBlock, _ := pem.Decode(caCertF)
cacert, err := x509.ParseCertificate(certDERBlock.Bytes)
Following this, in lines 78-93
, a new PdfReader is created from the input file using:
file, err := os.Open(inputPath)
if err != nil {
log.Fatal("Fail: %v\n", err)
}
defer file.Close()
reader, err := model.NewPdfReader(file)
if err != nil {
log.Fatal("Fail: %v\n", err)
}
Then using this model.PdfReader
, a new model.PdfAppendr
is created by calling model.NewPdfAppender(reader)
in line 90
. After this, a new signature handler is instantiated in line 99
using:
sighandler.NewEtsiPAdESLevelLT(priv.(*rsa.PrivateKey), cert, cacert, timestampServerURL, appender)
The private key, X509 certificate, the time stamp server URL and the appender object are passed as arguments on this function call. Following this, a new model.NewPdfSignature
is created using:
signature := model.NewPdfSignature(handler)
signature.SetName("PAdES B-LT Signature PDF")
signature.SetReason("TestPAdESPDF")
signature.SetDate(time.Now(), "")
if err := signature.Initialize(); err != nil {
log.Fatal("Fail: %v\n", err)
}
As can be seen from the above snippet, the Name, Reason and Date fields of the model.PdfSignature
are set before calling the Initialize
method.
The signature field and appearance are set in lines 115-128
. Then, In line 130
, the signature is applied using:
if err = appender.Sign(1, field); err != nil {
log.Fatal("Fail: %v\n", err)
}
Then in lines 135-139
the signed document is written to a buffer as follows:
// Write output to buffer.
buffer := bytes.NewBuffer(nil)
err = appender.Write(buffer)
if err != nil {
log.Fatal("Fail: %v\n", err)
}
To correctly save DSS/VRI a second pass is done using:
pdf2, err := model.NewPdfReader(bytes.NewReader(buffer.Bytes()))
if err != nil {
log.Fatal("Fail: %v\n", err)
}
appender2, err := model.NewPdfAppender(pdf2)
if err != nil {
log.Fatal("Fail: %v\n", err)
}
appender2.SetDSS(appender.GetDSS())
Finally, the document is written to a file using:
err = appender2.WriteToFile(outputPath)
if err != nil {
log.Fatal("Fail: %v\n", err)
}
Run the code
Run the code using the following command:
go run pdf_sign_pades_b_lt.go <FILE.PFX> <PASSWORD> <FILE.PEM> <INPUT_PDF_PATH> <OUTPUT_PDF_PATH>