Protecting Payment Buttons by Using Encrypted Website Payments

Securing PayPal Checkout
Manish Ranjan 7/15/2010

...................... 3 5........ 4 Securing PayPal Checkout button Page 1 of 15 .............. 2 2.............................................. Downloading the PayPal Public Certificate From the PayPal Website................................................................ 2 3................................................................Table of contents 1.......... 2 4.............................................................................. Uploading Your Public Certificate to Your PayPal Account ... Generating Your Public Certificate Using OpenSSL ......... Implement PayPal Secure button in a project................................................ Generating Your Private Key Using OpenSSL ...............

2. Click the Browse button.pem 3. Click the Add button. Scroll down the page to the Your Public Certificates section. click the Encrypted Payment Settings link. Generating Your Private Key Using OpenSSL Using the openssl program. and select the public certificate that you want to upload to PayPal from your local computer. The Website Payment Certificates page appears. After your public certificate is uploaded successfully. it appears in the Your Public Certificates section of the Website Payment Certificates page. 6. and click the Add button. The Add Certificate page appears. Click the Profilesubtab. To generate your certificate. Securing PayPal Checkout button Page 2 of 15 . which generates a public certificate in the file my-pubcert. 4. The command generates a 1024-bit RSA private key that is stored in the file my-prvkey.pem: opensslreq -new -key my-prvkey. Log in to your PayPal Business or Premier account.pem: opensslgenrsa -out my-prvkey. Uploading Your Public Certificate to Your PayPal Account To upload your public certificate to your PayPal account: 1. 5. enter the following opensslcommand. 3.pem -x509 -days 365 -out my-pubcert. Generating Your Public Certificate Using OpenSSL The public certificate must be in PEM format. Note: The file you upload must be in PEM format. enter the following command to generate your private key.1. In the Selling Preferences column.pem 1024 2.

5. Click the Download button. Scroll down the page to the PayPal Public Certificate section. 3. 4. 2. Log in to your Business or Premier PayPal account. In the Seller Preferences column. and save the file in a secure location on your local computer. click the Encrypted Payment Settings link. Securing PayPal Checkout button Page 3 of 15 . Downloading the PayPal Public Certificate From the PayPal Website To download the PayPal public certificate: 1. You need the certificate ID that PayPal assigned to encrypt your payment buttons by using the Encrypted Website Payments software provided by PayPal. Store the certificate ID that PayPal assigned to your public certificate in a secure place. Click the Profilesubtab.7. 4.

pem". "discount_amount" => $discountAmt. "cancel_return" => HTTP_PATH. Make sure it's writable **/ $paypal->setTempDirectory("/tmp"). "on0" => "Transaction ID#".class. } /** set standard PayPal variables in an array **/ $fields = array("cmd" => "_xclick". "notify_url" => HTTP_PATH. "no_shipping" => "1". "on1" => "User ID#".00'. /** This will contain the encrypted button text **/ $encryptedButton = "". "return" => HTTP_PATH.php". "os0" => $yourorderid. "business" => $paypal_account. "bn" => "PP-BuyNowBF" ).class. /** For a list of thrown exceptions. "currency_code" => "USD". /** The user certificate and private key you generated **/ $paypal->setUserCertificate("site-public. /** The ID of the certificate PayPal gave you **/ $paypal->setPaypalCertificateID("P75YBBV2DJQJS"). "site. "no_note" => "1". "amount" => $totalcost.pem").php").pem"). /** Generate the encrypted button **/ $encryptedButton = $paypal->encryptButton($fields).5.php **/ try { if(!isset($discountAmt)){ $discountAmt='0. "os1" => $loggedinuserid. refer to the bottom of PayPalEWP. /** Create a new instance of the class **/ $paypal = new PayPalEWP(). /** The certificate PayPal gave you **/ $paypal->setPaypalCertificate("paypal_cert. /** Temporary directory for file storage."/ComfirmPayment. "item_name" => $item_name."/Notify."/Cancel.php". Implement PayPal Secure button in a project require_once( .php"./PayPalEWP. Securing PayPal Checkout button Page 4 of 15 .

