diff --git a/tfa.admin.inc b/tfa.admin.inc
index 28319af..c063e08 100644
--- a/tfa.admin.inc
+++ b/tfa.admin.inc
@@ -25,10 +25,10 @@ function tfa_admin_settings($form, $form_state) {
     }
   }
 
-  // Check if mcrypt plugin is available.
-  if (!extension_loaded('mcrypt')) {
+  // Check if openssl or mcrypt extensions are available.
+  if (!extension_loaded('openssl') && !extension_loaded('mcrypt')) {
     // @todo allow alter in case of other encryption libs.
-    drupal_set_message(t('The TFA module requires the PHP Mcrypt extension be installed on the web server. See <a href="!link">the TFA help documentation</a> for setup.', array('!link' => url('admin/help/tfa'))), 'error');
+    drupal_set_message(t('The TFA module requires one of the PHP OpenSSL or MCrypt extensions to be installed on the web server. See <a href="!link">the TFA help documentation</a> for setup.', array('!link' => url('admin/help/tfa'))), 'error');
     return array();
   }
 
diff --git a/tfa.inc b/tfa.inc
index bb9ab82..035eb0c 100644
--- a/tfa.inc
+++ b/tfa.inc
@@ -376,6 +376,8 @@ class TfaSetup {
  */
 abstract class TfaBasePlugin {
 
+  const CRYPT_VERSION = '1';
+
   /**
    * @var string
    */
@@ -502,18 +504,43 @@ abstract class TfaBasePlugin {
    *
    * Should be used when writing codes to storage.
    *
-   * @param string.
+   * @param string $text
+   *   The plaintext to be encrypted.
+   *
    * @return string
+   *   The encrypted text.
    */
   protected function encrypt($text) {
+    // Backwards compatibility with MCrypt.
+    if (!extension_loaded('openssl') && extension_loaded('mcrypt')) {
+      return $this->encryptWithMCrypt($text);
+    }
+    $iv = drupal_random_bytes(16);
+
+    return sprintf(
+      '%s|%s|%s',
+      self::CRYPT_VERSION,
+      $iv,
+      openssl_encrypt($text, 'AES-256-CBC', $this->encryptionKey, OPENSSL_RAW_DATA, $iv)
+    );
+  }
+
+  /**
+   * Encrypt using the deprecated mcrypt extension.
+   *
+   * @param string $text
+   *
+   * @return string
+   */
+  protected function encryptWithMCrypt($text, $iv = null) {
     $td = mcrypt_module_open('rijndael-128', '', 'cbc', '');
-    $iv = drupal_random_bytes(mcrypt_enc_get_iv_size($td));
+    $iv = $iv ?: drupal_random_bytes(mcrypt_enc_get_iv_size($td));
 
     $key = substr($this->encryptionKey, 0, mcrypt_enc_get_key_size($td));
 
     mcrypt_generic_init($td, $key, $iv);
-    // Encrypt with message length so decryption can return message without
-    // padding.
+      // Encrypt with message length so decryption can return message without
+      // padding.
     $text = strlen($text) . '|' . $text;
     $data = mcrypt_generic($td, $text);
 
@@ -528,10 +555,36 @@ abstract class TfaBasePlugin {
    *
    * Should be used when reading codes from storage.
    *
-   * @param string
+   * @param string $data
+   *   The encrypted text.
+   *
    * @return string
+   *   The plaintext, or FALSE on failure.
    */
   protected function decrypt($data) {
+    $version_prefix = self::CRYPT_VERSION . '|';
+    $version_match = strpos($data, $version_prefix) === 0;
+    // Backwards compatibility with the old MCrypt scheme.
+    if (!$version_match) {
+      if (extension_loaded('mcrypt')) {
+        return $this->decryptWithMCrypt($data);
+      }
+      return FALSE;
+    }
+
+    list(, $iv, $data) = explode('|', $data, 3);
+
+    return openssl_decrypt($data, 'AES-256-CBC', $this->encryptionKey, TRUE, $iv);
+  }
+
+  /**
+   * Decrypt using the deprecated MCrypt extension.
+   *
+   * @param string $data
+   *
+   * @return string
+   */
+  protected function decryptWithMCrypt($data) {
     $td = mcrypt_module_open('rijndael-128', '', 'cbc', '');
     $iv = substr($data, 0, mcrypt_enc_get_iv_size($td));
 
diff --git a/tfa.install b/tfa.install
index cbf7943..9bd610d 100644
--- a/tfa.install
+++ b/tfa.install
@@ -26,13 +26,19 @@ function tfa_uninstall() {
  */
 function tfa_requirements($phase) {
   if ($phase == 'runtime') {
-    if (!extension_loaded('mcrypt')) {
-      $requirement_severity = REQUIREMENT_ERROR;
-      $description = t('The TFA module requires the PHP Mcrypt extension be installed on the web server.');
+    if (!extension_loaded('openssl')) {
+      if (extension_loaded('mcrypt')) {
+        $requirement_severity = REQUIREMENT_WARNING;
+        $description = t('The TFA module recommends the PHP OpenSSL extension to be installed on the web server.');
+      }
+      else {
+        $requirement_severity = REQUIREMENT_ERROR;
+        $description = t('The TFA module requires either the PHP OpenSSL or MCrypt extensions to be installed on the web server.');
+      }
     }
     else {
       $requirement_severity = REQUIREMENT_OK;
-      $description= '';
+      $description = '';
     }
 
     $enabled = variable_get('tfa_enabled', 0);
