Rev 10 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php
/**
* Openssl encrypt/decrypt functions
*
* Available under the MIT License
*
* The MIT License (MIT)
* Copyright (c) 2016 ionCube Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
* OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
* OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
class Cryptor {
private static $instance = null;
private static $cipher_algo;
private static $hash_algo;
private static $keystring;
private static $iv_num_bytes;
private static $format;
private static $hasOpenSSL = true;
const FORMAT_RAW = 0;
const FORMAT_B64 = 1;
const FORMAT_HEX = 2;
/**
* Create a Cryptor singleton instance
* @param array $cryptConfig The cipher algorithm, the hash algorithm and the key.
* @param [type] $fmt Optional override for the output encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX. Default: FORMAT_B64.
*/
public static function getInstance($cryptorConfig = null, $fmt = Cryptor::FORMAT_B64) {
if (is_null(self::$instance)) {
self::$instance = new self();
if (!extension_loaded("openssl")) {
self::$hasOpenSSL = false;
return self::$instance;
}
}
else {
return self::$instance;
}
// store cryptor configuration
if (!is_null($cryptorConfig)) {
if (isset($cryptorConfig['cipherAlgorithm']) && !empty($cryptorConfig['cipherAlgorithm'])) {
self::$cipher_algo = $cryptorConfig['cipherAlgorithm'];
}
else {
self::$cipher_algo = 'aes-256-cbc';
}
if (isset($cryptorConfig['hashAlgorithm']) && !empty($cryptorConfig['hashAlgorithm'])) {
self::$hash_algo = $cryptorConfig['hashAlgorithm'];
}
else {
self::$hash_algo = 'sha256';
}
if (isset($cryptorConfig['key']) && !empty($cryptorConfig['key'])) {
self::$keystring = $cryptorConfig['key'];
}
else {
throw new \Exception("Cryptor:: - key not set in configuration");
}
if ($fmt === Cryptor::FORMAT_RAW || $fmt === Cryptor::FORMAT_B64 || $fmt == Cryptor::FORMAT_HEX) {
self::$format = $fmt;
}
else {
self::$format = Cryptor::FORMAT_B64;
}
}
if (!in_array(self::$cipher_algo, openssl_get_cipher_methods(true))) {
throw new \Exception("Cryptor:: - unknown cipher algo {" . self::$cipher_algo . "}");
}
if (!in_array(self::$hash_algo, openssl_get_md_methods(true))) {
throw new \Exception("Cryptor:: - unknown hash algo {" . self::$hash_algo . "}");
}
self::$iv_num_bytes = openssl_cipher_iv_length(self::$cipher_algo);
return self::$instance;
}
/**
* Encrypt a string.
* @param string $in String to encrypt.
* @param string $key Optional encryption key.
* @param int $fmt Optional override for the output encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX.
* @return string The encrypted string.
*/
public static function encryptString($in, $key = null, $fmt = null) {
if (!self::$hasOpenSSL) {
return base64_encode($in);
}
if ($fmt === null) {
$fmt = self::$format;
}
if ($key === null) {
$key = self::$keystring;
}
// Build an initialization vector
$iv = openssl_random_pseudo_bytes(self::$iv_num_bytes, $isStrongCrypto);
if (!$isStrongCrypto) {
throw new \Exception("Cryptor::encryptString() - Not a strong key");
}
// Hash the key
$keyhash = openssl_digest($key, self::$hash_algo, true);
// and encrypt
$opts = OPENSSL_RAW_DATA;
$encrypted = openssl_encrypt($in, self::$cipher_algo, $keyhash, $opts, $iv);
if ($encrypted === false) {
throw new \Exception('Cryptor::encryptString() - Encryption failed: ' . openssl_error_string());
}
// The result comprises the IV and encrypted data
$res = $iv . $encrypted;
// and format the result if required.
if ($fmt == Cryptor::FORMAT_B64) {
$res = base64_encode($res);
}
else if ($fmt == Cryptor::FORMAT_HEX) {
$res = unpack('H*', $res) [1];
}
return $res;
}
/**
* Decrypt a string.
* @param string $in String to decrypt.
* @param string $key Optional decryption key.
* @param int $fmt Optional override for the input encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX.
* @return string The decrypted string.
*/
public static function decryptString($in, $key = null, $fmt = null) {
if (!self::$hasOpenSSL) {
return base64_decode($in);
}
if ($fmt === null) {
$fmt = self::$format;
}
if ($key === null) {
$key = self::$keystring;
}
$raw = $in;
// Restore the encrypted data if encoded
if ($fmt == Cryptor::FORMAT_B64) {
$raw = base64_decode($in);
}
else if ($fmt == Cryptor::FORMAT_HEX) {
$raw = pack('H*', $in);
}
// and do an integrity check on the size.
if (strlen($raw) < self::$iv_num_bytes) {
throw new \Exception('Cryptor::decryptString() - ' . 'data length ' . strlen($raw) . " is less than iv length {self::$iv_num_bytes}");
}
// Extract the initialization vector and encrypted data
$iv = substr($raw, 0, self::$iv_num_bytes);
$raw = substr($raw, self::$iv_num_bytes);
// Hash the key
$keyhash = openssl_digest($key, self::$hash_algo, true);
// and decrypt.
$opts = OPENSSL_RAW_DATA;
$res = openssl_decrypt($raw, self::$cipher_algo, $keyhash, $opts, $iv);
if ($res === false) {
throw new \Exception('Cryptor::decryptString - decryption failed: ' . openssl_error_string());
}
return $res;
}
/**
* Static convenience method for encrypting.
* @param string $in String to encrypt.
* @param string $key Optional encryption key.
* @param int $fmt Optional override for the output encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX.
* @return string The encrypted string.
*/
public static function Encrypt($in, $key = null, $fmt = null) {
return self::encryptString($in, $key, $fmt);
}
/**
* Static convenience method for decrypting.
* @param string $in String to decrypt.
* @param string $key Optinal eecryption key.
* @param int $fmt Optional override for the input encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX.
* @return string The decrypted string.
*/
public static function Decrypt($in, $key = null, $fmt = null) {
return self::decryptString($in, $key, $fmt);
}
}