title: AES 128 CBC encryption in PHP
body: <p>Hello guys I have a problem with my encryption. I created a simple member registration that can encrypt user's data. but before encrypting it I must format it in JSON format. But I have a problem in getting back the correct data. When I decoded my code. It has an excess character in the JSON that's why I can't get the correct value. But the JSON data is correct after decrypting it. </p>
  
  <p>Here's my goal.</p>
  
  <ol>
  <li>Get member's input data</li>
  <li>Format the data in JSON format</li>
  <li>Encrypt it using AES 128 CBC encryption (I created a function the returns an array. One is the encrypted and the other is the decrypted)</li>
  <li>Display the encrypted and the decrypted data in plain text</li>
  </ol>
  
  <p>Here's my code so far.</p>
  
  <p>My function in encrypting and decrypting data</p>
  
  <pre><code>public function encryption($data){
  
      # --- ENCRYPTION ---
  
      # the key should be random binary, use scrypt, bcrypt or PBKDF2 to
      # convert a string into a key
      # key is specified using hexadecimal
      $key = pack('H*', "73f8d4969098400c44dcb50111eb4193");
  
      # show key size use either 16, 24 or 32 byte keys for AES-128, 192
      # and 256 respectively
      $key_size =  strlen($key);
      //echo "Key size: " . $key_size . "&lt;br /&gt;";
  
      $plaintext = $data;
  
      # create a random IV to use with CBC encoding
      $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
      $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
  
      # creates a cipher text compatible with AES (Rijndael block size = 128)
      # to keep the text confidential 
      # only suitable for encoded input that never ends with value 00h
      # (because of default zero padding)
      $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,
                                   $plaintext, MCRYPT_MODE_CBC, $iv);
  
      # prepend the IV for it to be available for decryption
      $ciphertext = $iv . $ciphertext;
  
      # encode the resulting cipher text so it can be represented by a string
      $ciphertext_base64 = base64_encode($ciphertext);
  
      //echo  $ciphertext_base64 . "&lt;br /&gt;";
  
      # === WARNING ===
  
      # Resulting cipher text has no integrity or authenticity added
      # and is not protected against padding oracle attacks.
  
      # --- DECRYPTION ---
  
      $ciphertext_dec = base64_decode($ciphertext_base64);
  
      # retrieves the IV, iv_size should be created using mcrypt_get_iv_size()
      $iv_dec = substr($ciphertext_dec, 0, $iv_size);
  
      # retrieves the cipher text (everything except the $iv_size in the front)
      $ciphertext_dec = substr($ciphertext_dec, $iv_size);
  
      # may remove 00h valued characters from end of plain text
      $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key,
                                      $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);
  
      //echo  $plaintext_dec . "&lt;br /&gt;";
  
      $enc_data = array();
  
      $enc_data['encrypted'] = $ciphertext_base64;
      $enc_data['decrypted'] = $plaintext_dec;
  
      return $enc_data;
  
  }
  </code></pre>
  
  <p>Here's the process</p>
  
  <pre><code>$a = array();
  
  $a['billing_address'] = array(
      'type' =&gt; $var_type1,
      'title' =&gt; $this-&gt;input-&gt;post('title'),
      'address' =&gt; $this-&gt;input-&gt;post('address1'),
      'address2' =&gt; $this-&gt;input-&gt;post('address2'),
      'barangay' =&gt; $billing_brgy_name,
      'city' =&gt; $billing_city_name,
      'country' =&gt; $this-&gt;input-&gt;post('country'),
      'state' =&gt; $this-&gt;input-&gt;post('state'),
      'zip_code' =&gt; $this-&gt;input-&gt;post('zipcode')
  );
  
  $a['shipping_address'] = array(
      'type2' =&gt; $var_type2,
      'title2' =&gt; $this-&gt;input-&gt;post('title'),
      'lastname2' =&gt; ucwords($this-&gt;input-&gt;post('lastname2')),
      'firstname2' =&gt; ucwords($this-&gt;input-&gt;post('firstname2')),
      'address1_2' =&gt; $this-&gt;input-&gt;post('address1_2'),
      'address2_2' =&gt; $this-&gt;input-&gt;post('address2_2'),
      'barangay2' =&gt; $shipping_brgy_name,
      'city2' =&gt; $shipping_city_name,
      'country2' =&gt; $this-&gt;input-&gt;post('country2'),
      'state2' =&gt; $this-&gt;input-&gt;post('state2'),
      'zip_code2' =&gt; $this-&gt;input-&gt;post('zipcode2'),
      'phone' =&gt; $this-&gt;input-&gt;post('tel2_1')
  );
  
  $account_info = array(
      'user_id' =&gt; NULL,
      'partner_id' =&gt; $this-&gt;input-&gt;post('partner_id'),
      'firstname' =&gt; ucwords($this-&gt;input-&gt;post('firstname')),
      'lastname' =&gt; ucwords($this-&gt;input-&gt;post('lastname')),
      'username' =&gt; strtolower($this-&gt;input-&gt;post('username')),
      'password' =&gt; $this-&gt;input-&gt;post('pass2'),
      'tel1' =&gt; $this-&gt;input-&gt;post('tel1'),
      'tel2' =&gt; $this-&gt;input-&gt;post('tel2'),
      'birthdate' =&gt; $timestamp,
      'gender' =&gt; $this-&gt;input-&gt;post('gender'),
      'status' =&gt; $this-&gt;input-&gt;post('status'),
      'addresses' =&gt; $a
  );
  
  $encode = json_encode($account_info);
  
  $enc = $this-&gt;encryption($encode);
  
  $i = $enc['decrypted'];
  
  echo $encode;
  print_r(json_decode($encode));
  echo $enc['encrypted']."&lt;br /&gt;";
  echo $enc['decrypted'];
  </code></pre>
  
  <p>Here's the sample output</p>
  
  <p>The normal data in JSON format</p>
  
  <pre><code>{"user_id":null,"partner_id":"werewr","firstname":"Eqwe","lastname":"Qweqw","username":"wewe123","password":"11111111","tel1":"ewr","tel2":"werwer","birthdate":1386691200,"gender":"M","status":"Separated","addresses":{"billing_address":{"type":"B","title":"Ms.","address":"sdfsdf","address2":"sdfsfd","barangay":"Magsaysay","city":"San Jose","country":"PH","state":"DIN","zip_code":"22"},"shipping_address":{"type2":"S","title2":"Ms.","lastname2":"12312","firstname2":"32132","address1_2":"sdfs","address2_2":"fsdfsd","barangay2":"San Roque","city2":"Pandi","country2":"PH","state2":"BUL","zip_code2":"2323","phone":"12313"}}}
  </code></pre>
  
  <p>The decoded data</p>
  
  <pre><code>stdClass Object
  (
      [user_id] =&gt; 
      [partner_id] =&gt; werewr
      [firstname] =&gt; Eqwe
      [lastname] =&gt; Qweqw
      [username] =&gt; wewe123
      [password] =&gt; 11111111
      [tel1] =&gt; ewr
      [tel2] =&gt; werwer
      [birthdate] =&gt; 1386691200
      [gender] =&gt; M
      [status] =&gt; Separated
      [addresses] =&gt; stdClass Object
          (
              [billing_address] =&gt; stdClass Object
                  (
                      [type] =&gt; B
                      [title] =&gt; Ms.
                      [address] =&gt; sdfsdf
                      [address2] =&gt; sdfsfd
                      [barangay] =&gt; Magsaysay
                      [city] =&gt; San Jose
                      [country] =&gt; PH
                      [state] =&gt; DIN
                      [zip_code] =&gt; 22
                  )
  
              [shipping_address] =&gt; stdClass Object
                  (
                      [type2] =&gt; S
                      [title2] =&gt; Ms.
                      [lastname2] =&gt; 12312
                      [firstname2] =&gt; 32132
                      [address1_2] =&gt; sdfs
                      [address2_2] =&gt; fsdfsd
                      [barangay2] =&gt; San Roque
                      [city2] =&gt; Pandi
                      [country2] =&gt; PH
                      [state2] =&gt; BUL
                      [zip_code2] =&gt; 2323
                      [phone] =&gt; 12313
                  )
  
          )
  
  )
  </code></pre>
  
  <p>The encrypted data</p>
  
  <pre><code>7cwUCHUeHy8VNJQ+U7e9oDO51REcf2Y6FANnsTSWOnXAvysfjTWxxg6fq/t9EnDcNNs5+m1QNMGdYNlgWmGhv3e+OEaSVPtvDcHiy/DrqpyPKBAvDqiPUEcrd3Lmu8iGZyiMhv/i+fBDxJI6EQ6WbH6o0N+1j9GC8qmZ5BSdq16TKwEEpzHh4NktNMzGLOMugYhD5yzfD+Uwx2H+VfEb9V4epq1xWqbDUP9DeVOFTP5f8FMkMTbamg20lcRvGSykk4NKhk0VVrpUxr556X99cxP9bhFi7unXhqukZghy/7ZDsTrYQGSGktdrCpdPlqlBNHGWuDp592LIwSCNFHwV2Fyg/10ZjVyHAKWW3I56AHaEwqRdJzbDdNSDttbvyq8VwuPruQv8xXOPMw/L66WJ3PAUxiAywcEyKKbKdo9vxD/RSQTQQti0v+9cw+QrBXpCSLh9K0TDk1MwQiboJWstD6ALzIZQff1Hzr9MRzdsk9zQyxsxJ0DP3n9c3Ks4eWRpEHN7N6m+4KhWPMFMPTIiSKWSJvW1MXRiXEDC+e8nVyOd0ICbBKqPzz/pwbmX4yzmAPxm2zSR7Mp+NwKCPrEijT9ofM7DN619NumA15J9egZ6UOf2ZMac5takgHnF7SIoKmnjOhj1QgdlGN/Emuph2/1rXLEr9+TJ79syqdxuxcTbNo/FhPdW/cdvR5H0Jj2d7wuZ6sXta5IJLpPM7MdgYVpPyOdm/4g2FB31E2dOF3wIZ/zaAlbkRxF9CUyUzIPC512Yk1mUK6o77RzYJlTfE/6x8OZJBOf7ycdz2Ap0gnVzXV4fryM6dxvLkwjI5LhN/CtDZ+3luDX9jGx9RqFUPQn6ronnplCQErHTp83WLnI=
  </code></pre>
  
  <p>The decrypted data</p>
  
  <pre><code>{"user_id":null,"partner_id":"werewr","firstname":"Eqwe","lastname":"Qweqw","username":"wewe123","password":"11111111","tel1":"ewr","tel2":"werwer","birthdate":1386691200,"gender":"M","status":"Separated","addresses":{"billing_address":{"type":"B","title":"Ms.","address":"sdfsdf","address2":"sdfsfd","barangay":"Magsaysay","city":"San Jose","country":"PH","state":"DIN","zip_code":"22"},"shipping_address":{"type2":"S","title2":"Ms.","lastname2":"12312","firstname2":"32132","address1_2":"sdfs","address2_2":"fsdfsd","barangay2":"San Roque","city2":"Pandi","country2":"PH","state2":"BUL","zip_code2":"2323","phone":"12313"}}}{
  </code></pre>
  
  <p>When I tried to display as an array it results to blank 'no data'. As you can see in my decrypted data there's an excess character of '{' that's why I can't get array form. I can't spot where my code goes wrong. Please help me guys thanks.</p>