A QSCD can be deployed as a cloud service as long as it meets the required standards. I am not looking to, as of such, create one for legislation reasons but more of a way of my software being able to prove that the certificate come from us.
The idea is to create a PKI where the QSCD 'issues' the user the keys, which then Electronically signs a PDF file. If the public key can decode the file, it proves that it did come from that user (in this case will be a bot account that signs certificates).
I have found online solutions which entitle you to pay for such services but wanted to know how to create my own solution. I came across using openssl_* to achieve this. I took a look at a few answers to find how to create these keys.
The part I am now stuck on is how to load a PDF document and use the private key to electronically sign it and then export the new PDF file and then how to then decrypt it with the public key ensuring that it hasn't been tampered with.
My current attempt looks like this:
$config = array(
"digest_alg" => 'sha512',
"private_key_bits" => 4096,
"private_key_type" => OPENSSL_KEYTYPE_RSA
);
$keyPair = openssl_pkey_new($config);
$privateKey = NULL;
openssl_pkey_export($keyPair, $privateKey);
$keyDetails = openssl_pkey_get_details($keyPair);
$publicKey = $keyDetails['key'];
openssl_pkcs7_sign("toSign.pdf", "signed.pdf"); // how to sign using the private key?
penssl_public_decrypt("signed.pdf", $publicKey);
Related
I'm trying to follow the 3rd party documentation for verifying a webhook body using the Signature header -- the 3rd party will be referred to as 3P going forward).
3P offered a sample Kotlin implementation using a java library. I am using PHP and decided to try gree/jose as my library.
As a sanity check, I've copied their sample data into my implementation, but I am still getting a false outcome.
$signature = '1IJl6VyKU4pYfqMHUd55QBNq5Etbz5a7DOCkID2Nloay76y4f02w2iMXONlyL/Bx9SkrbivOHW1l1XadkUrd5pKUK1fhpcnItukLrsK5ADQOcuEjSLBg9qJffZYooXfc7hOD/fV0sN33W2vBYJspbR3P766DwG/6IO/20f9t/DcSWa79EFZPMnsCicEArNS3iIYBtdZSX5ta5EETt7S8acHbpIlSDrTcYpo0vuz19LQ6SPQqN2LGdR+U7ZOiUQWdfMXhUgE7w94pHQzcOq1IHfw3CylUEcRR/DhrGqs4mBaagO6JpWzeqE1uTAiN579kOtSSqjblTb2AXALTQ3+TtA=='; // taken from "Signature" in headers
$payload = '{"eventId":"569886904","officeId":"132917981","eventType":"INTEGRATION_DEACTIVATED","event":{"integration":{"status":"INACTIVE","webhookId":"2bc47eed-08a0-4d18-a5c0-b7f18ab802e3","officeId":"132917981","createdDateTime":"2020-03-17T23:39:41.804Z","lastUpdatedDateTime":"2020-03-17T23:39:41.804Z"}},"createdDateTime":"2020-03-17T23:39:41.806Z"}'; // this is the body of the request sent to my application
$components = [
'kty' => 'RSA',
'e' => 'AQAB',
'n' => 'ANV-aocctqt5xDRnqomCgsO9dm4hM0Qd75TqG7z2G5Z89JQ7SRy2ok-fIJRiSU5-JfjPc3uph3gSOXyqlNoEh4YGL2R4AP7jhxy9xv0gDVtj1tExB_mmk8EUbmj8hTIrfAgEJrDeB4qMk7MkkKxhHkhLNEJEPZfgYHcHcuKjp2l_vtpiuR9Ouz0febB9K4gLozrp9KHW2K-m0z02-tSurxmmij5nnJ-CEgp0wXcCS4w4G0jve4hcLlL9FU8HKxrb0d4rMQgM3VAal6yG5pwMdtrsch7xA-occwWFC_tHgpDJGNvOJNFtuk7Cit_aom-6U6ssGF13sUtdrog2ePWjVxc=',
'kid' => '2020-03-18',
'alg' => 'RSA256',
]; // the $components array values are sourced by a separate API call to the 3P
$rsa = JOSE_JWK::decode($components); // => phpseclib\Crypt\RSA instance
$publicKey = $rsa->createKey()['publickey']; // this appears to work perfectly
$rsa->loadKey($publicKey);
var_dump($rsa->verify($payload, $rsa->sign($signature))); // bool(false)
I've been floundering with this piece of software for over 2 days now and I feel like I've tried ~100 different things (some proof). I've even tried partially abandoning the gree/jose library. Ultimately, I just need a working solution (regardless of if it is repairing this implementation or entertaining a different implementation/library).
I feel like I am probably missing a step (or two) in preparing my strings prior to calling verify(), but I am too unfamiliar with this process to identify it myself. Of course, verify() doesn't indicate if I'm getting hotter or colder.
Places I've been:
How to convert C# RSA to php?
RSA signature verification in php not working when signed from c# code
https://hotexamples.com/examples/-/-/openssl_verify/php-openssl_verify-function-examples.html
https://www.php.net/manual/en/function.openssl-verify.php
https://en.wikipedia.org/wiki/RSA_(cryptosystem)
Signing JSON objects
https://tools.ietf.org/id/draft-ietf-jose-json-web-signature-09.html
https://hotexamples.com/examples/phpseclib.crypt/RSA/verify/php-rsa-verify-method-examples.html
https://github.com/nov/jose-php
RS256 in Java means RSASSA-PKCS1-v1_5 using SHA-256
$signature = '1IJl6VyKU4pYfqMHUd55QBNq5Etbz5a7DOCkID2Nloay76y4f02w2iMXONlyL/Bx9SkrbivOHW1l1XadkUrd5pKUK1fhpcnItukLrsK5ADQOcuEjSLBg9qJffZYooXfc7hOD/fV0sN33W2vBYJspbR3P766DwG/6IO/20f9t/DcSWa79EFZPMnsCicEArNS3iIYBtdZSX5ta5EETt7S8acHbpIlSDrTcYpo0vuz19LQ6SPQqN2LGdR+U7ZOiUQWdfMXhUgE7w94pHQzcOq1IHfw3CylUEcRR/DhrGqs4mBaagO6JpWzeqE1uTAiN579kOtSSqjblTb2AXALTQ3+TtA=='; // taken from "Signature" in headers
$payload = '{"eventId":"569886904","officeId":"132917981","eventType":"INTEGRATION_DEACTIVATED","event":{"integration":{"status":"INACTIVE","webhookId":"2bc47eed-08a0-4d18-a5c0-b7f18ab802e3","officeId":"132917981","createdDateTime":"2020-03-17T23:39:41.804Z","lastUpdatedDateTime":"2020-03-17T23:39:41.804Z"}},"createdDateTime":"2020-03-17T23:39:41.806Z"}'; // this is the body of the request sent to my application
$components = [
'kty' => 'RSA',
'e' => 'AQAB',
'n' => 'ANV-aocctqt5xDRnqomCgsO9dm4hM0Qd75TqG7z2G5Z89JQ7SRy2ok-fIJRiSU5-JfjPc3uph3gSOXyqlNoEh4YGL2R4AP7jhxy9xv0gDVtj1tExB_mmk8EUbmj8hTIrfAgEJrDeB4qMk7MkkKxhHkhLNEJEPZfgYHcHcuKjp2l_vtpiuR9Ouz0febB9K4gLozrp9KHW2K-m0z02-tSurxmmij5nnJ-CEgp0wXcCS4w4G0jve4hcLlL9FU8HKxrb0d4rMQgM3VAal6yG5pwMdtrsch7xA-occwWFC_tHgpDJGNvOJNFtuk7Cit_aom-6U6ssGF13sUtdrog2ePWjVxc=',
'kid' => '2020-03-18',
'alg' => 'RSA256',
]; // the $components array values are sourced by a separate API call to the 3P
$rsa = JOSE_JWK::decode($components); // => phpseclib\Crypt\RSA instance
$rsa->setHash('sha256');
var_dump($rsa->_rsassa_pkcs1_v1_5_verify($payload, JOSE_URLSafeBase64::decode($signature)));
I have a NodeJS application generating JSON Web Tokens with the PS256 algorithm. I want to try and verify the signatures in these tokens in a PHP application.
So far I've got the following:
My JWT:
eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMTBiYjllYS00YTg0LTQ1ZTMtOTg5My0wYzNhNDYxZmQzMGUiLCJpYXQiOjE2MDU4OTI5NjcsImV4cCI6MTYwNjQ5Nzc2NywiYXVkIjoiNzBiYzcxMTQ1MWM2NDBjOTVlZjgzYjdhNDliMWE0MWIiLCJpc3MiOiIyM2ZhYTRiNC0wNmVlLTRlNGEtYTVjZC05NjJmOTRhMjEzYmYiLCJqdGkiOiI1MTNiYjczZC0zOTY3LTQxYzUtODMwOS00Yjc1ZDI4ZGU3NTIifQ.kLtaSYKyhqzx7Dc7UIz7tqU8TsXabRLxGiaqw21lgCcuf_eBvpiLkFOuXpUs-V8XQunQg8jV-bKlKUIb0pLvipjhRP50IwKDClQgNtIwn4yyX5RyDNGJur0qHNnkHMLaF11NsXGPyhvh-6ogSZjWgyZnkQJkXpz4jggBetwqz1hnicapGfNb6C-UdRcOLyCaiMD4OmvniFVCY6YoKlC6eHdwxsgHAxOSgD1QKiiQX_yAe39ja_axZD2Ii3QaNgO0WXzfWMbqRg_yl0y3kjQFys9iXGvQ1JIKDMLffR3rKVL5PgKSU3e472xcPKf6PNSJzphPi1G_xH2gqg1VVXo3Lg
Decoded:
Header:
(
[alg] => PS256
[typ] => JWT
)
Body:
(
[sub] => 010bb9ea-4a84-45e3-9893-0c3a461fd30e
[iat] => 1605892967
[exp] => 1606497767
[aud] => 70bc711451c640c95ef83b7a49b1a41b
[iss] => 23faa4b4-06ee-4e4a-a5cd-962f94a213bf
[jti] => 513bb73d-3967-41c5-8309-4b75d28de752
)
sub is a GUID user ID (we utilize GUIDs so that if a user's ID is leaked no information can be extrapolated, like the number of users in our system or when a user signed up)
iat is the epoch time that the token was issued (UTC)
exp is the epoch time that the token will expire (UTC)
aud doesn't conform to the JWT spec. I abused this claim to mitigate the effects of stolen tokens. It's the MD5 hash of data sent with every client request that would be difficult for someone to guess. So if someone were to steal this token and use it without sending the appropriate passphrase, the token would be automatically revoked
iss also doesn't conform to the JWT spec. I abused this claim to list the ID of the key used for signing the JWT. This way I can rotate my public-private key pair and know which key to use when validating signatures
jti is a GUID uniquely identifying the JWT. Compared against an in-memory store of revoked tokens
I went with the PS256 algorithm over RS256 because I read on a blog post that it's more secure. Honestly I don't know the difference.
I went with the PS256 algorithm over ES256 because upon testing I found that while ES256 generated smaller signatures (and therefore smaller tokens), it took about 3x longer to compute. My goal is to make this app as scalable as possible, so long computation time is to be avoided.
My public key:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA0wO7By66n38BCOOPqxnj78gj8jMKACO5APe+M9wbwemOoipeC9DR
CGxC9q+n/Ki0lNKSujjCpZfnKe5xepL2klyKF7dGQwecgf3So7bve8vvb+vD8C6l
oqbCYEOHdLCDoC2UXEWIVRcV5H+Ahawym+OcE/0pzWlNV9asowIFWj/IXgDVKCFQ
nj164UFlxW1ITqLOQK1WlxqHAIoh20RzpeJTlX9PYx3DDja1Pw7TPomHChMeRNsw
Z7zJiavYrBCTvYE+tm7JrPfbIfc1a9fCY3LlwCTvaBkL2F5yeKdH7FMAlvsvBwCm
QhPE4jcDINUds8bHu2on5NU5VmwHjQ46xwIDAQAB
-----END RSA PUBLIC KEY-----
Using jsonwebtoken for NodeJS I can verify this token and authorize requests made using it. So all of the data seems good, the key works, and the math checks out.
However I've run into two problems when trying to verify the token in PHP:
1. The public key doesn't seem to be valid?
$key = openssl_pkey_get_public($pem);
print_r($key);
die();
This code prints out "false" - suggesting that the key could not be read from the PEM text posted above. Googling around I found this comment in the PHP manual which provided a solution. I did as instructed (removed new-lines from my key, prepended MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A, then wrapped to 64 characters) and for some reason openssl_pkey_get_public($pem) actually returned an OpenSSL Public Key now. I'm not really keen on using copy/paste solutions I don't understand, though, and the comment mentioned that this will only work for 2048-bit keys, which concerns me if we ever want to upgrade our security in the future.
After making the changes suggested to my key the new key looks like this:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0wO7By66n38BCOOPqxnj
78gj8jMKACO5APe+M9wbwemOoipeC9DRCGxC9q+n/Ki0lNKSujjCpZfnKe5xepL2
klyKF7dGQwecgf3So7bve8vvb+vD8C6loqbCYEOHdLCDoC2UXEWIVRcV5H+Ahawy
m+OcE/0pzWlNV9asowIFWj/IXgDVKCFQnj164UFlxW1ITqLOQK1WlxqHAIoh20Rz
peJTlX9PYx3DDja1Pw7TPomHChMeRNswZ7zJiavYrBCTvYE+tm7JrPfbIfc1a9fC
Y3LlwCTvaBkL2F5yeKdH7FMAlvsvBwCmQhPE4jcDINUds8bHu2on5NU5VmwHjQ46
xwIDAQAB
-----END PUBLIC KEY-----
(note that this is the same key, just with 32 magic bytes prepended to the beginning of it and "BEGIN RSA PUBLIC KEY" replaced with "BEGIN PUBLIC KEY")
2. The signature fails to verify (possibly because I'm using PS256 and not RS256)
Ignoring the issues with #1 for now and moving on to the next step, I tried to verify my signature like so:
$success = openssl_verify($jwtHeader . "." . $jwtBody, $jwtSignature, $key, OPENSSL_ALGO_SHA256);
This returned false. Meaning the signature was not valid. But I know the signature was valid because it worked fine in NodeJS. So I suspect the issue here revolves around my choice of algorithm.
How do I get PHP to properly verify this token?
Update 1
Here's the code that I'm using to verify my tokens in NodeJS. This is a HapiJS + TypeScript project, but you should be able to make sense of it. jwt is just defined as import * as jwt from "jsonwebtoken";:
jwt.verify(
token,
server.plugins["bf-jwtAuth"].publicKeys[tokenData.iss].key,
{
algorithms: [options.algorithm],
audience: userHash,
maxAge: options.tokenMaxAge
},
err =>
{
// We can disregard the "decoded" parameter
// because we already decoded it earlier
// We're just interested in the error
// (implying a bad signature)
if (err !== null)
{
request.log([], err);
return reject(Boom.unauthorized());
}
return resolve(h.authenticated({
credentials: {
user: {
id: tokenData.sub
}
}
}));
}
);
There's not too much to see here, because I just relied on a third-party tool to do all of the validation for me. jwt.verify(...) and it worked like magic.
Update 2
Assuming that my issue lie in the algorithm being used (PS256 vs RS256) I started searching around and found this StackOverflow post which pointed me at phpseclib
We actually coincidentally already had phpseclib installed via Composer as a dependency of Google's auth SDK, so I bumped it up to a top-level dependency and gave it a try. Unfortunately I still ran into an issue. Here's my code so far:
use phpseclib\Crypt\RSA;
// Setup:
$rsa = new RSA();
$rsa->setHash("sha256");
$rsa->setMGFHash("sha256");
$rsa->setSignatureMode(RSA::SIGNATURE_PSS);
// The variables I'm working with:
$jwt = explode(".", "..."); // [Header, Body, Signature]
$key = "..."; // This is my PEM-encoded string, from above
// Attempting to verify:
$rsa->loadKey($key);
$valid = $rsa->verify($jwt[0] . "." . $jwt[1], base64_decode($jwt[2]));
if ($valid) { die("Valid"); } else { die("Invalid"); }
Neither die() statement is reached as I hit an error on the $rsa->verify() line with the following:
ErrorException: Invalid signature
at
/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php(2693)
Looking at this line in the library, it looks like it's failing at the "length checking" step:
if (strlen($s) != $this->k) {
user_error("Invalid signature");
}
I'm not sure what length it's expecting, though. I passed the raw signature directly from the JWT
After messing with this all day I finally figured out the missing piece.
First, some quick notes on the original question (already touched on in the updates):
To do RSA signatures with PSS padding ("PS256") you will need a third-party library, because the OpenSSL functions in PHP don't support this. A common recommendation is phpseclib
The 32 magic bytes I had to add to the key were only a quirk of PHP's OpenSSL functions and don't need to be utilized with phpseclib
With that said, my final problem (with the signature being "invalid") was:
JWT signatures are base64URL encoded, not base64 encoded
I wasn't even aware there was an RFC specification for base64URL encoding. It turns out you just replace every + with a - and every / with an _. So instead of:
$signature = base64_decode($jwt[2]);
It should be:
$signature = base64_decode(strtr($jwt[2], "-_", "+/"));
This works and my signature finally validates!
I am a completely new person to cryptography. I have tried HS256, RS256 but they got cracked. Where can I find RS512 or higher security algorithm tutorial for PHP REST?
I tried with documentation of
https://github.com/firebase/php-jwt there is documentation for RS256. but token generated using that one gets cracked here https://base64decode.org. I have tried with longer length keys as well.
The I tried with https://github.com/web-token/jwt-framework There is description for components but hardly I could understand about how to use it.
$token = array(
"iss" => $iss,
"aud" => $aud,
"iat" => $iat,
"nbf" => $nbf,
"exp" => $exp,
"data" => array(
"egfield1" => $user->egfield1,
"egfield2" => $user->egfield2,
"egfield3" => $user->egfield3,
"egfield4" => $user->egfield4
)
);
//example private
$privateKey = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC8kGa1pSjbSYZVebtTRBLxBz5H4i2p/llLCrEeQhta5kaQu/Rn
vuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t0tyazyZ8JXw+KgXTxldMPEL9
5+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4ehde/zUxo6UvS7UrBQIDAQAB
AoGAb/MXV46XxCFRxNuB8LyAtmLDgi/xRnTAlMHjSACddwkyKem8//8eZtw9fzxz
bWZ/1/doQOuHBGYZU8aDzzj59FZ78dyzNFoF91hbvZKkg+6wGyd/LrGVEB+Xre0J
Nil0GReM2AHDNZUYRv+HYJPIOrB0CRczLQsgFJ8K6aAD6F0CQQDzbpjYdx10qgK1
cP59UHiHjPZYC0loEsk7s+hUmT3QHerAQJMZWC11Qrn2N+ybwwNblDKv+s5qgMQ5
5tNoQ9IfAkEAxkyffU6ythpg/H0Ixe1I2rd0GbF05biIzO/i77Det3n4YsJVlDck
ZkcvY3SK2iRIL4c9yY6hlIhs+K9wXTtGWwJBAO9Dskl48mO7woPR9uD22jDpNSwe
k90OMepTjzSvlhjbfuPN1IdhqvSJTDychRwn1kIJ7LQZgQ8fVz9OCFZ/6qMCQGOb
qaGwHmUK6xzpUbbacnYrIM6nLSkXgOAwv7XXCojvY614ILTK3iXiLBOxPu5Eu13k
eUz9sHyD6vkgZzjtxXECQAkp4Xerf5TGfQXGXhxIX52yH+N2LtujCdkQZjXAsGdm
B2zNzvrlgRmgBrklMTrMYgm1NPcW+bRLGcwgW2PTvNM=
-----END RSA PRIVATE KEY-----
EOD;
$jwt = JWT::encode($token, $privateKey, 'RS256');
//example token RS256 generated
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJkZGQuaW4iLCJhdWQiOiJubm4uY29tIiwiaWF0IjoxNTQ4NTA0MDQzLCJuYmYiOjE1NDg1MDQwNDMsImV4cCI6MTU0ODU5MDQ0MywiZGF0YSI6eyJibGFoIGJsYWggYmxhaCI6ImJsYWggYmxhaCBibGFoIn19.Z9PdtP0ziezMxEpVBvgdsLBKndcy1fHDe5I2ypxvd2BEXSXxifLw2zJ3o3bcVZ5MogBaBbZyJOIxHA5M2XnLah90e48wVo5rXlG13edPCnPy4yt6onSfNO86Jbimr-JmQqDiN2oCeFBVCmqWu0wGxHZsyiOfp1dkBuyCJNz6mi0
issue is that it does get decoded on that site without any key
I am not able to understand am I doing wrong here or the algorithms are crackable or something. Please guide. Thank you
I think you have some concepts mixed up. JWT's, or better known as JSON Web Tokens, are built on the cryptology concept of message authentication code (MAC).
MAC gives the ability to confirm that the message came from the stated sender. It does not 'encrypt' the data thus you being able to see the direct contents of the message.
Base64 is a mutual translator for any datatype, JWT will use this encoding so you can put objects, arrays or whatever data you like inside of these tokens. Only, it ensures that no modification has been made to it.
For example, user A steals user B's JWT. He wants to access more data for more period of time so he tries to alter the exp property, he cannot resign the JWT with the MAC since he does not know the secret (in your case, the $privateKey).
When he then sends the new JWT to your server, it will throw a InvalidSignatureError which you can catch with your try catch finally blocks.
This can throw multiple errors, like expired token, so I'd suggest using catch(Exception $e) and then working with what type of error it was.
If you're looking to encrypt the contents (although it defeats the point of using JWT) you can use LibSodium, or a container I made for making it easier.
If you do not want to encrypt the $token, then do not put sensitive items inside of the token.
I am studying the digital certificates in PKI ( Public Key Infrastructure ). Almost all manuals / pages regarding this give following similar steps.
Get subject identity + subject public key, (AND/OR Encrypted Message hash with subject's private key) and build a certificate.
Sign certificate with CA's private key
At destination, verify certificate with CA's public key
Now I am able to find way in php (using openssl lib) to for 1st and 2nd step which can generate a certificate and sign it ( optionally generate a signature hash and sign it too ) through openssl APIs.
But Issue with third step, Their are no guide line or function call which show how to verify certificate with CA's public key.
If I am missing something ?
Example code I checking is like below
$data = 'my data';
//create new private and public key
$req_key = openssl_pkey_new(array(
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
));
$dn = array(
"countryName" => "IN",
"stateOrProvinceName" => "Delhi",
"organizationName" => "example.net",
"organizationalUnitName" => "Security",
"commonName" => "example.net"
);
$req_csr = openssl_csr_new ($dn, $req_key);
$req_cert = openssl_csr_sign($req_csr, null, $req_key, 365);
openssl_x509_export ($req_cert, $out_cert);
echo $out_cert;
BACKGROUND : I need to implement PKI based data sharing/validating for some application. It would be involve some data entity (data entity would have its on public and private key) encrypted at source side and then send to destination. Then destination decrypt and get clear data. But that whole must involve PKI that means digital signature + digital certificate implementation along with.
This task isn't pretty straightforward in PHP. In fact, PHP isn't good tool for implementing CA stuff. It supports basic PKI operations but that's all. I see three options:
X.509 is just DER encoded ASN.1 structure. You can inspect it with guiDumpASN-ng for example. There are also some ASN.1 libraries in PHP world. Basicaly, the CA signature is inside certificate. If you'll able to extract it, you can then verify digital signature on your own.
http://php.net/manual/en/function.openssl-verify.php#98282
Try to use function like openssl-x509-checkpurpose that should be able to check certificate chain.
Try to use phpseclib - look at Validate X.509 certificates -> validateSignature().
I hope it will help you a little bit.
Do not mess up with implementing certificates validation by yourself but look for an implementation of the CPV (Certification Path Validation) algorithm, which includes all the validations required to be performed in a certification chain, where certificate signature validation is only one of them.
Now, I've been looking for a PHP API to perform CPV but I found none so I resorted to execute the following external OpenSSL command from PHP:
exec("openssl verify -CAfile trusted_root_cas.pem -untrusted intermediate_cas.pem endentity_cert.pem", $output, $return_var);
if ($return_var == 0) {
echo "Certification path validation completed successfully";
} else {
echo "Certification path validation completed with errors";
}
Where all trusted_root_cas.pem, intermediate_cas.pem and endentity_cert.pem could be temporal files created just for the execution of the previous command.
Now, if you want to know what openssl verify does, execute man verify:
The verify command verifies certificate chains.
Previously I have created system that was sending SOAP messages using certificate.
Example shows how it was done:
$client_options = array();
$client_options['local_cert'] = '<path to .pem file>';
$client_options['passphrase'] = '<.pem file password>';
$client = new SoapClient('<address to wsdl file>', $client_options);
$tmp_res = $client->some_function($params);
But now I have to create server that receives messages like these.
I found many resources, all suggesting this code:
$classmap = array('<class_name2>'=>'<class_name2>');
$server = new SoapServer('<path to wdsl file>',array('classmap'=>$classmap));
$server->setClass("<class_name>");
$server->handle();
Code itself works, but what I can't understand is - how certificates work within this client-server communication.
As I understand, for secure communication two pairs of private key and certificate are required. One for each of parties.
There is way to add .pem file with one private key and certificate pair for SoapClient.
Incoming messages (at the both sides) comes unencrypted.
.
Mustn't there be a way to pass certificate and key pair for SoapServer?
How exactly verification of certificates are performed (at what point and what is checked)?
How I can filter out messages only from the user I'm interested in, provided, I can get his certificate?
Sorry for such childish questions, but can You point me out, where I am wrong and provide appropriate resources to find information about this?
Thanks.