6 * @link http://www.open-emr.org
7 * @author Ensoftek, Inc
8 * @author Brady Miller <brady.g.miller@gmail.com>
9 * @copyright Copyright (c) 2015 Ensoftek, Inc
10 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
11 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
15 * Function to AES256 encrypt a given string
17 * @param string $sValue Raw data that will be encrypted.
18 * @param string $customPassword If null, then use standard key. If provide a password, then will derive key from this.
19 * @param string $baseEncode True if wish to base64_encode() encrypted data.
20 * @return string returns the encrypted data.
22 function aes256Encrypt($sValue, $customPassword = null, $baseEncode = true)
24 if (!extension_loaded('openssl')) {
25 error_log("OpenEMR Error : Encryption is not working because missing openssl extension.");
28 if (empty($customPassword)) {
29 // Collect the encryption key. If it does not exist, then create it
30 $sSecretKey = aes256PrepKey("two", "a");
32 // Turn the password into a hash(note use binary) to use as the key
33 $sSecretKey = hash("sha256", $customPassword, true);
35 // Collect the separate key for the HMAC hash. If it does not exist, then create it
36 $sSecretKeyHmac = aes256PrepKey("two", "b");
38 if (empty($sSecretKey) ||
empty($sSecretKeyHmac)) {
39 error_log("OpenEMR Error : Encryption is not working because key(s) is blank.");
43 $iv = random_bytes(openssl_cipher_iv_length('AES-256-CBC'));
45 error_log('OpenEMR Error : Encryption is not working because of random_bytes() Error: ' . $e->getMessage());
46 } catch (Exception
$e) {
47 error_log('OpenEMR Error : Encryption is not working because of random_bytes() Exception: ' . $e->getMessage());
50 $processedValue = openssl_encrypt(
58 $hmacHash = hash_hmac('sha256', $iv.$processedValue, $sSecretKeyHmac, true);
60 if ($sValue != "" && ($processedValue == "" ||
$hmacHash == "")) {
61 error_log("OpenEMR Error : Encryption is not working.");
64 // prepend the encrypted value with the $hmacHash and $iv
65 $completedValue = $hmacHash . $iv . $processedValue;
68 return base64_encode($completedValue);
70 return $completedValue;
76 * Function to AES256 decrypt a given string, version 2
78 * @param string $sValue Encrypted data that will be decrypted.
79 * @param string $customPassword If null, then use standard key. If provide a password, then will derive key from this.
80 * @param string $baseEncode True if wish to base64_decode() encrypted data.
81 * @return string or false returns the decrypted data or false if failed.
83 function aes256DecryptTwo($sValue, $customPassword = null, $baseEncode = true)
85 if (!extension_loaded('openssl')) {
86 error_log("OpenEMR Error : Decryption is not working because missing openssl extension.");
90 if (empty($customPassword)) {
91 // Collect the encryption key.
92 $sSecretKey = aes256PrepKey("two", "a");
94 // Turn the password into a hash(note use primary) to use as the key
95 $sSecretKey = hash("sha256", $customPassword, true);
97 // Collect the separate key for the HMAC hash. If it does not exist, then create it
98 $sSecretKeyHmac = aes256PrepKey("two", "b");
100 if (empty($sSecretKey) ||
empty($sSecretKeyHmac)) {
101 error_log("OpenEMR Error : Encryption is not working because key(s) is blank.");
106 $raw = base64_decode($sValue, true);
107 if ($raw === false) {
108 error_log("OpenEMR Error : Encryption did not work because illegal characters were noted in base64_encoded data.");
115 $ivLength = openssl_cipher_iv_length('AES-256-CBC');
116 $hmacHash = mb_substr($raw, 0, 32, '8bit');
117 $iv = mb_substr($raw, 32, $ivLength, '8bit');
118 $encrypted_data = mb_substr($raw, ($ivLength+
32), null, '8bit');
120 $calculatedHmacHash = hash_hmac('sha256', $iv.$encrypted_data, $sSecretKeyHmac, true);
122 if (hash_equals($hmacHash, $calculatedHmacHash)) {
123 return openssl_decrypt(
131 error_log("OpenEMR Error : Decryption failed authentication.");
137 * Function to AES256 decrypt a given string, version 1
139 * @param string $sValue Encrypted data that will be decrypted.
140 * @param string $customPassword If null, then use standard key. If provide a password, then will derive key from this.
141 * @param string $baseEncode True if wish to base64_decode() encrypted data.
142 * @return string returns the decrypted data.
144 function aes256DecryptOne($sValue, $customPassword = null, $baseEncode = true)
146 if (!extension_loaded('openssl')) {
147 error_log("OpenEMR Error : Decryption is not working because missing openssl extension.");
150 if (empty($customPassword)) {
151 // Collect the key. If it does not exist, then create it
152 $sSecretKey = aes256PrepKey();
154 // Turn the password into a hash to use as the key
155 $sSecretKey = hash("sha256", $customPassword);
158 if (empty($sSecretKey)) {
159 error_log("OpenEMR Error : Encryption is not working.");
163 $raw = base64_decode($sValue);
168 $ivLength = openssl_cipher_iv_length('AES-256-CBC');
170 $iv = substr($raw, 0, $ivLength);
171 $encrypted_data = substr($raw, $ivLength);
173 return openssl_decrypt(
182 // Function to decrypt a given string
183 // This specific function is only used for backward compatibility
184 function aes256Decrypt_mycrypt($sValue)
186 $sSecretKey = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3");
191 base64_decode($sValue),
205 // Function to collect (and create, if needed) the standard key
206 // The key is stored at sites/<site-dir>/documents/logs_and_misc/methods/one
207 // This mechanism will allow easy migration to new keys/ciphers in the future while
208 // also maintaining backward compatibility of encrypted data (for example, if upgrade
209 // to another cipher/mode, then could place the new key for this in
210 // sites/<site-dir>/documents/logs_and_misc/methods/two and then adjust pertinent code).
211 function aes256PrepKey($version = "one", $sub = "")
214 $label = $version.$sub;
216 // Collect the key. If it does not exist, then create it
217 if (!file_exists($GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/methods/" . $label)) {
221 // Produce a 256bit key (32 bytes equals 256 bits)
222 $newKey = random_bytes(32);
224 error_log('OpenEMR Error : Encryption is not working because of random_bytes() Error: ' . $e->getMessage());
225 } catch (Exception
$e) {
226 error_log('OpenEMR Error : Encryption is not working because of random_bytes() Exception: ' . $e->getMessage());
229 file_put_contents($GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/methods/". $label, base64_encode($newKey));
232 // Collect key from file
233 $key = base64_decode(rtrim(file_get_contents($GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/methods/" . $label)));
236 error_log("OpenEMR Error : Key creation is not working.");