Hi. Briefly, my goal is to digitally sign a document using the API of the Cloud Signature Consortium for the remote part and openssl for the local part.
First of alI I tried signing only locally, providing hard-coded certificate and private key. It works like a charm. Here, the snippet I used for the purpose. ``` *static* *void* sign_with_signer( CustomSigner &signer, X509 *cert, EVP_PKEY *pkey ) { *[...]* *int* rc; BIO *mem = BIO_new( BIO_s_mem() ); *if*( !mem ) { *[...]* } *unsigned* *int* flags = PKCS7_DETACHED | PKCS7_BINARY; PKCS7 *pkcs7 = PKCS7_sign( cert, pkey, *NULL*, mem, flags ); *if*( !pkcs7 ) { BIO_free( mem ); *[...]* } *while*( len = signer.ReadForSignature( pBuffer, uBufferLen ), len > 0 ) { rc = BIO_write( mem, pBuffer, len ); *if*( *static_cast*<*unsigned* *int*>( rc ) != len ) { PKCS7_free( pkcs7 ); BIO_free( mem ); *[...]* } } * [...]* *if*( PKCS7_final( pkcs7, mem, flags ) <= 0 ) { PKCS7_free( pkcs7 ); BIO_free( mem ); *[...]* } *bool* success = *false*; BIO *out = BIO_new( BIO_s_mem() ); *if*( !out ) { PKCS7_free( pkcs7 ); BIO_free( mem ); *[...]* } *char* *outBuff = *NULL*; *long* outLen; i2d_PKCS7_bio( out, pkcs7 ); outLen = BIO_get_mem_data( out, &outBuff ); *if*( outLen > 0 && outBuff ) { *if*( *static_cast*<size_t>( outLen ) > signer.GetSignatureSize() ) { PKCS7_free( pkcs7 ); BIO_free( out ); BIO_free( mem ); *[...]* } Signature signature( outBuff, outLen ); signer.SetSignature( signature ); success = *true*; } PKCS7_free( pkcs7 ); BIO_free( out ); BIO_free( mem ); *if*( !success ) *[...]* } ``` Now using the CSC `credentials/info` API I have: ``` "cert": { "status": "valid", "certificates": [ "<Base64-encoded_X.509_end_entity_certificate>", "<Base64-encoded_X.509_intermediate_CA_certificate>", "<Base64-encoded_X.509_root_CA_certificate>" ], "issuerDN": "<X.500_issuer_DN_printable_string>", "serialNumber": "5AAC41CD8FA22B953640", "subjectDN": "<X.500_subject_DN_printable_string>", "validFrom": "20180101100000Z", "validTo": "20190101095959Z" }, ``` So I have to build the X509 which I need to sign the document. I guess using something like that: ``` *bool* pdf::CryptoModule::make_certificate(*const* *char* *data, X509 **out_cert) { *if*( !data || !*data ) { *return* *false*; } *if*( !out_cert ) { *return* *false*; } BIO *bio; bio = BIO_new(BIO_s_mem()); BIO_puts(bio, data); // *out_cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); *out_cert = d2i_X509_bio(bio, *NULL*); *if*( !*out_cert ) { *return* *false*; } *return* *true*; } ``` But at this point I don't have the private key! Instead, CSC `signatures/signHash` will provide me the signature object to apply to the document. ``` { "signatures": [ "KedJuTob5gtvYx9qM3k3gm7kbLBwVbEQRl26S2tmXjqNND7MRGtoew==", "Idhef7xzgtvYx9qM3k3gm7kbLBwVbE98239S2tm8hUh85KKsfdowel==" ] } ``` Here is how things should work: [image: page64image25534384] At this point I would like to understand what are the openSSL APIs to use for - get the X509s - get the raw signature of the document to be passed to the Signer who will apply it. In my humble opinion the ``` PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO **in*, *const* EVP_CIPHER *cipher, *int* flags); *int* PKCS7_add_attrib_content_type(PKCS7_SIGNER_INFO *si, ASN1_OBJECT *coid); *int* PKCS7_add0_attrib_signing_time(PKCS7_SIGNER_INFO *si, ASN1_TIME *t); *int* PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si, *const* *unsigned* *char* *md, *int* mdlen); ``` could be what is right for me, but I'm not sure how to use it. Thank you very much and have a nice day!