Merge pull request #1761 from sjpadgett/PP2-appointment
[openemr.git] / library / crypto.php
blobdce0b902e193b1727f4ab6d5dc4fcdb7961c0440
1 <?php
2 /**
3 * Crypto library.
5 * @package OpenEMR
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
14 /**
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 // Use the standard key
30 if (empty($GLOBALS['key_for_encryption'])) {
31 // Collect the key. If it does not exist, then create it
32 $GLOBALS['key_for_encryption'] = aes256PrepKey();
34 $sSecretKey = $GLOBALS['key_for_encryption'];
35 } else {
36 // Turn the password into a hash to use as the key
37 $sSecretKey = hash("sha256", $customPassword);
40 $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-256-CBC'));
42 $processedValue = openssl_encrypt(
43 $sValue,
44 'AES-256-CBC',
45 $sSecretKey,
46 OPENSSL_RAW_DATA,
47 $iv
50 if ($sValue != "" && $processedValue == "") {
51 error_log("OpenEMR Error : Encryption is not working.");
54 // prepend the encrypted value with the $iv
55 $completedValue = $iv . $processedValue;
57 if ($baseEncode) {
58 return base64_encode($completedValue);
59 } else {
60 return $completedValue;
64 /**
65 * Function to AES256 decrypt a given string
67 * @param string $sValue Encrypted data that will be decrypted.
68 * @param string $customPassword If null, then use standard key. If provide a password, then will derive key from this.
69 * @param string $baseEncode True if wish to base64_decode() encrypted data.
70 * @return string returns the decrypted data.
72 function aes256Decrypt($sValue, $customPassword = null, $baseEncode = true)
74 if (!extension_loaded('openssl')) {
75 error_log("OpenEMR Error : Decryption is not working because missing openssl extension.");
78 if (empty($customPassword)) {
79 // Use the standard key
80 if (empty($GLOBALS['key_for_encryption'])) {
81 // Collect the key. If it does not exist, then create it
82 $GLOBALS['key_for_encryption'] = aes256PrepKey();
84 $sSecretKey = $GLOBALS['key_for_encryption'];
85 } else {
86 // Turn the password into a hash to use as the key
87 $sSecretKey = hash("sha256", $customPassword);
90 if ($baseEncode) {
91 $raw = base64_decode($sValue);
92 } else {
93 $raw = $sValue;
96 $ivLength = openssl_cipher_iv_length('AES-256-CBC');
98 $iv = substr($raw, 0, $ivLength);
99 $encrypted_data = substr($raw, $ivLength);
101 return openssl_decrypt(
102 $encrypted_data,
103 'AES-256-CBC',
104 $sSecretKey,
105 OPENSSL_RAW_DATA,
110 // Function to decrypt a given string
111 // This specific function is only used for backward compatibility
112 function aes256Decrypt_mycrypt($sValue)
114 $sSecretKey = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3");
115 return rtrim(
116 mcrypt_decrypt(
117 MCRYPT_RIJNDAEL_256,
118 $sSecretKey,
119 base64_decode($sValue),
120 MCRYPT_MODE_ECB,
121 mcrypt_create_iv(
122 mcrypt_get_iv_size(
123 MCRYPT_RIJNDAEL_256,
124 MCRYPT_MODE_ECB
126 MCRYPT_RAND
129 "\0"
133 // Function to collect (and create, if needed) the standard key
134 // The key is stored at sites/<site-dir>/documents/logs_and_misc/methods/one
135 // This mechanism will allow easy migration to new keys/ciphers in the future while
136 // also maintaining backward compatibility of encrypted data (for example, if upgrade
137 // to another cipher/mode, then could place the new key for this in
138 // sites/<site-dir>/documents/logs_and_misc/methods/two and then adjust pertinent code).
139 function aes256PrepKey()
141 // Collect the key. If it does not exist, then create it
142 if (!file_exists($GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/methods/one")) {
143 // Create a key file
144 // Below will produce a 256bit key (32 bytes equals 256 bits)
145 $newKey = base64_encode(openssl_random_pseudo_bytes(32));
146 file_put_contents($GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/methods/one", $newKey);
149 // Collect key from file
150 $key = base64_decode(rtrim(file_get_contents($GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/methods/one")));
152 if (empty($key)) {
153 error_log("OpenEMR Error : Audit Log with encryption is not working. Unable to collect key information or key is empty.");
156 // Return the key
157 return $key;