/** * Encrypts the settings using the automatically detected preferred algorithm * * @param $settingsINI string The raw settings INI string * * @return string The encrypted data to store in the database */ public static function encryptSettings($settingsINI, $key = null) { // Do we really support encryption? if (!self::supportsEncryption()) { return $settingsINI; } // Does any of the preferred encryption engines exist? $encryption = self::preferredEncryption(); if (empty($encryption)) { return $settingsINI; } // Do we have a non-empty key to begin with? if (empty($key)) { $key = self::getKey(); } if (empty($key)) { return $settingsINI; } if ($encryption == 'AES128') { $encrypted = AEUtilEncrypt::AESEncryptCBC($settingsINI, $key, 128); if (empty($encrypted)) { $encryption = 'CTR128'; } else { // Note: CBC returns the encrypted data as a binary string and requires Base 64 encoding $settingsINI = '###AES128###' . base64_encode($encrypted); } } if ($encryption == 'CTR128') { $encrypted = AEUtilEncrypt::AESEncryptCtr($settingsINI, $key, 128); if (empty($encrypted)) { $encryption = ''; } else { // Note: CTR returns the encrypted data readily encoded in Base 64 $settingsINI = '###CTR128###' . $encrypted; } } return $settingsINI; }
/** * Writes an encrypted block to the archive * @param resource $fp The file pointer resource of the file to write to * @param string $data Raw binary data to encrypt and write */ private function _writeEncryptedBlock(&$fp, $data) { $decryptedSize = akstringlen($data); $data = AEUtilEncrypt::AESEncryptCBC($data, $this->password, 128); $encryptedSize = akstringlen($data); // Do we have enough space to store the 8 byte header? if ($this->_useSplitZIP) { // Compare to free part space clearstatcache(); $current_part_size = @filesize($this->_dataFileName); $free_space = $this->_fragmentSize - ($current_part_size === false ? 0 : $current_part_size); if ($free_space <= 8) { @fclose($fp); // Not enough space on current part, create new part if (!$this->_createNewPart()) { $this->setError('Could not create new JPS part file ' . basename($this->_dataFileName)); return false; } // Open data file for output $fp = @fopen($this->_dataFileName, "ab"); if ($fp === false) { $this->setError("Could not open archive file '{$this->_dataFileName}' for append!"); return; } } } else { $free_space = $encryptedSize + 8; } // Write the header $this->_fwrite($fp, pack('V', $encryptedSize) . pack('V', $decryptedSize)); if ($this->getError()) { return; } $free_space -= 8; // Do we have enough space to write the data in one part? if ($free_space >= $encryptedSize) { $this->_fwrite($fp, $data); if ($this->getError()) { return; } } else { // Split between parts - Write first part $firstPart = substr($data, 0, $free_space); $secondPart = substr($data, $free_space); if (md5($firstPart . $secondPart) != md5($data)) { die('DEBUG -- Multibyte character problems!'); die; } $this->_fwrite($fp, $firstPart, $free_space); if ($this->getError()) { @fclose($fp); return; } // Create new part if (!$this->_createNewPart()) { // Die if we couldn't create the new part $this->setError('Could not create new JPA part file ' . basename($this->_dataFileName)); @fclose($fp); return false; } else { // Close the old data file @fclose($fp); // Open data file for output $fp = @fopen($this->_dataFileName, "ab"); if ($fp === false) { $this->setError("Could not open archive file {$this->_dataFileName} for append!"); return false; } } // Write the rest of the data $this->_fwrite($fp, $secondPart, $encryptedSize - $free_space); } }
/** * Packages the response to a JSON-encoded object, optionally encrypting the * data part with a caller-supplied password. * @return string The JSON-encoded response */ private function getResponse() { // Initialize the response $response = array('encapsulation' => $this->encapsulation, 'body' => array('status' => $this->status, 'data' => null)); switch ($this->method_name) { case 'Download': $data = json_encode($this->data); break; default: $data = $this->json_encode($this->data); break; } if (empty($this->password)) { $this->encapsulation = self::ENCAPSULATION_RAW; } switch ($this->encapsulation) { case self::ENCAPSULATION_RAW: break; case self::ENCAPSULATION_AESCTR128: $data = AEUtilEncrypt::AESEncryptCtr($data, $this->password, 128); break; case self::ENCAPSULATION_AESCTR256: $data = AEUtilEncrypt::AESEncryptCtr($data, $this->password, 256); break; case self::ENCAPSULATION_AESCBC128: $data = base64_encode(AEUtilEncrypt::AESEncryptCBC($data, $this->password, 128)); break; case self::ENCAPSULATION_AESCBC256: $data = base64_encode(AEUtilEncrypt::AESEncryptCBC($data, $this->password, 256)); break; } $response['body']['data'] = $data; switch ($this->method_name) { case 'Download': return '###' . json_encode($response) . '###'; break; default: return '###' . $this->json_encode($response) . '###'; break; } }