Main Page
 The gatekeeper of reality is
 quantified imagination.

Stay notified when site changes by adding your email address:

Your Email:

Bookmark and Share
Email Notification
Project PCI Compliance & TLS 1.2
Purpose
The purpose of this project is to show how to test the web environment to determine if backend systems (primarily those interacting with remote API systems such as Authorize.Net) are capable of using TLS 1.2. PCI compliance requires (by June 2018) that systems use TLS 1.2. Luckily, API testing is simple with Authorize.Net's sandbox environment; Authorize.Net is moving to TLS 1.2 for their production API in September 2017. What has been done with this page is to show the testing process (all in Php) as you may already have parts in-hand and may only need some reference. You can download the entire testing project here.

<?php
/*
This is a check to see if TLS 1.2 is operable on the web server. If it is then the next step is to see if curl is able to connect to
Authorize.net using TLS 1.2 in their test environment as, according to documentation, they have disabled all protocols with the exception
of TLS 1.2 that will be going live on SEPTEMBER 2017 (meaning prior versions will be disabled). In broader scope for PCI and a website in
general, TLS 1.1 is to be used no later than June 2016 and by June 30, 2018 TLS 1.2 must be used.
Reference: https://community.developer.authorize.net/t5/The-Authorize-Net-Developer-Blog/Request-for-Comments-API-Best-Practices/ba-p/53668


Step 1 of the test is to see if you are using the following (or later versions):
OpenSSL 1.0.1
cURL 7.34.0 (7.38 preferred as it will have newer ciphers, SSL/TLS beyond what 7.34 has)
PHP 5.6


STEP 2 of the text is to submit a request to "howsmyssl.com" to see what a 3rd party detects. You may or may not want to complete this step
if you have other means at your disposal.


STEP 3 of the test is to submit a test transaction to the Authorize.net server using TLS 1.2. You will need to customize the connection information
for your account.


ADDITIONAL PCI INFORMATION:
https://blog.pcisecuritystandards.org/migrating-from-ssl-and-early-tls?utm_campaign=Merchant%202nd%20TLS%20Notice%20v2.html&utm_medium=email&utm_source=Eloqua
ADDITIONAL AUTHORIZE.NET INFORMATION:
https://support.authorize.net/authkb/index?page=content&id=A1623&actp=LIST


NOTES:
With the Authorize.Net sandbox requiring TLS 1.2, if you attempt to connect without having TLS 1.2, you should get an error like "Unknown SSL protocol error in connection to apitest.authorize.net:443".
If you need a certificate bundle for some reason (perhaps you have an old bundle that results in getting an error like
"SSL certificate problem, verify that the CA cert is OK" when SSL_VERIFYPEER is on), try downloading a more recent cacert.pem bundle from
https://curl.haxx.se/docs/caextract.html
If you are using a bundle under "old school" php/curl you will need to change the file extension from pem to crt.
Other Php/TLS information:
http://php.net/manual/en/migration56.openssl.php
*/


/* Define step to perform */
$test_perform = 1; /* Set to 1 to test for version information,set to 2 to perform a SSL test against "howsmyssl.com", set to 3 to submit a test transaction to authorize.net */
$ciphers = Array(); /* Do not change */
$cipher_aliases = Array(); /* Do not change */
$digests = Array(); /* Do not change */
$digest_aliases = Array(); /* Do not change */
$response_curlerror = ""; /* Do not change */
$response_curl = ""; /* Do not change */
$result = array(); /* Do not change */


/* (STEP 1) Get version and cipher information */
if ($test_perform === 1) {
if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
$ciphers = openssl_get_cipher_methods();
$ciphers_and_aliases = openssl_get_cipher_methods(true);
$cipher_aliases = array_diff($ciphers_and_aliases, $ciphers);
$digests = openssl_get_md_methods();
$digests_and_aliases = openssl_get_md_methods(true);
$digest_aliases = array_diff($digests_and_aliases, $digests);
}
else {
/* Php version too low to use */
$ciphers[0] = "Php version less than 5.3.0. Upgrade needed to determine ciphers.";
$ciphers_and_aliases[0] = "Php version less than 5.3.0. Upgrade needed to determine aliases.";
$digests[0] = "Php version less than 5.3.0. Upgrade needed to determine digests.";
$digest_aliases[0] = "Php version less than 5.3.0. Upgrade needed to determine aliases.";
}
}


