Sign pdf file using cert from token device

Good day,

I’m downloading a .pfx certificate from AmazonWebServices to my app, then export the certificate to a token device.

Now I want to sign my pdf file using the certificate in the token device, in using .pfx cert situated in the app I would use OpenSSLSignatureHandler extended from PTSignatureHandler object and parse the .pfx cert path to it and be able to sign my pdf as shown below:

@interface OpenSSLSignatureHandlerSapo : PTSignatureHandler {

SHA_CTX m_sha_ctx;
EVP_PKEY *mp_pkey; // private key
X509 *mp_x509; // signing certificate
STACK_OF(X509) *mp_ca; // certificate chain up to the CA
}

  • (id) init:(NSString *)p12file password:(NSString *)password;
  • (NSData*) CreateSignature;
  • (void) AppendData:(NSData *)data;
  • (NSString*) GetName;
  • (void) dealloc;

So now I want to use the blobKey in the token device to be able to sign, How do I go about that in Objective C?

Thank you.

Hi Sipho,

Sorry for the delay, I was trying to get a better answer for you, but it is unclear what you are trying to do, and how PDFNet fits in.

So now I want to use the blobKey in the token device to be able to sign, How do I go about that in Objective C?

This sounds like a general iOS/Objective-C query.

Hi Ryan,

To further explain what I’m trying to accomplish .

I’m downloading a .pfx certificate from AmazonWebServices to my phone, then export the certificate to an external token device via bluetooth.
Now, when I’m signing my pdf file - I read / connect to the external token device via bluetooth and parse the certificate from external token device to my app, the certificate comes back as NSMutableData to parse it to an extended OpenSSLSignatureHandler Object class I’ve created with the below methods.

Initially I would pass the .pfx file to the init method, now i have to pass the NSMutableData (cert) from the token device and I’m getting this exception "@throw ([NSException exceptionWithName: @“PDFNet Exception” reason: @“Cannot parse private key.” userInfo: nil]); ".

HEADER FILE

#import <Foundation/Foundation.h>

#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pkcs12.h>
#include <openssl/pkcs7.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>

#import <PDFNet/PDFNetOBJC.h>
#import <PDFNet/PDFViewCtrl.h>

@interface OpenSSLSignatureHandler : PTSignatureHandler {

SHA_CTX m_sha_ctx;
EVP_PKEY *mp_pkey; // private key
X509 *mp_x509; // signing certificate
STACK_OF(X509) *mp_ca; // certificate chain up to the CA
}

  • (id) init:(NSString *)p12file password:(NSString )password certder: (NSMutableData) certData ;
  • (NSData*) CreateSignature;
  • (void) AppendData:(NSData *)data;
  • (NSString*) GetName;
  • (void) dealloc;

@end

IMPLEMENTATION FILE

#import “OpenSSLSignatureHandler.h”

@implementation OpenSSLSignatureHandler

  • (id)init:(NSString *)p12file password:(NSString *)password {

if (self = [super init]) {
// Initialize OpenSSL library
CRYPTO_malloc_init();
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();

FILE* fp = fopen([p12file cStringUsingEncoding: NSASCIIStringEncoding], “rb”);
if (fp == NULL)
@throw ([NSException exceptionWithName: @“PDFNet Exception” reason: @“Cannot open private key.” userInfo: nil]);

PKCS12* p12 = d2i_PKCS12_fp(fp, NULL);
fclose(fp);

if (p12 == NULL)
@throw ([NSException exceptionWithName: @“PDFNet Exception” reason: @“Cannot parse private key.” userInfo: nil]);

mp_pkey = NULL;
mp_x509 = NULL;
mp_ca = NULL;
int parseResult = PKCS12_parse(p12, [password cStringUsingEncoding: NSASCIIStringEncoding], &mp_pkey, &mp_x509, &mp_ca);
PKCS12_free(p12);

if (parseResult == 0)
@throw ([NSException exceptionWithName: @“PDFNet Exception” reason: @“Cannot parse private key.” userInfo: nil]);

//initialize sha context
SHA1_Init(&m_sha_ctx);
}
return self;
}

  • (NSData *)CreateSignature {

unsigned char sha_buffer[SHA_DIGEST_LENGTH];
memset((void*) sha_buffer, 0, SHA_DIGEST_LENGTH);
SHA1_Final(sha_buffer, &m_sha_ctx);

PKCS7* p7 = PKCS7_new();
PKCS7_set_type(p7, NID_pkcs7_signed);

PKCS7_SIGNER_INFO* p7Si = PKCS7_add_signature(p7, mp_x509, mp_pkey, EVP_sha1());
PKCS7_add_attrib_content_type(p7Si, OBJ_nid2obj(NID_pkcs7_data));
PKCS7_add0_attrib_signing_time(p7Si, NULL);
PKCS7_add1_attrib_digest(p7Si, (const unsigned char*) sha_buffer, SHA_DIGEST_LENGTH);
PKCS7_add_certificate(p7, mp_x509);

int c = 0;
for ( ; c < sk_X509_num(mp_ca); c++) {
X509* cert = sk_X509_value(mp_ca, c);
PKCS7_add_certificate(p7, cert);
}
PKCS7_set_detached(p7, 1);
PKCS7_content_new(p7, NID_pkcs7_data);

PKCS7_SIGNER_INFO_sign(p7Si);

int p7Len = i2d_PKCS7(p7, NULL);
NSMutableData* signature = [NSMutableData data];
unsigned char* p7Buf = (unsigned char*) malloc(p7Len);
if (p7Buf != NULL) {
unsigned char* pP7Buf = p7Buf;
i2d_PKCS7(p7, &pP7Buf);
[signature appendBytes: (const void*) p7Buf length: p7Len];
free(p7Buf);
}
PKCS7_free(p7);

return (signature);
}

  • (void)AppendData:(NSData *)data {
    SHA1_Update(&m_sha_ctx, [data bytes], [data length]);
    return;
    }

  • (NSString *)GetName {
    return (@“Adobe.PPKLite”);
    }

  • (BOOL)Reset {
    SHA1_Init(&m_sha_ctx);
    return (YES);
    }

http://www.pdftron.com/pdfnet/samplecode/DigitalSignaturesTest.cpp.html

Hi

You will need to make sure that the binary data you obtained from your token device is the exact same binary data representation of your original certificate file. If it is, then you will need to use OpenSSL’s BIO APIs to parse it as a binary data. Our sample only shows how to parse a PKCS#12 certificate file into OpenSSL’s PKCS12 structure. It will not be possible to feed binary data directly to the API’s used by our sample. Please consult OpenSSL’s documentation on how to perform binary data parsing. The rest of process should be similar to the sample project we provide (some minor tweaks may be necessary).

If you are using cryptographic token interfaces, you may benefit more into using the PKCS#11 APIs of OpenSSL (Please see OpenSSL’s documentation for more details).