Digital Sign PDF File with PHP and laravel - php

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.

Related

remote SSL Connection to AWS(Keypairs) using PHP

I am trying to connect to an AWS RDS instance using SSL but I keep getting this error:
mysqli_real_connect(): Unable to set private key file
What im doing is this:
Generate key pairs in AWS, keep private key.
Use OpenSSL to get the cert.pem using this command and the private key that I got from AWS: openssl req -newkey rsa:2048 -nodes -keyout private-key-generated-by-AWS.pem -x509 -days 365 -out certificate.pem
I downloaded the cacert.pem from this website: https://curl.haxx.se/docs/caextract.html
Here is my code:
mysqli_ssl_set($con,"sshconn.pem","certificate.pem","cacert.pem",NULL,NULL);
if (!mysqli_real_connect($con,"myAWSendpoint","username","password","DBname"))
{
die("Connect Error: " . mysqli_connect_error());
}
mysqli_close($con);
?>
I am pretty sure I am not setting my private key correctly but I don't know what I'm doing wrong, any suggestions? Thank you!
AWS RDS uses server side authentication, not client side. You'll need to the master password once you setup the SSL connection or whatever users you have provisioned inside the DB or IAM users.
https://dev.mysql.com/doc/refman/5.6/en/using-encrypted-connections.html
A root certificate that works for all regions can be downloaded at https://s3.amazonaws.com/rds-downloads/rds-ca-2015-root.pem
Intermediates are here: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html
mysql -h myinstance.c9akciq32.rds-us-east-1.amazonaws.com
--ssl-ca=[full path]rds-combined-ca-bundle.pem --ssl-verify-server-cert
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_MySQL.html#MySQL.Concepts.SSLSupport

Telegram BOT - setWebhook not working

I'm new to creating telegram bots and I really don't know where to start.
Only thing I know about is PHP.
Making it simple I have a VPS with Windows Server 2008 R2 installed on it and I've made a self-signed certificate using
openssl req -newkey rsa:2048 -sha256 -nodes -keyout server.key -x509 -days 365 -out server.pem -subj "/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn Company/CN=YOURDOMAIN.EXAMPLE"
Then I converted PEM to CER using
openssl x509 -inform PEM -in server.pem -outform DER -out server.cer
I'v had WAMP server installed and set it to work with server.cer & server.key as certificate and key then I'v tested the HTTPS(443) and it worked.
Then I installed a REST client on the chrome and sent URL of the bot.php and PEM file as multipart form data as the official documentation said.
Now I get this error:
{
ok: false,
error_code: 400,
description: "Error: Bad webhook: Posix Error: Success: getaddrinfo: Name or service not known"
}
and ... I'm here now ! :| asking you for help
What is the problem and how should I solve this
Thanks in advance :)
NOTE: I don't have a domain I'm using my VPS's IP
Telegram requires valid ssl certificate for your domain.
I will tell how I solved this.
You can use NGROK that can expose local ip to the internet with temporary domain and https enabled.
Link to install - https://ngrok.com/
After you install it, just run in your console:
ngrok http 127.0.0.1:8003
(ofc use ip and port of from your WAMP configuration)
and you will get a free temporary domain (it will look like https://f9eb2f08.ngrok.io) with https enabled.
Then set url with your new domain as a telegram webhook_url and bot's requests will go to your local server as long as NGROK is running.

Certificate for TCPDF

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

Trouble connecting to SSL-encrypted web service with PHP

I got two certificate files from the provider, one in a .cer-format and one in a .p7b-format. I then converted the p7b-certificate to a p12-certificate. With this certificate I'm able to connect to the wsdl from my browser.
Then I proceeded to convert that certificate to .pem-format, using some instructions I found on this site.
openssl pkcs12 -clcerts -nokeys -out test.pem -in mycert.p12
openssl pkcs12 -nocerts -out key.pem -in mycert.p12
then combing the cert with the key using the following command:
cat test.pem key.pem > cert.pem
Heres my construct for the web service class:
public function __construct() {
$wsdl_url = 'https://url.to/web_service?wsdl';
$pass = 'passphrase';
$cert = 'cert.pem';
try {
$this->client = new SoapClient($wsdl_url, array('local_cert' => $cert, 'passphrase' => $pass));
} catch(SoapFault $e) {
print_r($e);
}
}
And here is the error:
SSL operation failed with code 1. OpenSSL Error messages: error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca in /var/www/html/..
Trying to verify the certificate using:
openssl verify cert.pem
gives me the following error:
error 20 at 0 depth lookup:unable to get local issuer certificate
I've also tried creating the .pem-certificate using the following openssl command:
openssl pkcs12 -in mycert.p12 -out mycert.pem
Verifying this gives me OK, but PHP gives me the following error:
Unable to set local cert chain file `mycert.pem'; Check that your cafile/capath settings include details of your certificate and its issuer
I'm assuming it should be possible to make it work somehow, as I am able to access the wsdl through my browser, by using the .p12-certificate. But I'm not able to locate a solution as to how I should proceed.
Thanks in advance.
I think you have a few problems here. Firstly, I don't think your options for the local certificate are being used by the constructor for the SoapClient object. The options array does not support SSL config options. Secondly, given that the options you're supplying to the SoapClient are not being used Open SSL is complaining about the certificate on the remote host being a self certified certificate.
I think it should be possible to get around this but without playing with the code I can't be sure on all of the options. I think you need to create a custom stream context using stream_context_create() to set the SSL options you need (have a look at http://ca.php.net/stream_context_create and the context options for SSL). This can then be passed to the SoapClient object as the stream_context option in the config array. Using the stream_context you can set the various SSL options that you need and these will override the defaults.
I'm sorry I can't be more precise on the options you need to set. Hopefully playing around with the stream context will solve your issue.
I am thinking that it is unable to find the root certificate that issued the certificate that you were provided with.
Certificates are normally signed and issued by a signing authority, and your client needs to know the public key of the signing authority. If your certificate is a self signed certificate then it won't matter.
To check
openssl x509 -text -noout -in key.pem
Check the output and look for Issuer. If the issuer is not the same as the CN of the certificate then you need a root certificate from the signing authority that provided your certificate.
You can normally grab it by using a browser to open your wsdl address and checking the certificate chain and exporting the root certificate from the hierarchy tab.
Where you save it in your situation I am not sure, but there will be something to point to a trust store of some type.

Extract public key from cer file to use in nusoap

Can someone tell me how can I extract a public keu in .pem format from a .cer file ?
I'm trying to configure webservice over https with nusoap.
Tks,
ED
openssl x509 -inform der -in <certificate> -noout -pubkey
Should print out the public key.
Any time I need to convert certificate formats I like to hop on my Linux shell and use the openssl CLI.
Take a look at this page for common openssl commands. You will be most interested in the one titled "Convert DER (.crt .cer .der) to PEM".

Categories