/* (STEP 2) Define "howsmyssl.com" for remote SSL test */
if ($test_perform === 2) {
$ch = curl_init('https://www.howsmyssl.com/a/check');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
curl_close($ch);
$result = json_decode($data);
}


/* (STEP 3) Define the Authorize.Net Merchant Information */
if ($test_perform === 3) {
//$ch = curl_init("https://api2.authorize.net/xml/v1/request.api"); /* Live */
$ch = curl_init("https://apitest.authorize.net/xml/v1/request.api"); /* Test */


$gateway_login = "your-merchant-id"; /* Change this for your test account */
$gateway_key = "your-merchant-key"; /* Change this for your test account */


$payload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
$payload = $payload . "<authenticateTestRequest xmlns=\"AnetApi/xml/v1/schema/AnetApiSchema.xsd\">";
$payload = $payload . "<merchantAuthentication>";
$payload = $payload . "<name>" . $gateway_login . "</name>";
$payload = $payload . "<transactionKey>" . $gateway_key . "</transactionKey>";
$payload = $payload . "</merchantAuthentication>";
$payload = $payload . "</authenticateTestRequest>";


curl_setopt($ch, CURLOPT_HEADER, 0); /* Set to 1 to see HTTP headers, otherwise 0 or XML reading will not work */
curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type: text/xml"));
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_PORT, 443);
//curl_setopt($ch, CURLOPT_SSLVERSION, 6); /* Use TLS 1.2. According to php documentation you should not need to specify this manually; instead let Curl choose. Authorize.net sandbox will require TLS 1.2 until September 2017 - after which point it will also be required on live */
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . "/cacert.crt"); /* Location in same folder as this file */
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);


$response_curl = curl_exec($ch);
if (curl_errno($ch)) {
$response_curlerror = curl_error($ch);
}
curl_close($ch);
}


/* Generate some output */
print "<html><body>\n";
if ($test_perform === 1) {
/* STEP 1 */
/* Get version information */
$verinfo_curl = curl_version();
$verinfo_php = phpversion();
/* Show version details */
print "OpenSSL version (minimum should be 1.0.1): " . $verinfo_curl['ssl_version'] . "<br />";
print "cURL version (minimum should be 7.34.0): " . $verinfo_curl['version'] . "<br />";
print "PHP version (minimum should be 5.6): " . $verinfo_php . "<br />";
print "<hr />Ciphers:<hr />";
print "<pre>";
print_r($ciphers);
print "</pre><br />";
print "<hr />Cipher Aliases:<hr />";
print "<pre>";
print_r($cipher_aliases);
print "</pre><br />";
print "<hr />Digests:<hr />";
print "<pre>";
print_r($digests);
print "</pre><br />";
print "<hr />Digest Aliases:<hr />";
print "<pre>";
print_r($digest_aliases);
print "</pre><br />";
}
else if ($test_perform === 2) {
/* STEP 2 */
print "TLS Version: " . $result['tls_version'] . "<br />";
print "Raw Response:<br />";
print var_dump($result) . "<br />";
}
else if ($test_perform === 3) {
/* STEP 3 */
/* Show results of submitting request using TLS 1.2 */
print "Result of Submission:<br />";
if (strlen($response_curlerror) > 0) { print "Curl ERROR: " . $response_curlerror . "<br />"; }
else { print $response_curl . "<br />"; }
}
else {
/* Something is afoot */
print "Nothing appears to have been setup.";
}
print "</body></html>\n";


?>


About Joe