phacility/phabricator · error · Exception

Failed to openssl_decrypt() data: %s

Error message

Failed to openssl_decrypt() data: %s

What it means

Thrown by PhabricatorFileAES256StorageFormat::decryptData() when openssl_decrypt() returns false while reading a file stored with the 'aes-256-cbc' format. The ciphertext failed OpenSSL's AES-256-CBC decryption/padding checks, which almost always means the key or IV does not match the one used at write time, or the stored blob is corrupted or truncated. The message embeds PHP's openssl_error_string() output. The file stays unreadable until the correct key material is back in the keyring.

Source

Thrown at src/applications/files/format/PhabricatorFileAES256StorageFormat.php:165

          'Failed to openssl_encrypt() data: %s',
          openssl_error_string()));
    }

    return $result;
  }

  private function decryptData(
    $data,
    PhutilOpaqueEnvelope $key,
    PhutilOpaqueEnvelope $iv) {

    $method = 'aes-256-cbc';
    $key = $key->openEnvelope();
    $iv = $iv->openEnvelope();

    $result = openssl_decrypt($data, $method, $key, OPENSSL_RAW_DATA, $iv);
    if ($result === false) {
      throw new Exception(
        pht(
          'Failed to openssl_decrypt() data: %s',
          openssl_error_string()));
    }

    return $result;
  }

  public static function newAES256Key() {
    // Unsurprisingly, AES256 uses a 256 bit key.
    $key = Filesystem::readRandomBytes(phutil_units('256 bits in bytes'));
    return new PhutilOpaqueEnvelope($key);
  }

  public static function newAES256IV() {
    // AES256 uses a 256 bit key, but the initialization vector length is
    // only 128 bits.
    $iv = Filesystem::readRandomBytes(phutil_units('128 bits in bytes'));

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Restore the original key that encrypted the file to the keyring config (keep old keys and add the new one as a separate entry instead of replacing material)
  2. Verify the file's stored format.properties (IV) and the blob bytes are intact: check blob length in the storage engine and re-read from the backend
  3. If the key material is definitively lost, delete and re-upload the affected files — AES-256-CBC data cannot be recovered without the key
  4. Inspect the appended openssl_error_string() detail and confirm the PHP OpenSSL extension and cipher aes-256-cbc are available

Example fix

// before: rotation replaced the old key, reads now throw
// "keyring": [ { "name": "prod", "type": "aes-256-cbc", "material.base64": "<NEW>", "default": true } ]

// after: keep the previous key so existing files remain readable
// "keyring": [
//   { "name": "prod-2024", "type": "aes-256-cbc", "material.base64": "<NEW>", "default": true },
//   { "name": "prod-2023", "type": "aes-256-cbc", "material.base64": "<OLD>" }
// ]
Defensive patterns

Strategy: try-catch

Try / catch

try {
  $data = $file->loadFileData();
} catch (Exception $ex) {
  if (preg_match('/openssl_decrypt/', $ex->getMessage())) {
    // Key mismatch or corrupted encrypted blob for PHID ".$file->getPHID().".
    // Check keyring config before treating this as a storage outage.
    PhutilLogEngine::logError('files.decrypt', $ex->getMessage());
  }
  throw $ex;
}

Prevention

When it happens

Trigger: Calling loadFileData(), getFileDataIterator(), thumbnails/transforms, or `./bin/files cat` on an encrypted file after the keyring key material was replaced or the original key was removed; decrypting a blob whose bytes or stored format.properties IV were damaged in the storage engine (chunked MySQL blob, disk, S3); selecting a different key name via selectMasterKey() than the one the file was encrypted with.

Common situations: Key rotation that replaced key material instead of adding a new key alongside the old one; copying encrypted file rows between installs whose keyring configs differ; bit rot or manual edits in the storage blob; truncated multipart uploads left in storage.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/6d157ef9b5fa361c. Report an issue: GitHub.