Current File : /home/pacjaorg/public_html/copp/copp/wp-content/plugins/backwpup/inc/class-encryption.php |
<?php
/**
* Encrypt / decrypt data using the best algorithm available.
*
* This should be converted to a real object (instead of a all-static, "poor man namespace" class) and a algorithm
* factory should be injected, to be used to create an instance of an algorithm instance.
* However, at the moment with PHP 5.2 and the "poor" autoloader we have, an interface would just be another file in
* "/inc" folder causing confusion. Also, I don't want to create an interface in a file named `class-...php`.
* When we get rid of PHP 5.2, we setup a better autoloader and we get rid of WP coding standard, we finally should
* refactor to proper code.
*/
class BackWPup_Encryption
{
public const PREFIX = '$BackWPup$';
public const KEY_TYPE_CUSTOM = '$0';
private static $classes = [
BackWPup_Encryption_OpenSSL::PREFIX => \BackWPup_Encryption_OpenSSL::class,
BackWPup_Encryption_Mcrypt::PREFIX => \BackWPup_Encryption_Mcrypt::class,
BackWPup_Encryption_Fallback::PREFIX => \BackWPup_Encryption_Fallback::class,
];
/**
* Encrypt a string using the best algorithm available.
*
* In case the given string is encrypted with a weaker algorithm, it will first be decrypted then the plain text
* obtained is encrypted with the better algorithm available and returned.
*
* @param string $string value to encrypt
*
* @return string encrypted string
*/
public static function encrypt($string)
{
if (!is_string($string) || !$string) {
return '';
}
try {
$cypher_class = self::cypher_class_for_string($string);
} catch (Exception $e) {
/** @TODO what to do here? The string is encrypted, but cypher used to encrypt isn't supported in current system */
return $string;
}
try {
[$key, $key_type] = self::get_encrypt_info($cypher_class, $string);
} catch (Exception $e) {
/** @TODO what to do here? The string is encrypted, a custom key was used to encrypt, but it is not available anymore */
return $string;
}
$best_cipher_class = self::best_cypher();
// The given string is not encrypted, let's encrypt it and return
if (!$cypher_class) {
/** @var BackWPup_Encryption_OpenSSL|BackWPup_Encryption_Mcrypt|BackWPup_Encryption_Fallback $best_cypher */
$best_cypher = new $best_cipher_class($key, $key_type);
return $best_cypher->encrypt($string);
}
$encryption_count = substr_count($string, self::PREFIX);
// The given string is encrypted once using best cypher, let's just return it
if ($encryption_count === 1 && $cypher_class === $best_cipher_class) {
return $string;
}
/** @var BackWPup_Encryption_OpenSSL|BackWPup_Encryption_Mcrypt|BackWPup_Encryption_Fallback $cypher */
$cypher = new $cypher_class($key, $key_type);
$string = $cypher->decrypt($string);
return self::encrypt($string);
}
/**
* Decrypt a string (Passwords).
*
* @param string $string value to decrypt
*
* @return string decrypted string
*/
public static function decrypt($string)
{
if (!is_string($string) || !$string) {
return '';
}
try {
$cypher_class = self::cypher_class_for_string($string);
} catch (Exception $e) {
/** @TODO what to do here? The cypher used to encrypt is not supported in current system */
return '';
}
if (!$cypher_class) {
/** @TODO what to do here? The string seems not encrypted or maybe is corrupted */
return $string;
}
try {
[$key, $key_type] = self::get_encrypt_info($cypher_class, $string);
} catch (Exception $e) {
/** @TODO what to do here? A custom key was used to encrypt but it is not available anymore */
return '';
}
/** @var BackWPup_Encryption_OpenSSL|BackWPup_Encryption_Mcrypt|BackWPup_Encryption_Fallback $cypher */
$cypher = new $cypher_class($key, $key_type);
return trim(stripslashes($cypher->decrypt($string)), "\0");
}
/**
* @param string $string
*
* @throws Exception
*
* @return string
*/
private static function cypher_class_for_string($string)
{
foreach (self::$classes as $prefix => $class) {
$enc_prefix = self::PREFIX . $prefix;
if (strpos($string, $enc_prefix) !== 0) {
continue;
}
if (!call_user_func([$class, 'supported'])) {
throw new Exception(
"Give string was encrypted using {$class} but it is not currently supported in this system."
);
}
return $class;
}
return '';
}
/**
* @return string
*/
private static function best_cypher()
{
foreach (self::$classes as $prefix => $class) {
if (!call_user_func([$class, 'supported'])) {
continue;
}
return $class;
}
// This should never happen because BackWPup_Encryption_Fallback::supported() always returns true
return '';
}
/**
* @param string|null $class
* @param string $string
*
* @throws Exception
*
* @return array
*/
private static function get_encrypt_info($class = null, $string = '')
{
$default_key = DB_NAME . DB_USER . DB_PASSWORD;
if (!is_string($class) || !$class) {
return defined('BACKWPUP_ENC_KEY')
? [BACKWPUP_ENC_KEY, self::KEY_TYPE_CUSTOM]
: [$default_key, ''];
}
$enc_prefix = self::PREFIX . constant("{$class}::PREFIX");
$has_custom_key = strpos($string, $enc_prefix . self::KEY_TYPE_CUSTOM) === 0;
if ($has_custom_key) {
if (!defined('BACKWPUP_ENC_KEY')) {
throw new Exception(
"Given string was encrypted using a custom key but 'BACKWPUP_ENC_KEY' constant is not defined anymore."
);
}
return [BACKWPUP_ENC_KEY, self::KEY_TYPE_CUSTOM];
}
return [$default_key, ''];
}
}