title: What is causing these characters?
body: <p>I have a PHP page that loops through a CSV file and encrypts the 'email' column using the following function:</p>
  <pre><code>function my_encrypt($data, $key)
  {
      // Remove the base64 encoding from our key
      $encryption_key = base64_decode($key);
      // Generate an initialization vector
      $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
      // Encrypt the data using AES 256 encryption in CBC mode using our encryption key and initialization vector.
      $encrypted = openssl_encrypt($data, 'aes-256-cbc', $encryption_key, 0, $iv);
      // The $iv is just as important as the key for decrypting, so save it with our encrypted data using a unique separator (::)
      return base64_encode($encrypted . '::' . $iv);
  }
  </code></pre>
  <p>In another part of the app, I decrypt the returned value using:</p>
  <pre><code>function my_decrypt($data, $key)
  {
      // Remove the base64 encoding from our key
      $encryption_key = base64_decode($key);
      // To decrypt, split the encrypted data from our IV - our unique separator used was &quot;::&quot;
      list($encrypted_data, $iv) = explode('::', base64_decode($data), 2);
      return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
  }
  </code></pre>
  <p>This all works smoothly for the most part, but every now and then, the decrypted value comes back with a few weird characters in it.</p>
  <p>For example: <code>rsmi3�6CTΣ%mecompany.com</code> was returned instead of <code>rsmith@somecompany.com</code>.</p>
  <p>I'm not sure if it's the input or the output that is bad, but I'm guessing it has something to do with the uploaded CSV file... encoding issue? What do those characters mean and under what conditions are they produced?</p>
  <h2><strong>UPDATE</strong></h2>
  <p>Here's the code I'm using to add the encrypted value to the CSV:</p>
  <pre><code>$file = fopen(get_stylesheet_directory() . &quot;/emma_members.csv&quot;, &quot;r&quot;); //Open the old file for reading
  $newFile = fopen(get_stylesheet_directory() . &quot;/emma_members_new.csv&quot;, &quot;w&quot;); //Create a new file for writing
  
  if (!$file) error_log('ERROR opening file');
  if (!$newFile) error_log('ERROR creating file');
  
  $columns = ['email', 'member_id', 'member_since', 'plaintext_preferred', 'bounce_count', 'status_name', 'last_modified_at', 'city', 'first_name', 'last_name', 'request-demo', 'job-function', 'title', 'country', 'current-ams', 'opt-in', 'address-2', 'unique-identifier', 'state', 'postal_code', 'web-address', 'address', 'phone-number', 'company', 'area-of-specialization', 'work-phone'];
  
  while (($data = fgetcsv($file)) !== FALSE) {
  
      $row = array_combine($columns, $data);
  
      $email = &quot;{$row['email']}&quot;;
      $uid = my_encrypt($email, ENCRYPT_KEY_1);
  
      $row['unique-identifier'] = $uid;
      $ret = fputcsv($newFile, array_values($row));
  }
  </code></pre>
  <h2><strong>UPDATE 2</strong></h2>
  <p>So after much testing with thousands of emails, it seems the <code>my_encrypt</code> function returns some bad values, depending on the input of course. It didn't happen with EVERY email address, but even 1 is too many for my use case.</p>
  <p>I even tried getting rid of the <code>::</code> between the data and the iv, but that didn't work either (although it's possible I did it wrong).</p>
  <p>Anyway, I ended up using the following function in its place, and all is well:</p>
  <pre><code>function encrypt_decrypt($action, $string) {
      $output = false;
  
      $encrypt_method = &quot;AES-256-CBC&quot;;
      $secret_key = PHRASE_1;
      $secret_iv = PHRASE_2;
  
      // hash
      $key = hash('sha256', $secret_key);
      
      // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
      $iv = substr(hash('sha256', $secret_iv), 0, 16);
  
      if ( $action == 'encrypt' ) {
          $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
          $output = base64_encode($output);
      } else if( $action == 'decrypt' ) {
          $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
      }
  
      return $output;
  }
  </code></pre>