Certificate for TCPDF - php

I would like to generate a certificate(self-signed at the moment) for an encrypted PDF on the server. What is interesting to me is the workflow on how to to that with TCPDF.
What I did:
1) Generate keys:
openssl req -x509 -nodes -days 365000 -newkey rsa:1024
openssl pkcs12 -export -in tcpdf.crt -out tcpdf.p12
2) Then generate the PDF with the .crt - file
3) Then I started acrobat reader and installed the certificate (tcpdf.p12). I used Document->security settings -> digital id
4) I could import the security settings but still can't open the PDF. Don't know if I am doing it right? What happens that acrobat reader 9.5.4 opens a dialog with input of a password. I give in the password and an error appears -> unknown error -> CRecipientList-218
5) Code I used (basically the same)
$certificate = 'file://../tcpdf.crt';
$info = array(
'Name' => 'TCPDF',
'Location' => 'Office',
'Reason' => 'Testing TCPDF',
'ContactInfo' => 'http://www.tcpdf.org',
);
$pdf->setSignature($certificate, $certificate, 'tcpdfdemo', '', 2, $info);
$pdf->SetProtection($permissions=array('print', 'copy'), $user_pass='', owner_pass=null, $mode=1, $pubkeys=array(array('c' => 'file://../tcpdf.crt', 'p' => array('print'))));
I combined the following examples:
http://www.tcpdf.org/examples/example_052.phps
http://www.tcpdf.org/examples/example_016.phps
P.S.: I know its a very practical example. Just thought its easier to understand the steps I am doing.
Questions:
Is the workflow in general right on how(!) to approach certificates for a PDF with encryption?
When I generate the .p12 file I have to give in a password for that file which I used later on when imported the certificate into acrobat. I'm asking because I have also the possibility "on generation" to give the password.
If the workflow is right...how do I fix the problem?

The approach is basically correct - but you may have missed some detail in it.
I have been using the certificate in *.crt format without the passphrase (including private and public key) and it works fine.
Also note, that you must have installed OpenSSL extension in PHP.
See the comments for method TCPDF::setSignature() by Nicola Asuni:
* To create self-signed signature: openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout tcpdf.crt -out tcpdf.crt
* To export crt to p12: openssl pkcs12 -export -in tcpdf.crt -out tcpdf.p12
* To convert pfx certificate to pem: openssl pkcs12 -in tcpdf.pfx -out tcpdf.crt -nodes
You dont need to install any certificate into Acrobat Reader - generated PDF documents signed with self-signed certificates simply show up as untrusted, but still they can normally open.

I hope you also took a look at the comments ;)
there is a mini how to setup the pdf using provided file
especially:
// To open the document you need to install the private key (tcpdf.p12) on the Acrobat Reader. The password is: 1234
however, you need to provide setProtection with existing key:
'c' => 'file://../tcpdf.crt'
the path you given is just showing where you need to give the path, but the path itself need to be changed
Summary: please read again the comments in the example 016 file, they WILL help to get it working the way you need

Related

PDO connection to remote DB using SSL; FastCGI errors when verifying server cert

