ECDSA (Elliptic Curve Digital Signature Algorithm) is more secure with shorter keys compared to RSA, and it also has faster verification speeds, making it widely applicable.
Since the ECDSA algorithm can only perform signing and cannot handle encryption and decryption, the ECIES (Elliptic Curve Integrated Encryption Scheme) was developed.
The ECIES uses the ECDH algorithm to generate a shared key, but due to platform compatibility issues, some older systems still cannot support it.
Therefore, based on the encryption approach of ECIES, I designed my own RSAIES encryption method:
Detailed Explanation of RSAIES Encryption Method
- Generate a random AES key and encrypt it using the RSA encryption method.
- Generate a random AES key IV value.
- Use the random AES key to perform AES-128-CFB encryption on the data, with the parameter OPENSSL_RAW_DATA.
- Base64 process the ciphertext and IV value (supports HEX).
- Calculate the hash value (mac) using SHA256 for the receiver to verify data integrity.
- Put the encrypted random AES key
cipher, vectoriv, encoding methodcode, ciphertext hash valuemac, and encryption typeRSAIESinto the encryption field.
Detailed Explanation of RSAIES Decryption Method
- Calculate the hash value of the received ciphertext using SHA256 to verify if the mac value is the same, determining if the data is complete.
- Decode the received encrypted random AES key
cipherusingbase64_decode, then decrypt it using the RSA method to obtain the original AES key. - Use the obtained random AES key and the received vector
ivto decrypt using aes-128-cfb, with the parameter OPENSSL_RAW_DATA. - Obtain the plaintext.
Example code: https://github.com/unntech/litephp/blob/master/src/Encrypt/RSA.php
/**
* RSAIES encryption
* Generate a random AES key and encrypt it using the RSA method.
* Use AES-128-CFB to encrypt the text, with the parameter OPENSSL_RAW_DATA.
* @param string $plaintext Plaintext data
* @param string $code Ciphertext encoding supports base64 | hex | bin
* @return false | array
* [ 'cipher' => 'encrypted AES key',
* 'iv' => 'iv',
* 'code' => 'base64',
* 'ciphertext' => 'ciphertext',
* 'mac' => 'ciphertext SHA256 hash'
* ]
*
*/
public function encrypt_ies(string $plaintext, string $code = 'base64', int $padding = OPENSSL_PKCS1_PADDING)
{
$publicKey = $this->third_public_key;
// Generate random symmetric key
$cipher_method = 'aes-128-cfb';
$symmetricKey = openssl_random_pseudo_bytes(16); // Use AES-128 key length
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher_method));
// Encrypt the symmetric key using the public key (using RSAIES process)
openssl_public_encrypt($symmetricKey, $encryptedKey, $publicKey, $padding);
// Encrypt the message using the symmetric key (AES-128-CFB)
$encryptedMessage = openssl_encrypt($plaintext, $cipher_method, $symmetricKey, OPENSSL_RAW_DATA, $iv);
$ciphertext = Encode::encode($encryptedMessage, $code);
// Calculate the hash value of the ciphertext using SHA256
$mac = strtoupper(hash("sha256", $ciphertext));
// AES key cipher, vector iv, ciphertext, and hash value
return [
'cipher_method' => $cipher_method,
'cipher' => Encode::encode($encryptedKey, $code),
'iv' => Encode::encode($iv, $code),
'code' => $code,
'ciphertext' => $ciphertext,
'mac' => $mac,
];
}
/**
* RSAIES decryption
* Decrypt $cipher using RSA method to obtain the AES key.
* Decrypt the ciphertext using AES-128-CFB, with the parameter OPENSSL_RAW_DATA, to obtain the plaintext.
* @param string $ciphertext Ciphertext
* @param string $cipher Encrypted AES key
* @param string $iv AES encryption vector
* @param string|null $mac Ciphertext hash value
* @param string $code Encoding
* @param int $padding Padding method (OPENSSL_PKCS1_PADDING / OPENSSL_NO_PADDING)
* @return string|null
*/
public function decrypt_ies(string $ciphertext, string $cipher = '', string $iv = '', ?string $mac = null, string $code = 'base64', int $padding = OPENSSL_PKCS1_PADDING): ?string
{
// Decrypt the symmetric key
openssl_private_decrypt(Encode::decode($cipher, $code), $symmetricKey, $this->private_key, $padding);
if (empty($symmetricKey)) {
return null;
}
// 2. Verify MAC
if (!is_null($mac)) {
$_mac = strtoupper(hash("sha256", $ciphertext));
if ($mac != $_mac) {
return null;
}
}
// 3. Decrypt the ciphertext
$plaintext = openssl_decrypt(Encode::decode($ciphertext, $code), 'aes-128-cfb', $symmetricKey, OPENSSL_RAW_DATA, Encode::decode($iv, $code));
return $plaintext;
}
RSAIES (Integrated Encryption Scheme) is an RSA integrated encryption scheme that takes advantage of RSA’s wide usage and high cross-platform compatibility, using RSA to encrypt and decrypt the random AES key.
Then, AES is used for symmetric encryption of data, which is faster than RSA encryption and avoids the complexity of handling long texts in RSA encryption.