enc use wipe to fallback to unset if sodium not installed. Fixed size name issues with vars be called bit when their bytes.

main
Robert 3 years ago
parent b8051fba32
commit b95490c165
  1. 70
      src/classes/services/encryption.php

@ -19,14 +19,14 @@ final class encryption {
const iterations = 81952; // should be over 80K. The number of internal iterations to perform for the derivation. const iterations = 81952; // should be over 80K. The number of internal iterations to perform for the derivation.
const length = 64; // The length of the output string. If raw_output is TRUE this corresponds to the byte-length of the derived key, if raw_output is FALSE this corresponds to twice the byte-length of the derived key (as every byte of the key is returned as two hexits). const length = 64; // The length of the output string. If raw_output is TRUE this corresponds to the byte-length of the derived key, if raw_output is FALSE this corresponds to twice the byte-length of the derived key (as every byte of the key is returned as two hexits).
const raw = true; // When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits. const raw = true; // When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits.
const key_bits = 32; // 256 bit encryption key const key_bytes = 32; // 32 bytes = 256 bits, 64 bytes = 512 bits, 16 bytes = 128 bits encryption key
private $random_engine; private $random_engine;
private $binary = false; private $binary = false;
private $url_encode = false; private $url_encode = false;
private $method = 'AES-256-CBC'; private $method = 'AES-256-CBC';
private $default_hash = 'sha256'; // should be sha256 or higher private $default_hash = 'sha256'; // should be sha256 or higher
private $_iterations = self::iterations, $_length=self::length, $_raw=self::raw, $_key_bits=self::key_bits; private $_iterations = self::iterations, $_length=self::length, $_raw=self::raw, $_key_bytes=self::key_bytes;
public function __construct() { public function __construct() {
$this->random_engine = new \tts\random_engine(); $this->random_engine = new \tts\random_engine();
@ -65,38 +65,38 @@ final class encryption {
* like encrypted sessions. Where as, good, normal, * like encrypted sessions. Where as, good, normal,
* and paranoid are for cookies, DB storage, etc... * and paranoid are for cookies, DB storage, etc...
*/ */
case 'lighting': // 0.0001 Seconds case 'lighting': // 0.0006 Seconds
$this->set_loops(3); // Very very fast $this->set_loops(98); // Very very fast
$this->set_length(64); $this->set_length(64);
$this->set_key_bits(16); $this->set_key_bytes(16);
$this->method = 'AES-128-CBC'; $this->method = 'AES-128-CBC';
$this->default_hash = 'sha256'; $this->default_hash = 'sha256';
return true; return true;
case 'blaze': // 0.0109 Seconds case 'blaze': // 0.0109 Seconds
$this->set_loops(1843); $this->set_loops(1843);
$this->set_length(64); $this->set_length(64);
$this->set_key_bits(32); $this->set_key_bytes(32);
$this->method = 'AES-128-CBC'; $this->method = 'AES-128-CBC';
$this->default_hash = 'sha256'; $this->default_hash = 'sha256';
return true; return true;
case 'quick': // 0.0167 Seconds case 'quick': // 0.0167 Seconds
$this->set_loops(2843); $this->set_loops(2843);
$this->set_length(64); $this->set_length(64);
$this->set_key_bits(32); $this->set_key_bytes(32);
$this->method = 'AES-192-CBC'; $this->method = 'AES-192-CBC';
$this->default_hash = 'sha256'; $this->default_hash = 'sha256';
return true; return true;
case 'good': // 0.0732 Seconds case 'good': // 0.0732 Seconds
$this->set_loops(11952); $this->set_loops(11952);
$this->set_length(64); $this->set_length(64);
$this->set_key_bits(32); $this->set_key_bytes(32); // 32B or 256b, standard key size
$this->method = 'AES-256-CBC'; $this->method = 'AES-256-CBC';
$this->default_hash = 'sha256'; $this->default_hash = 'sha256';
return true; return true;
case 'normal': // 0.4901 Seconds case 'normal': // 0.4901 Seconds
$this->set_loops(81952); // slow $this->set_loops(81952); // slow
$this->set_length(64); $this->set_length(64);
$this->set_key_bits(32); $this->set_key_bytes(32);
$this->method = 'AES-256-CBC'; $this->method = 'AES-256-CBC';
$this->default_hash = 'sha256'; $this->default_hash = 'sha256';
return true; return true;
@ -105,8 +105,8 @@ final class encryption {
case 'high': case 'high':
case 'slow-secure': // Very slow case 'slow-secure': // Very slow
$this->set_loops(82952); $this->set_loops(82952);
$this->set_length(128); $this->set_length(128); // extended length to make it work
$this->set_key_bits(64); $this->set_key_bytes(64); // extended key size for 512 hash
$this->method = 'AES-256-CBC'; $this->method = 'AES-256-CBC';
$this->default_hash = 'sha512'; $this->default_hash = 'sha512';
return true; return true;
@ -126,8 +126,8 @@ final class encryption {
$this->_raw = $output_raw; $this->_raw = $output_raw;
} }
public function set_key_bits(int $key_bits=self::key_bits): void { public function set_key_bytes(int $key_bytes=self::key_bytes): void {
$this->_key_bits = $key_bits; $this->_key_bytes = $key_bytes;
} }
public function list_ssl_methods(): array { public function list_ssl_methods(): array {
@ -224,8 +224,8 @@ final class encryption {
$iv = $this->random_engine->get_bytes($ivsize); // Requires PHP 7 $iv = $this->random_engine->get_bytes($ivsize); // Requires PHP 7
// Encryption key generated by PBKDF2 (since PHP 5.5) // Encryption key generated by PBKDF2 (since PHP 5.5)
$keys = hash_pbkdf2($this->default_hash, $key, $iv, $this->_iterations, $this->_length, $this->_raw); $keys = hash_pbkdf2($this->default_hash, $key, $iv, $this->_iterations, $this->_length, $this->_raw);
$encKey = substr($keys, 0, $this->_key_bits); // X bit encryption key $encKey = substr($keys, 0, $this->_key_bytes); // X bit encryption key
$hmacKey = substr($keys, $this->_key_bits); // X bit hmac key $hmacKey = substr($keys, $this->_key_bytes); // X bit hmac key
$ciphertext = openssl_encrypt( $ciphertext = openssl_encrypt(
$text, $text,
$this->method, $this->method,
@ -233,11 +233,11 @@ final class encryption {
OPENSSL_RAW_DATA, OPENSSL_RAW_DATA,
$iv $iv
); );
sodium_memzero($text); \bs_tts\common::wipe($text);
sodium_memzero($key); \bs_tts\common::wipe($key);
sodium_memzero($encKey); \bs_tts\common::wipe($encKey);
$hmac = hash_hmac($this->default_hash, $iv . $ciphertext, $hmacKey); $hmac = hash_hmac($this->default_hash, $iv . $ciphertext, $hmacKey);
sodium_memzero($hmacKey); \bs_tts\common::wipe($hmacKey);
if (! $this->binary) { if (! $this->binary) {
return (! $this->url_encode) ? base64_encode($hmac . $iv . $ciphertext) : \tts\misc::base64url_encode($hmac . $iv . $ciphertext); return (! $this->url_encode) ? base64_encode($hmac . $iv . $ciphertext) : \tts\misc::base64url_encode($hmac . $iv . $ciphertext);
} else { } else {
@ -264,9 +264,9 @@ final class encryption {
$ciphertext = substr($text, $ivsize + $this->_length); $ciphertext = substr($text, $ivsize + $this->_length);
// Generate the encryption and hmac keys // Generate the encryption and hmac keys
$keys = hash_pbkdf2($this->default_hash, $key, $iv, $this->_iterations, $this->_length, $this->_raw); $keys = hash_pbkdf2($this->default_hash, $key, $iv, $this->_iterations, $this->_length, $this->_raw);
$encKey = substr($keys, 0, $this->_key_bits); // X bit encryption key $encKey = substr($keys, 0, $this->_key_bytes); // X bit encryption key
$hmacNew = hash_hmac($this->default_hash, $iv . $ciphertext, substr($keys, $this->_key_bits)); $hmacNew = hash_hmac($this->default_hash, $iv . $ciphertext, substr($keys, $this->_key_bytes));
if (! hash_equals($hmac, $hmacNew)) { // to prevent timing attacks if (! hash_equals($hmac, $hmacNew)) { // to prevent timing attacks/Verify MSG Auth
return false; // Note: hash_equals() requires PHP5.6+ return false; // Note: hash_equals() requires PHP5.6+
} }
$ret = openssl_decrypt( $ret = openssl_decrypt(
@ -276,10 +276,10 @@ final class encryption {
OPENSSL_RAW_DATA, OPENSSL_RAW_DATA,
$iv $iv
); );
sodium_memzero($ciphertext); \bs_tts\common::wipe($ciphertext);
sodium_memzero($key); \bs_tts\common::wipe($key);
sodium_memzero($encKey); \bs_tts\common::wipe($encKey);
sodium_memzero($keys); \bs_tts\common::wipe($keys);
return $ret; return $ret;
} }
@ -303,7 +303,7 @@ final class encryption {
} }
$ret = bin2hex(pack('H*', $key)); $ret = bin2hex(pack('H*', $key));
sodium_memzero($key); \bs_tts\common::wipe($key);
return $ret; return $ret;
} }
@ -317,7 +317,7 @@ final class encryption {
} }
/** /**
* Also, this requires SSL connection to the database. * This FN requires SSL connection to the database.
* So, the KEY does not get exposed!!!! * So, the KEY does not get exposed!!!!
*/ */
public function mysql_aes_encode(string $data, string $key, bool $bind = true) { public function mysql_aes_encode(string $data, string $key, bool $bind = true) {
@ -325,14 +325,18 @@ final class encryption {
$safe_key = addslashes($key); $safe_key = addslashes($key);
$parm = ($bind) ? ":{$safe_text}" : "'{$safe_text}'"; $parm = ($bind) ? ":{$safe_text}" : "'{$safe_text}'";
$ret = "HEX(AES_ENCRYPT($parm},'{$safe_key}'))"; $ret = "HEX(AES_ENCRYPT($parm},'{$safe_key}'))";
sodium_memzero($key); \bs_tts\common::wipe($key);
sodium_memzero($safe_key); \bs_tts\common::wipe($safe_key);
sodium_memzero($data); \bs_tts\common::wipe($data);
sodium_memzero($safe_text); \bs_tts\common::wipe($safe_text);
sodium_memzero($parm); \bs_tts\common::wipe($parm);
return $ret; return $ret;
} }
/**
* This FN requires SSL connection to the database.
* So, the KEY does not get exposed!!!!
*/
public function mysql_aes_decode(string $field_name, string $key, bool $add_as = false) { public function mysql_aes_decode(string $field_name, string $key, bool $add_as = false) {
$safe_field = addslashes($field_name); $safe_field = addslashes($field_name);
$safe_key = addslashes($key); $safe_key = addslashes($key);

Loading…
Cancel
Save