Third Party Signing Example
Sign a document with PCSK@7 signature using any third party signature generator.
/* * Copyright © 2020-2026 PSPDFKit GmbH. All rights reserved. * * The PSPDFKit Sample applications are licensed with a modified BSD license. * Please see License for details. This notice may not be removed from this file. */
package com.pspdfkit.catalog.examples.kotlin
import android.content.Contextimport android.net.Uriimport android.util.Logimport com.pspdfkit.catalog.Rimport com.pspdfkit.catalog.SdkExampleimport com.pspdfkit.catalog.SdkExample.Companion.TAGimport com.pspdfkit.configuration.activity.PdfActivityConfigurationimport com.pspdfkit.document.DocumentSourceimport com.pspdfkit.document.PdfDocumentLoaderimport com.pspdfkit.document.providers.AssetDataProviderimport com.pspdfkit.signatures.DigitalSignatureTypeimport com.pspdfkit.signatures.SignerOptionsimport com.pspdfkit.signatures.SigningConfigurationimport com.pspdfkit.signatures.SigningManagerimport com.pspdfkit.signatures.getPrivateKeyEntryFromP12Streamimport com.pspdfkit.signatures.getX509Certificatesimport com.pspdfkit.ui.PdfActivityIntentBuilderimport kotlinx.coroutines.CoroutineScopeimport kotlinx.coroutines.Dispatchersimport kotlinx.coroutines.launchimport java.io.Fileimport java.io.IOExceptionimport java.security.GeneralSecurityExceptionimport java.security.KeyStore
/** * An example showing the ability to sign a document using a third-party service. * */class ThirdPartySigningExample(context: Context) : SdkExample(context, R.string.thirdPartySigningExampleTitle, R.string.thirdPartySigningExampleDescription) {
override fun launchExample(context: Context, configuration: PdfActivityConfiguration.Builder) { val assetName = "Form_example.pdf"
val unsignedDocument = PdfDocumentLoader.openDocument(context, DocumentSource(AssetDataProvider(assetName))) val keyEntryWithCertificates = getPrivateKeyEntry(context) val signatureFormFields = unsignedDocument.documentSignatureInfo.signatureFormFields val outputFile = File(context.filesDir, "signedDocument.pdf") outputFile.delete() // make sure output is deleted from previous runs.
/** [SignerOptions] contains all the required configuration for [SigningManager]*/ val signerOptions = SignerOptions.Builder(signatureFormFields[0], Uri.fromFile(outputFile)) .setType(digitalSignatureType).build() CoroutineScope(Dispatchers.Main).launch { SigningManager.getDataToSign(context, signerOptions).onSuccess { unsignedData -> // --- Start --- // // This code can be replaced by a third party signing service that signs the data in PKCS@7 format. val signingConfiguration = SigningConfiguration( privateKey = keyEntryWithCertificates.privateKey, certificates = keyEntryWithCertificates.getX509Certificates() ) val signResponse = if (digitalSignatureType == DigitalSignatureType.BASIC) { SigningManager.signWithBasicSignature(context, signingConfiguration, unsignedData.first, unsignedData.second) } else { SigningManager.signWithCAdESSignature(context, signingConfiguration, unsignedData.first, unsignedData.second) } // --- End --- //
signResponse.onSuccess { signedData -> SigningManager.embedPKCS7Signature(context, signerOptions, signedData).onSuccessEmpty { val intent = PdfActivityIntentBuilder.fromUri(context, Uri.fromFile(outputFile)) .configuration(configuration.build()) .build() context.startActivity(intent) }.onError { Log.e(TAG, "embedPKCS7Signature: ${it.localizedMessage}") } }.onError { Log.e(TAG, "signWithBasicSignature: ${it.localizedMessage}") } }.onError { Log.e(TAG, "getDataToSign: ${it.localizedMessage}") } } }
/** * Loads the [KeyStore.PrivateKeyEntry] that will be used by our [SigningManager]. */ @Throws(IOException::class, GeneralSecurityException::class) private fun getPrivateKeyEntry(context: Context): KeyStore.PrivateKeyEntry { // Inside a p12 we have both the certificate (or certificate chain to the root CA) and private key used for signing. val keystoreFile = context.assets.open("digital-signatures/ExampleSigner.p12") return getPrivateKeyEntryFromP12Stream(keystoreFile, "test") }}This code sample is an example that illustrates how to use our SDK. Please adapt it to your specific use case.