private $paypalCertificateFile. user private key. ?>-----END PKCS7-----"> </form> PayPalEWP. * * @author Joshua Gilman * @version 1.php <?php /** * Class for creating Paypal Encrypted Website Payment buttons * * Uses given user certificate. PayPal * certificate. private $userKeyFile. private $paypalCertificateID. private $userKey.0.gif" border="0" name="submit"> <input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----<?php echo $encryptedButton. private $userCertificateFile. private $tempDirectory. * * @param Array $fields Securing PayPal Checkout button Page 5 of 15 .class.com/cgi-bin/webscr" method="POST"><input type="hidden" name="cmd" value="_s-xclick"> <input type="image" src="/Images/btn_xpressCheckout.paypal. /** * Takes the given form fields and encrypts * them according to the PayPal EWP standard * returning the encrypted button code.?> <form name="_xclick" id="_xclick" action="https://www.0 * @package PayPalLib * */ classPayPalEWP { private $userCertificate. private $paypalCertificate. and PayPal certificate ID to create form * content from the given array and then encrypt using * the above details according to the PayPal EWP standard.

'wb'). } /** Create a temporary file to begin storing our data as we process it **/ $dataFile = tempnam($this->tempDirectory. /** Create the form data by separating each value set by a new line character **/ foreach($fields as $key => $value) { $plainText . fclose($fh). $plainText). "w+"). /** Open a handle for outputting the signed data **/ $fh = fopen($dataFile . } /** Make sure we have a PayPal certificate **/ if ($this->paypalCertificate == NULL) { throw new emptyFieldException("paypalCertificate"). $signedText = array(). } /** Define variables to be used later **/ $plainText = "". /** Start off the form data with the PayPal certificate ID **/ $plainText . "data"). $this->paypalCertificateID. /** First create a file for storing the plain text value of the form data **/ $fh = fopen($dataFile .txt".= "cert_id=" . "_plain. fwrite($fh.* @return String */ public function encryptButton($fields) { /** Make sure we have a user certificate **/ if ($this->userCertificate == NULL) { throw new emptyFieldException("userCertificate"). } /** Make sure we have a PayPal certificate ID **/ if ($this->paypalCertificateID == NULL) { throw new emptyFieldException("paypalCertificateID").txt". "_signed. /** Sign the plain text file using the given user certificate and user key **/ Securing PayPal Checkout button Page 6 of 15 . $encText = "".= "\n{$key}={$value}".

PKCS7_BINARY)) { throw new encryptFailedException($dataFile . /** Parse the signed file between the header and content **/ $signedText = explode("\n\n". $dataFile . /** Save only the content but base64 decode it first **/ $fh = fopen($dataFile . 'wb'). @unlink($dataFile .if (!openssl_pkcs7_sign($dataFile . "_enc.txt". $this->userKey.txt")). array(). @unlink($dataFile . $dataFile . "_enc.txt". $this>paypalCertificateFile). "_plain. fwrite($fh. "_signed. "_plain. * * @param String $userCertificateFile * @param String $userKeyFile * @return Boolean */ public function setUserCertificate($userCertificateFile.txt").txt".txt".txt")). file_get_contents($dataFile . @unlink($dataFile . $this->userCertificateFile. } /** * Sets the user certificate to be used with encryption.txt".txt". $encText = $encryptedData[1]. "_signed. "_signed. "_enc. file_get_contents($dataFile .txt"). /** Now encrypt the signed file we just wrote to using the PayPal certificate **/ if (!openssl_pkcs7_encrypt($dataFile . } /** Close our previously opened handle **/ fclose($fh). base64_decode($signedText[1])). $this>userCertificate. "_signed. /** Delete all of our temporary files **/ @unlink($dataFile). "_plain. /** Return the now encrypted form content **/ return $encText. $this->userKeyFile).txt". fclose($fh). "_signed. $userKeyFile) Securing PayPal Checkout button Page 7 of 15 . } /** Parse the encrypted file between header and content and grab the content **/ $encryptedData = explode("\n\n". "_signed. array().txt"). PKCS7_BINARY)) { throw new signFailedException($dataFile . $this>paypalCertificate.

} /** Make sure this key and certificate belong together **/ if (!openssl_x509_check_private_key($cert. $key = openssl_get_privatekey(file_get_contents($this->userKeyFile)). $this->userKeyFile = $userKeyFile. /** Load the resource handles for both the user certificate and key **/ $cert = openssl_x509_read(file_get_contents($this->userCertificateFile)). Securing PayPal Checkout button Page 8 of 15 . } /** Make sure the key is valid **/ if ($key === FALSE) { throw new invalKeyException($this->userKeyFile). $this->userKey = $key. } /** Make sure the user key file is valid **/ if (!is_readable($userKeyFile)) { throw new invalKeyException($userKeyFile). } /** Set the appropriate values **/ $this->userCertificateFile = $userCertificateFile. $key)) { throw new invalCertKey($this->userCertificateFile. } /** Assign the appropriate values **/ $this->userCertificate = $cert. } /** * Sets the PayPal certificate to be used with encryption. $this->userKeyFile). /** Make sure the certificate is valid **/ if ($cert === FALSE) { throw new invalUserCertException($this->userCertificateFile).{ /** Make sure the user certificate file is valid **/ if (!is_readable($userCertificateFile)) { throw new invalUserCertException($userCertificateFile). return TRUE.

} /** * Sets the temporary directory the encryption process will use. } /** Assign the appropriate values **/ $this->paypalCertificate = $cert. /** Make sure the certificate is valid **/ if ($cert === FALSE) { throw new invalPaypalCertException($this->paypalCertificateFile). } /** Set the proper values **/ $this->paypalCertificateFile = $paypalCertificateFile. /** Grab the resource of the PayPal certificate **/ $cert = openssl_x509_read(file_get_contents($this->paypalCertificateFile)). } /** * Sets the PayPal certificate ID to be used with encryption. * * @param String $tempDirectory * @return Boolean */ public function setTempDirectory($tempDirectory) { Securing PayPal Checkout button Page 9 of 15 . return TRUE. * * @param String $paypalCertificateID */ public function setPaypalCertificateID($paypalCertificateID) { $this->paypalCertificateID = $paypalCertificateID.* * @param String $paypalCertificateFile * @return Boolean */ public function setPaypalCertificate($paypalCertificateFile) { /** Make sure the certificate file is valid **/ if (!is_readable($paypalCertificateFile)) { throw new invalPaypalCertException($paypalCertificateFile).

} public function getCertFile() { return $this->certFile. } } /** Below are defined exceptions used by the PayPalEWP class **/ /** * Thrown when an invalid user certificate is used./** Make sure the temporary directory is valid **/ if (!is_dir($tempDirectory) || !is_writable($tempDirectory)) { throw new invalTempDirectory($tempDirectory). } } /** * Thrown when an invalid PayPal certificate is given * */ classinvalPaypalCertException extends Exception { private $paypalCertFile. Securing PayPal Checkout button Page 10 of 15 . } public function __toString() { return "Invalid User Certificate File: \"{$this->certFile}\"". return TRUE. public function __construct($certFile) { $this->certFile = $certFile. } /** Assign the appropriate values **/ $this->tempDirectory = $tempDirectory. * */ classinvalUserCertException extends Exception { private $certFile.

} } /** * Thrown when an invalid user certificate is given * */ classinvalCertKey extends Exception { private $certFile. public function __construct($keyFile) { $this->keyFile = $keyFile. } public function __toString() { return "Invalid User Key File: \"{$this->keyFile}\"". } public function getKeyFile() { return $this->keyFile. } } /** * Thrown when an invalid user key is given * */ classinvalKeyException extends Exception { private $keyFile.public function __construct($paypalCertFile) { $this->paypalCertFile = $paypalCertFile. } public function __toString() { return "Invalid PayPal Certificate File: \"{$this->paypalCertFile}\"". Securing PayPal Checkout button Page 11 of 15 . private $keyFile. } public function getPaypalCertFile() { return $this->paypalCertFile.

} public function getTmpDir() { return $this->tmpDir. $keyFile) { $this->certFile = $certFile. } public function getCertFile() { return $this->certFile. $this->keyFile = $keyFile. } } Securing PayPal Checkout button Page 12 of 15 .public function __construct($certFile. } } /** * Thrown when an invalid temporary directory is given * */ classinvalTempDirectory extends Exception { private $tmpDir. } public function __toString() { return "Invalid temporary directory: \"{$this->tmpDir}\"". } public function __toString() { return "Key file: \"{$this->keyFile}\" does not belong to Certificate file: \"{$this>certFile}\"". } public function getKeyFile() { return $this->keyFile. public function __construct($tmpDir) { $this->tmpDir = $tmpDir.

} public function getContentFile() { return $this->contentFile. } public function getField() { return $this->field. private $keyFile./** * Thrown when one of the required fields used in PayPalEWP:EncryptButton is NULL * */ classemptyFieldException extends Exception { private $field. $this->keyFile = $keyFile. } } /** * Thrown when the signing of a file using a user certificate and user key failed * */ classsignFailedException extends Exception { private $contentFile. $certFile. $this->certFile = $certFile. } public function getCertFile() { Securing PayPal Checkout button Page 13 of 15 . } public function __toString() { return "The required field '{$this->field}' is empty". $keyFile) { $this->contentFile = $contentFile. public function __construct($contentFile. private $certFile. public function __construct($field) { $this->field = $field.

} public function getKeyFile() { return $this->keyFile. } public function getContentFile() { return $this->contentFile. $this->certFile = $certFile. } public function getCertFile() { return $this->certFile. } } /** * Thrown when the encryption of a file using a certificate fails * */ classencryptFailedException extends Exception { private $contentFile. } } ?> Securing PayPal Checkout button Page 14 of 15 . public function __construct($contentFile. } public function __toString() { return "Failed to encrypt file '{$this->contentFile}' with certificate file '{$this>certFile}'".return $this->certFile. } public function __toString() { return "Failed to sign file '{$this->contentFile}' with user certificate '{$this->certFile}' and user key '{$this->keyFile}'". $certFile) { $this->contentFile = $contentFile. private $certFile.