The Encryption
class in JiFramework provides a set of methods for securely handling encryption and decryption of data, as well as password hashing and verification. It leverages industry-standard algorithms like AES-256-CBC for symmetric encryption and PBKDF2 for key derivation, ensuring that your application's sensitive data is protected against unauthorized access.
Key Features:
- Two Methods of Encryption:
- Key-Based Encryption: Encrypt data using a 32-byte encryption key directly. This method is suitable when you can securely store and manage the encryption keys.
- Password-Based Encryption: Encrypt data using a password of any length. The class internally derives a 32-byte key from the password using a secure key derivation function (PBKDF2). This method is convenient when you prefer to use passwords or passphrases instead of managing encryption keys.
By using the Encryption
class, developers can:
- Generate strong encryption keys and initialization vectors.
- Encrypt and decrypt data securely using symmetric encryption with keys or passwords.
- Derive encryption keys from passwords using a secure key derivation function.
- Hash and verify passwords using built-in PHP functions.
Important: Proper use of cryptographic functions is critical for application security. Always follow best practices and understand the implications of each method.
Usage:
// Option 1: Initialize the Encryption through the App
use JIFramework\Core\App\App;
$app = new App();
$encryption= $app->encryption;
OR
// Option 2: Directly instantiate the Encryption
use JIFramework\Core\Security\Encryption;
$encryption = new Encryption();
Explanation:
- Option 1: Initializes the
App
class and retrieves theencryption
instance through it, using the framework's main entry point. - Option 2: Directly creates a
encryption
instance.
Method: generateKey(int $length = 32): string
Description: Generates a random encryption key of specified length.
Parameters:
- $length (
int
, optional): The length of the key in bytes. Default is32
bytes for AES-256.
Returns: A hexadecimal string representing the generated key.
Usage:
$key = $encryption->generateKey(); // Generates a 32-byte key
echo 'Encryption Key: ' . $key;
// Example output:
// Encryption Key: 4d6f6e636861727461746162616361626164616262616461626361626164616461
Explanation:
- Uses
random_bytes()
to generate cryptographically secure random bytes. - Converts the binary key to a hexadecimal string using
bin2hex()
. - The key can be stored securely and used for encryption and decryption.
Method: encrypt(string $plaintext, string $key, string $iv = null): string
Description: Encrypts plaintext data using AES-256-CBC encryption with a 32-byte key.
Parameters:
- $plaintext (
string
): The data to encrypt. - $key (
string
): The encryption key in hexadecimal format. - $iv (
string
, optional): The initialization vector (IV) in hexadecimal format. If not provided, a random IV is generated.
Returns: A base64-encoded string containing the encrypted data along with the IV.
Usage:
$plaintext = 'Sensitive data to encrypt';
$key = $encryption->generateKey();
// Encrypt the data
$encryptedData = $encryption->encrypt($plaintext, $key);
echo 'Encrypted Data: ' . $encryptedData;
// Example output:
// Encrypted Data: U2FsdGVkX1+Kkq7jOjE8RVQ6pFradV1F7LrQWZfpK0c=
Explanation:
- Converts the key from hexadecimal to binary using
hex2bin()
. - If no IV is provided, generates a random IV of appropriate length.
- Encrypts the plaintext using
openssl_encrypt()
with AES-256-CBC. - Concatenates the IV and ciphertext, separates them with
::
, and encodes the result using base64. - The resulting string contains both the IV and the ciphertext, necessary for decryption.
Method: decrypt(string $ciphertext, string $key): string|false
Description: Decrypts data previously encrypted with the encrypt()
method using a 32-byte key.
Parameters:
- $ciphertext (
string
): The base64-encoded encrypted data containing the IV and ciphertext. - $key (
string
): The encryption key in hexadecimal format.
Returns: The decrypted plaintext as a string, or false
on failure.
Usage:
// Assume $encryptedData and $key are obtained from the encryption step
$decryptedData = $encryption->decrypt($encryptedData, $key);
if ($decryptedData !== false) {
echo 'Decrypted Data: ' . $decryptedData;
} else {
echo 'Decryption failed.';
}
// Example output:
// Decrypted Data: Sensitive data to encrypt
Explanation:
- Decodes the base64-encoded data to retrieve the concatenated IV and ciphertext.
- Splits the data using
explode('::', $data, 2)
to separate the IV and ciphertext. - Converts the key from hexadecimal to binary.
- Decrypts the ciphertext using
openssl_decrypt()
with AES-256-CBC. - Returns the plaintext if successful, or
false
if decryption fails.
Method: generateKeyFromPassword(string $password, string $salt = null, int $iterations = 100000): array
Description: Derives a secure 32-byte encryption key from a password of any length using PBKDF2 with SHA-256.
Parameters:
- $password (
string
): The password to derive the key from. - $salt (
string
, optional): A hexadecimal string representing the salt. If not provided, a random salt is generated. - $iterations (
int
, optional): The number of iterations for the key derivation function. Default is100,000
.
Returns: An associative array containing:
- 'key' (
string
): The derived 32-byte key in hexadecimal format. - 'salt' (
string
): The salt used in hexadecimal format.
Usage:
$password = 'my_secure_password';
$keyData = $encryption->generateKeyFromPassword($password);
echo 'Derived Key: ' . $keyData['key'] . PHP_EOL;
echo 'Salt: ' . $keyData['salt'];
// Example output:
// Derived Key: a1b2c3d4e5f67890123456789abcdef0a1b2c3d4e5f67890123456789abcdef0
// Salt: 1234567890abcdef1234567890abcdef
Explanation:
- If no salt is provided, generates a random 16-byte salt.
- Uses
hash_pbkdf2()
withsha256
to derive a 32-byte key from the password and salt. - Returns the key and salt in hexadecimal format for storage or further use.
- The salt should be stored alongside the key or encrypted data for future derivations.
Method: encryptWithPassword(string $plaintext, string $password, int $iterations = 100000): string
Description: Encrypts data using a password of any length. Internally, it derives a 32-byte encryption key from the password using PBKDF2 and then encrypts the data using AES-256-CBC.
Parameters:
- $plaintext (
string
): The data to encrypt. - $password (
string
): The password to derive the encryption key. - $iterations (
int
, optional): The number of iterations for the key derivation function. Default is100,000
.
Returns: A base64-encoded string containing the salt, IV, and ciphertext.
Usage:
$plaintext = 'Sensitive data to encrypt';
$password = 'my_secret_password';
$encryptedData = $encryption->encryptWithPassword($plaintext, $password);
echo 'Encrypted Data: ' . $encryptedData;
// Example output:
// Encrypted Data: U2FsdGVkX19i32jS2fE0x6Jx5aI6PbLqL4zJX1V7k1o=
Explanation:
- Password-Based Encryption: Allows encryption using a password of any length without needing to manage encryption keys directly.
- Generates a random salt and IV.
- Derives a 32-byte key from the password and salt using PBKDF2 with SHA-256.
- Encrypts the plaintext using
openssl_encrypt()
with AES-256-CBC. - Concatenates the salt, IV, and ciphertext in binary form.
- Encodes the result using base64 for storage or transmission.
- The recipient will need the same password to decrypt the data.
Method: decryptWithPassword(string $encodedData, string $password, int $iterations = 100000): string|false
Description: Decrypts data encrypted with the encryptWithPassword()
method using the password provided. Internally, it derives the same 32-byte key from the password and salt.
Parameters:
- $encodedData (
string
): The base64-encoded encrypted data containing the salt, IV, and ciphertext. - $password (
string
): The password used to derive the decryption key. - $iterations (
int
, optional): The number of iterations for the key derivation function. Must match the value used during encryption. Default is100,000
.
Returns: The decrypted plaintext as a string, or false
on failure.
Usage:
// Assume $encryptedData is obtained from the encryption step
$decryptedData = $encryption->decryptWithPassword($encryptedData, $password);
if ($decryptedData !== false) {
echo 'Decrypted Data: ' . $decryptedData;
} else {
echo 'Decryption failed.';
}
// Example output:
// Decrypted Data: Sensitive data to encrypt
Explanation:
- Decodes the base64-encoded data to retrieve the concatenated salt, IV, and ciphertext.
- Extracts the salt (16 bytes), IV, and ciphertext from the binary data.
- Derives the same 32-byte key from the password and extracted salt using PBKDF2 with SHA-256.
- Decrypts the ciphertext using
openssl_decrypt()
with AES-256-CBC. - Returns the plaintext if successful, or
false
if decryption fails.
Method: hashPassword(string $password): string
Description: Securely hashes a password using PHP's password_hash()
function.
Parameters:
- $password (
string
): The plaintext password to hash.
Returns: The hashed password as a string.
Usage:
$password = 'user_password';
$hashedPassword = $encryption->hashPassword($password);
echo 'Hashed Password: ' . $hashedPassword;
// Example output:
// Hashed Password: $2y$10$e0NRoF8Zp5e9sJYx/ox7ku3Z1oOFiHlGkE4Pl2Sm1X4U9tGmFg6u6
Explanation:
- Uses
password_hash()
with the default algorithm (usuallybcrypt
). - The resulting hash includes the algorithm, cost factor, and salt.
- The hash can be stored in the database for user authentication.
Method: verifyPassword(string $password, string $hash): bool
Description: Verifies a plaintext password against a hashed password.
Parameters:
- $password (
string
): The plaintext password to verify. - $hash (
string
): The hashed password to compare against.
Returns: true
if the password matches the hash, false
otherwise.
Usage:
// Assume $hashedPassword is retrieved from the database
$isValid = $encryption->verifyPassword($password, $hashedPassword);
if ($isValid) {
echo 'Password is valid.';
} else {
echo 'Invalid password.';
}
// Example output:
// Password is valid.
Explanation:
- Uses
password_verify()
to compare the plaintext password with the stored hash. - Returns
true
if the password is correct,false
otherwise. - Essential for authenticating users during login.
Below is a complete example demonstrating how to use the Encryption
class in an application.
$encryption->generateKey();
echo 'Generated Key: ' . $key . PHP_EOL;
// Encrypt data using the key
$plaintext = 'Secret message to encrypt';
$encryptedData = $encryption->encrypt($plaintext, $key);
echo 'Encrypted Data: ' . $encryptedData . PHP_EOL;
// Decrypt data using the same key
$decryptedData = $encryption->decrypt($encryptedData, $key);
if ($decryptedData !== false) {
echo 'Decrypted Data: ' . $decryptedData . PHP_EOL;
} else {
echo 'Decryption failed.' . PHP_EOL;
}
// 2. Password-Based Encryption and Decryption
echo "\n=== Password-Based Encryption ===\n";
// Encrypt data with a password
$password = 'UserPassword123!';
$encryptedWithPassword = $encryption->encryptWithPassword($plaintext, $password);
echo 'Encrypted with Password: ' . $encryptedWithPassword . PHP_EOL;
// Decrypt data with the same password
$decryptedWithPassword = $encryption->decryptWithPassword($encryptedWithPassword, $password);
if ($decryptedWithPassword !== false) {
echo 'Decrypted with Password: ' . $decryptedWithPassword . PHP_EOL;
} else {
echo 'Decryption with password failed.' . PHP_EOL;
}
// 3. Password Hashing and Verification
echo "\n=== Password Hashing ===\n";
// Hash a password
$hashedPassword = $encryption->hashPassword($password);
echo 'Hashed Password: ' . $hashedPassword . PHP_EOL;
// Verify the password
$isPasswordValid = $encryption->verifyPassword($password, $hashedPassword);
if ($isPasswordValid) {
echo 'Password is valid.' . PHP_EOL;
} else {
echo 'Invalid password.' . PHP_EOL;
}
Sample Output:
=== Key-Based Encryption ===
Generated Key: e7c8f1a5d6b9c3e2f4a1b2c3d4e5f6789abcdef0123456789abcdef01234567
Encrypted Data: [base64-encoded string]
Decrypted Data: Secret message to encrypt
=== Password-Based Encryption ===
Encrypted with Password: [base64-encoded string]
Decrypted with Password: Secret message to encrypt
=== Password Hashing ===
Hashed Password: $2y$10$...
Password is valid.