I have a remote server with a MariaDB DB that only accepts SSL connections for a certain user, and have generated some self-signed SSL certificates using the following
# Create CA certificate
openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca.pem
# Create server certificate, remove passphrase, and sign it
# server-cert.pem = public key, server-key.pem = private key
openssl req -newkey rsa:2048 -days 3600
-nodes -keyout server-key.pem -out server-req.pem
openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -req -in server-req.pem -days 3600 \
-CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem
# Create client certificate, remove passphrase, and sign it
# client-cert.pem = public key, client-key.pem = private key
openssl req -newkey rsa:2048 -days 3600 \
-nodes -keyout client-key.pem -out client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -req -in client-req.pem -days 3600 \
-CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem
(taken from https://dev.mysql.com/doc/refman/5.6/en/creating-ssl-files-using-openssl.html)
I filled in the details for each certificate as follows
Country Name: GB
Locality Name: Company Town
Organization Name: Company Name
Common Name: DEV CA, DEV Server, DEV Client (respectively)
and left all the other fields left blank
The remote server has the following in my.cnf
[mariadb]
ssl-ca=/path/to/ca.pem
ssl-cert=/path/to/server-cert.pem
ssl-key=/path/to/server-key.pem
I can connect from my local machine's command line by including the following in its my.cnf
[client]
ssl-ca=/path/to/ca.pem
ssl-cert=/path/to/client-cert.pem
ssl-key=/path/to/client-key.pem
I can create a PDO connection from my local machine using the following
$pdo = new PDO(
'mysql:host=xxx.xxx.xxx.xxx;dbname=database_1',
'database_user',
'database_password',
[
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
PDO::MYSQL_ATTR_SSL_KEY => '/path/to/client-key.pem',
PDO::MYSQL_ATTR_SSL_CERT => '/path/to/client-cert.pem',
PDO::MYSQL_ATTR_SSL_CA => '/path/to/ca.pem',
]
);
Unfortunately, if I remove the line
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
I get an Internal Server Error and the following shows up in my MAMP PRO apache error log
… FastCGI: incomplete headers (0 bytes) received from server …
I get no errors in my PHP error log
I can only assume something goes wrong with the certificate verification,
have I missed something? and/or
is it safe to leave PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT set to false?
When a client validates the server certificate, following will be checked
signature
certificate validity period includes the current time
certificate is not revoked (part of CRL)
host name matches CN or alternative name(s)
root ca
PDO with mysqlnd uses PHP streams, which checks the CN field only, but not Subject Alternative Names field(s). According to your code you specify an IP address to connect for, but not a name.
Unfortunately PHP also doesn't offer an additionally method for checking the sha finger print of peer certificate.
See also:
RFC 5280
PHP Bug 71845
is it safe to leave PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT set to
false?
For the most part, if access to your server is secure it is safe, although not recommended, to do this.
The reasons this is failing is that a TLS(SSL) Certificate is granted to a host access address, where the host access address is the IP Address or the Hostname, not the physical host machine. So your Common Name should be either the IP address of the server or the Hostname; whichever is used is what you must use to connect to the Server.
So, as your connecting to the host xxx.xxx.xxx.xxx (from 'mysql:host=xxx.xxx.xxx.xxx;dbname=database_1'), the Common Name on your certificate needs to be xxx.xxx.xxx.xxx

Warning: openssl_pkcs7_sign: error creating PKCS7 structure

We are trying to sign the PAN no. with Digital Signature. We are taking the PAN No. in in.txt file but we are getting error -
Warning: openssl_pkcs7_sign(): error creating PKCS7 structure!
openssl_pkcs7_sign(realpath("in.txt"), "out.txt",
'file://'.realpath('digitalsign.cer'),
'file://'.realpath('private_key.pem'),
array (), PKCS7_NOSIGS
);
Kindly suggest what we can do to resolve this issue.
I think your digital certificate and the Private key is an issue. Kindly create the Digital Certificate and Private Key with below command.
openssl req -x509 -days 365 -newkey rsa:1024 -keyout enc_key.pem -out selfcert.pem
Then after that use that certificate and private key and that will work for you. It worked for me and if still you face issue do comment.

Digital Sign PDF File with PHP and laravel

Hello i search a lot before make this question.
I know there is a paied option to sign pdf setasign.com
I try to use php function:
openssl_pkcs7_sign( FULL_PATH . "/pdforiginal.pdf", //ORIGIANL PDF
FULL_PATH ."signedPDF.pdf", // SIGNED PDF
"file://" . FULL_PATH . "signing_cert.pem",
array( "file://" . FULL_PATH. "private_key.pem",""),array());
signing_cert.pem <- // I Dont understand what is this i just have private_key and public_key. I see some examples where people use private_key here.
My private key dont have password shoud i use blank "" or null ?
If anyone can give me little information about this topic would be really helpful.
I find the solution.
I use FPDI library to open pdf and use tcpdf library to sign it.
That makes the process really simple.
require_once('tcpdf_include.php');
require_once "fpdi.php";
$pdf = new FPDI('P', 'mm', 'A4'); //FPDI extends TCPDF
$pages = $pdf->setSourceFile('document.pdf');
/*
NOTES:
- To create self-signed signature: openssl req -x509 -nodes -days 365000 -newkey rsa:1024 -keyout tcpdf.crt -out tcpdf.crt
- To export crt to p12: openssl pkcs12 -export -in tcpdf.crt -out tcpdf.p12
- To convert pfx certificate to pem: openssl pkcs12 -in tcpdf.pfx -out tcpdf.crt -nodes
*/
$certificate = 'file://data/cert/tcpdf.crt';
// set additional information
$info = array(
'Name' => 'TCPDF',
'Location' => 'Office',
'Reason' => 'Testing TCPDF',
'ContactInfo' => 'http://www.tcpdf.org',
);
for ($i = 1; $i <= $pages; $i++)
{
$pdf->AddPage();
$page = $pdf->importPage($i);
$pdf->useTemplate($page, 0, 0);
// set document signature
$pdf->setSignature($certificate, $certificate, 'tcpdfdemo', '', 2, $info);
}
Now Digital Certificates are being issued on cryptographic devices viz. USB Toke and Smartcards, and user will be holding the same, server might not have private key of the user's certificate. In web application, you need to get the pdf (hash) signed from USB Token or Smartcard connected to client's (browser) device.
You need to get pdf signed from browser itself, since, private key never comes out of USB Token. Please refer to answer https://stackoverflow.com/a/55676351/9659885
For PHP, easily available Java pdf library or any pdf component may be used through JavaBridge running on Tomcat through Apache proxy to digitally sign PDF from Browser USB token and PHP on server side.
I found a better solution to sign, but not only with PHP. You'll need to used the exec() command to do this.
1 - Need to install java. Linux sudo apt install /select_folder/default-jre
2 - Need to instal Portable Signer. Download the ZIP file and run the file jar ( https://sourceforge.net/projects/portablesigner/files/portablesigner/2.0-Release/PortableSigner-Generic-2.0.38c0573.zip/download ). Linux sudo java -jar /select_folder/PortableSigner.jar
3 - After install Portable Signer and choose the installation folder execute the app using the manual ( http://portablesigner.sourceforge.net/ ) with command exec() in php.
Example:
exec("java -jar PortableSigner.jar -n /Users/pfp/Desktop/unsigned.pdf -o /Users/pfp/Desktop/signed.pdf -s /Users/pfp/Desktop/certificate.pfx -p MySecretPassword");
In documentation you have many options to sign. I hope this ll help a lot the PHP comumunity here.

Certificate not accepted. Unable to set private key file

I try to make a connection through SoapClient. I need a certificate for this. I received a .pfx certificate. I used the following command to create a .pem file.
openssl pkcs12 -in cert.pfx -out cert.pem -nodes
There is a password in the certificate so I need to enter it before I get the cert.pem file. So far so good, I think.
Now I try to connect to the WSDL service.
$url = "https://test.website.com/webservices/transfer.asmx?WSDL";
$cert = '/path/to/cert.pem';
$passphrase = "12345678";
$soapClient = new SoapClient($url, array('local_cert'=>$cert,'passphrase'=>$passphrase));
I get the following error:
(Warning) SoapClient::SoapClient(): Unable to set private key file `/var/www/vhosts/............./cert.pem'
I think the problem is the certificate. Is the way that I converted the .pfx to a .pem the correct way?
The problem you're running into is that a .pem certificate is always supposed to be an encrypted file. According to the OpenSSL docs for the pkcs12 command when you used -nodes it didn't encrypt anything, rather put each node into plain text, which caused the .pem certificate to be invalid and your SoapClient couldn't parse the invalid file.
To fix this, hopefully you haven't deleted the original cert.pfx, just re-convert it using this line:
openssl pkcs12 -in cert.pfx -out cert.pem -clcerts
and your cert.pem file will be correct.
Today I had this problem with an invalid Cert/Private combination, meaning the cert wasn't belonging to the specified key.
You can verify this problem using:
openssl rsa -noout -modulus -in server.key | openssl md5
openssl x509 -noout -modulus -in server.crt | openssl md5
key and cert should return the same checksum. If not, somebody has mixed up some files.
The same procedure works for CSRs as well:
# and for a CSR
openssl req -noout -modulus -in server.csr | openssl md5

Warning: openssl_pkcs7_sign() [function.openssl-pkcs7-sign]: error getting private key in C:\xampp\htdocs\this\tcpdf\tcpdf.php on line 8366

I am using TCPDF to sign PDF, but when running the example 52 I got this error:
Warning: openssl_pkcs7_sign() [function.openssl-pkcs7-sign]: error getting
private key in C:\xampp\htdocs\this\tcpdf\tcpdf.php on line 8366
Could you please tell me or guide me where is the problem. I am just running the example without changing anything. I am using xampp.
The problem is with the location from where it tries to access the private key. Instead of '' like in their example use 'file://'.( dirname(FILE)).'./path/to/file'. This worked for me.
I solved it by using:
$certificate = 'file://'.realpath('../tcpdf.crt');
When you create your own certificate use this:
/*
NOTES:
- To create self-signed signature: openssl req -x509 -nodes -days 365000 -newkey rsa:1024 -keyout tcpdf.crt -out tcpdf.crt
- To export crt to p12: openssl pkcs12 -export -in tcpdf.crt -out tcpdf.p12
- To convert pfx certificate to pem: openssl pkcs12 -in tcpdf.pfx -out tcpdf.crt -nodes
*/
Finally, after weeks ago, I found the solution. I just donwloaded the TCPDF 5.9 Version and it works :D if you wanna try, here's the link to download that version
link: https://sourceforge.net/code-snapshots/git/u/u/u/mynetx/tcpdf.git/u-mynetx-tcpdf-5828c0d80580cbad069988e2067ad5e37e1e98e7.zip

Categories