<?php
require_once("english_encrypt.php");
define ( "TA_SUCCESS", 0 );
define ( "PUBLIC_KEY_ERROR", -1 );
define ( "PRIVATE_KEY_ERROR", -2 );
define ( "ENCRYPTION_ERROR", -3 );
define ( "DECRYPTION_ERROR", -4 );
/**
* class TA_OpenSSL
*
* Encrypts and Decrypts data using the OpenSSL extension
*
* I included a function that verifies the encryption by
* decrypting the data and comparing against the original
* string. I feel this is necessary to ensure retrieval
* of sensitive data. This class allows for private keys that
* have passphrases and those that do not. I recommend ALWAYS
* creating a private key that uses a passphrase. But it's up
* to you. I used the example code from the php manual to create
* this class. I have included the code in the readme.txt if anyone
* is interested. If you did not receive a copy of the readme.txt email
* me at hide@address.com and I will send one to you.
* I also have a derived class that is able to encrypt large data
* sources. I haven't fully tested it yet so I didn't release it here.
* If anyone is interested in obtaining a copy email me at
* hide@address.com and I will email you a copy.
*
* Note:
* I've also made it compatible with localization. The english version
* is in file english_encrypt.php. To use other languages just save the
* english_encrypt.php file as [language]_encrypt.php. Translate the defines
* to the language of choice and change the require_once at the top of this page.
* If you do we would appreciate it if you emailed us a copy of the new translation.
* Thanks <hide@address.com>
*
* Requires: OpenSSL Extension Installed and working
* PHP 4.1 or higher ( Tested on 4.3.1, 4.1.2, 4.3.3 )
* Localization File: english_encrypt.php or translated file
* RSA Certificate and Key File
*
* Creating a Private Key:
* openssl genrsa -des3 -out privkey.pem 2048
* Note: this was taken straight from http://www.openssl.org/docs/HOWTO/keys.txt
* to create a key file without a passphrase remove the -des3 param
* Key Size: In the above example the key size is 2048 bits. The size of your data
* to encrypt is limited by this number. You can only encrypt data of the
* length:
* bytes - 11
* 2048 bits / 8 bits per byte = 256 bytes
* 256 - 11 = 245 byte Maximum size of data to encrypt
* If you are going to encrypt larger chunks of data
* ust split up the data and encrypt. I will work on that:)
*
* Creating a Certificate:
* openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095
* Note: this was taken straight from http://www.openssl.org/docs/HOWTO/certificates.txt
*
* @author Rick Robinson <hide@address.com>
* @link http://www.terraaccess.com Terra Access
* @link http://dev.terraaccess.com TA Development Center
* @link http://www.openssl.org/docs/HOWTO/keys.txt Create Key HOWTO
* @link http://www.openssl.org/docs/HOWTO/certificates.txt Create Certificat HOWTO
*
* @package TA_Admin
* @version 0.1
* @copyright Copyright 2003-2005 Terra Access
*
* @link http://www.php.net PHP
* @access public
*/
class TA_OpenSSL
{
/**
* TA_OpenSSL::$public_key_path
*
* Full Path with filename to
* the public key file
*
* @access public
*/
var $public_key_path = "";
/**
* TA_OpenSSL::$private_key_path
*
* Full Path with filename to
* the private key file
*
* @access public
*/
var $private_key_path = "";
/**
* TA_OpenSSL::$passphrase
*
* Passphrase for private key if required
* ensure this is set to "" if you don't
* use a passphrase for your private key
*
* @access public
*/
var $passphrase = "";
/**
* TA_OpenSSL::$string_to_encrypt
*
* Holds the string to encrypt for
* verification and processing
*
* @access public
*/
var $string_to_encrypt = "";
/**
* TA_OpenSSL::$encrypted_data
*
* Holds the encrypted data for retrieval
* and testing
*
* @access public
*/
var $encrypted_data = "";
/**
* TA_OpenSSL::$decrypted_data
*
* Holds decrypted data for retrieval
*
* @access public
*/
var $decrypted_data = "";
/**
* TA_OpenSSL::$errno
*
* Set to the last error number
* encountered
*
* @access public
*/
var $errno = "";
/**
* TA_OpenSSL::$error
*
* Set to the text for the last
* error encountered
*
* @access public
*/
var $error = "";
/**
* TA_OpenSSL::set_public_key()
*
* Sets the path to the public key file
*
* @param string $public_key_path_in Path to Public Key
* @return none
* @access public
*/
function set_public_key( $public_key_path_in )
{
$this->public_key_path = $public_key_path_in;
}
/**
* TA_OpenSSL::set_private_key()
*
* Sets the path to the private key file
*
* @param string $private_key_path_in Path to Private Key
* @return none
* @access public
*/
function set_private_key( $private_key_path_in )
{
$this->private_key_path = $private_key_path_in;
}
/**
* TA_OpenSSL::set_passphrase()
*
* Sets the passphrase for the private key
* ensure this is "" if passphrase not used
*
* @param string $passphrase_in Private Key Passphrase
* @return none
* @access public
*/
function set_passphrase( $passphrase_in )
{
$this->passphrase = $passphrase_in;
}
/**
* TA_OpenSSL::encrypt_data_public()
*
* Uses the public key to encrypt data
* This can't be decrypted without the private key
*
* @param string $data_to_encrypt String to Encrypt
* @return string Encrypted data or error if failed
* @access public
*/
function encrypt_data_public( $data_to_encrypt )
{
$this->clear_error();
//set the class variable to data passed in
$this->string_to_encrypt = $data_to_encrypt;
//check to see if th public key path is valid
if (! file_exists($this->public_key_path))
{
$this->set_error ( PUBLIC_KEY_ERROR, loc_encrypt_invalid_public_key_path );
return PUBLIC_KEY_ERROR;
}
//open and read the public key
$fp = fopen ( $this->public_key_path, "r" );
$public_key_tmp = fread ( $fp, 8192 );
fclose( $fp );
//generate a public key resource
$public_key = openssl_get_publickey($public_key_tmp);
//if getting private key failed then kick out error
if (!$public_key)
{
$this->set_error(PUBLIC_KEY_ERROR, loc_encrypt_openssl_get_public_error);
openssl_free_key( $public_key );
return PUBLIC_KEY_ERROR;
}
//encrypt the data
openssl_public_encrypt( $this->string_to_encrypt, $encrypted_data_tmp, $public_key );
//check to make sure data is returned and decryption succeeds
if( empty( $encrypted_data_tmp))
{
$this->set_error( ENCRYPTION_ERROR, loc_encrypt_empty_return );
openssl_free_key( $public_key );
return ENCRYPTION_ERROR;
}
//verify able to properly decrypt data
$ret = $this->verify_encryption( $encrypted_data_tmp );
if( $ret != TA_SUCCESS )
{
//$this->set_error( $ret, loc_encrypt_verification_failed );
openssl_free_key($public_key);
return $ret;
}
$this->encrypted_data = $encrypted_data_tmp;
openssl_free_key($public_key);
return TA_SUCCESS;
}
/**
* TA_OpenSSL::decrypt_data_private()
*
* Decrypts data using the private key
*
* @param string $encrypted_data Data to Decrypt
* @return string $decrypted Plain Text Decryption
* @access public
*/
function decrypt_data_private( $encrypted_data )
{
$this->clear_error();
//check to see if th private key path is valid
if(! file_exists($this->private_key_path))
{
$this->set_error ( PRIVATE_KEY_ERROR, loc_encrypt_invalid_private_key_path );
return PRIVATE_KEY_ERROR;
}
$fp=fopen ($this->private_key_path,"r");
$private_key_tmp = fread( $fp, 8192 );
fclose($fp);
//check for passphrase and decrypt appropriately
//I don't know if passing an empty string is the
//same as not setting the variable. I need to test this still
if( $this->passphrase == "" )
{
$private_key = openssl_get_privatekey( $private_key_tmp );
}else{
$private_key = openssl_get_privatekey( $private_key_tmp, $this->passphrase );
}
//if getting private key failed then kick out error
if (!$private_key)
{
$this->set_error(PRIVATE_KEY_ERROR, loc_encrypt_openssl_get_private_error);
return PRIVATE_KEY_ERROR;
}
$ret = openssl_private_decrypt( $encrypted_data, $decrypted, $private_key );
//test to ensure data was decrypted
if (!$ret)
{
$this->set_error( DECRYPTION_ERROR, loc_encrypt_decryption_private_error );
openssl_free_key($private_key);
return DECRYPTION_ERROR;
}
$this->decrypted_data = $decrypted;
openssl_free_key($private_key);
return TA_SUCCESS;
}
/**
* TA_OpenSSL::verify_encryption()
*
* Verifies Encrypted data by decrypting and
* comparing against the original data
*
* @param string $encrypted_data Encryption to Verify
* @return TA_SUCCESS or DECRYPTION_ERROR
* @access public
*/
function verify_encryption ( $encrypted_data )
{
$ret = $this->decrypt_data_private($encrypted_data);
if( $ret != TA_SUCCESS )
{
return $ret;
}
if ( $this->decrypted_data == $this->string_to_encrypt )
{
return TA_SUCCESS;
}else{
return DECRYPTION_ERROR;
}
}
/**
* TA_OpenSSL::get_encrypted_data()
*
* Returns the last encrypted data
*
* @return string Encrypted Data
*
* @access public
*/
function get_encrypted_data()
{
return $this->encrypted_data;
}
/**
* TA_OpenSSL::get_decrypted_data()
*
* Returns the last decrypted data
*
* @return string Decrypted Data
*
* @access public
*/
function get_decrypted_data()
{
return $this->decrypted_data;
}
/**
* TA_OpenSSL::set_error()
*
* Sets the error number and error string values
* to the specified error
*
* @param integer $err_number Error Number
* @param string $error_string Error String
* @return none
* @access public
*/
function set_error( $err_number, $error_string )
{
$this->errno = $err_number;
$this->error = $error_string;
}
/**
* TA_OpenSSL::get_error_number()
*
* Returns the last error number set
*
* @return integer Error Number
* @access public
*/
function get_error_number()
{
return $this->errno;
}
/**
* TA_OpenSSL::kick_openssl_errors()
*
* Kicks out the errors stored in the
* openssl error handler. Only place
* I use html in this module.
*
* @return
*/
function kick_openssl_errors()
{
while($msg = openssl_error_string())
{
echo $msg . "<br />\n";
}
}
/**
* TA_OpenSSL::get_error_string()
*
* Returns the last error string set
*
* @return string Error String
* @access public
*/
function get_error_string()
{
return $this->error;
}
/**
* TA_OpenSSL::clear_error()
*
* Clears the last error set
*
* @return none
* @access public
*/
function clear_error()
{
$this->error = "";
$this->errno = "";
}
}
?>