java - When is padding required for encryption? -


i asked question here why aes java decryption return characters? getting characters when decrypt encrypted data. comment user "ebbe m. pedersen" understand problem not using same padding mechanism in both php , android java code. changed java code to

java code

 public class encryption {      private string iv = "fedcba9876543210";//dummy iv (change it!)     private ivparameterspec ivspec;     private secretkeyspec keyspec;     private cipher cipher;      private string secretkey = "0123456789abcdef";//dummy secretkey (change it!)      public encryption()     {         ivspec = new ivparameterspec(iv.getbytes());          keyspec = new secretkeyspec(secretkey.getbytes(), "aes");          try         {             cipher = cipher.getinstance("aes/cbc/pkcs5padding");//"aes/cbc/nopadding"         }         catch (nosuchalgorithmexception e)         {             // todo auto-generated catch block             e.printstacktrace();         }         catch (nosuchpaddingexception e) {             // todo auto-generated catch block             e.printstacktrace();         }     }      public byte[] encrypt(string text) throws exception     {         if(text == null || text.length() == 0)             throw new exception("empty string");          byte[] encrypted = null;          try {             cipher.init(cipher.encrypt_mode, keyspec, ivspec);              encrypted = cipher.dofinal(padstring(text).getbytes());         } catch (exception e)         {             throw new exception("[encrypt] " + e.getmessage());         }          return encrypted;     }      public byte[] decrypt(string code) throws exception     {         if(code == null || code.length() == 0)             throw new exception("empty string");          byte[] decrypted = null;          try {             cipher.init(cipher.decrypt_mode, keyspec, ivspec);              decrypted = cipher.dofinal(hextobytes(code));         } catch (exception e)         {             throw new exception("[decrypt] " + e.getmessage());         }         return decrypted;     }        public static string bytestohex(byte[] data)     {         if (data==null)         {             return null;         }          int len = data.length;         string str = "";         (int i=0; i<len; i++) {             if ((data[i]&0xff)<16)                 str = str + "0" + java.lang.integer.tohexstring(data[i]&0xff);             else                 str = str + java.lang.integer.tohexstring(data[i]&0xff);         }         return str;     }       public static byte[] hextobytes(string str) {         if (str==null) {             return null;         } else if (str.length() < 2) {             return null;         } else {             int len = str.length() / 2;             byte[] buffer = new byte[len];             (int i=0; i<len; i++) {                 buffer[i] = (byte) integer.parseint(str.substring(i*2,i*2+2),16);             }             return buffer;         }     }        private static string padstring(string source)     {         char paddingchar = ' ';         int size = 16;         int x = source.length() % size;         int padlength = size - x;          (int = 0; < padlength; i++)         {             source += paddingchar;         }          return source;     } } 

then added same pkcs5padding functions php mcrypt class:

php mcrypt class

class mcrypt {     private $iv = 'fedcba9876543210'; #same in java     private $key = '0123456789abcdef'; #same in java   function mcrypt() { }  function encrypt($str) {      //$key = $this->hex2bin($key);     $iv = $this->iv;      $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);      mcrypt_generic_init($td, $this->key, $iv);     $encrypted = mcrypt_generic($td, $str);      mcrypt_generic_deinit($td);     mcrypt_module_close($td);      return bin2hex($encrypted); }  function decrypt($code) {     //$key = $this->hex2bin($key);     $code = $this->hex2bin($code);     $iv = $this->iv;      $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);      mcrypt_generic_init($td, $this->key, $iv);     $decrypted = mdecrypt_generic($td, $code);      mcrypt_generic_deinit($td);     mcrypt_module_close($td);      return utf8_encode(trim($decrypted)); }  protected function hex2bin($hexdata) {     $bindata = '';      ($i = 0; $i < strlen($hexdata); $i += 2) {         $bindata .= chr(hexdec(substr($hexdata, $i, 2)));     }      return $bindata; }  function pkcs5_pad ($text, $blocksize) {     $pad = $blocksize - (strlen($text) % $blocksize);     return $text . str_repeat(chr($pad), $pad); }  function pkcs5_unpad($text) {     $pad = ord($text{strlen($text)-1});     if ($pad > strlen($text)) return false;     if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;     return substr($text, 0, -1 * $pad); }} 

now current problem sending/receiving utf-8 characters, not how decode/encode utf-8 characters. when send arabic/persian words contain example more 3 or less 3 characters returns nothing. example: if send word "خوب" (which has 3 characters) "خوب" correct; if send مچکرم (which has 5 characters) nothing.

i found problem not using unpadding function after decrypting data in php code, fixed that:

php code

<?php $data =file_get_contents('php://input'); $block_size=mcrypt_get_block_size("rijndael-128",'cbc'); require_once "encryption.php"; $etool=new mcrypt(); $data =$etool->decrypt($data); $data=$etool->pkcs5_unpad($data);//  <------ using unpad function $data =json_decode($data, true);    $data=$data["request"]; $etool=new mcrypt(); $data=$etool->pkcs5_pad($data,$block_size); $data=$etool->encrypt($data); $array=array('data'=>$data); echo  json_encode($array); 

and here java code it

jsonobject j=new jsonobject(sb.tostring());//sb string builder result=j.get("data").tostring(); result= new string(etool.decrypt( result ),"utf-8"); result = new string(result.getbytes("iso-8859-1")); log.d("success remote ",result); 

now problem reversed!! can words containing more or less 3 persian/arabic characters, not words containing exactly 3 characters.

i think should check "does unpadding required?" how if so?

function pkcs5_pad ($text, $blocksize) {     $pad = $blocksize - (strlen($text) % $blocksize);     return $text . str_repeat(chr($pad), $pad); }  function pkcs5_unpad($text) {     $pad = ord($text{strlen($text)-1});     if ($pad > strlen($text)) return false;     if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;     return substr($text, 0, -1 * $pad); } 

this code using php's string functions, operate on raw binary default , ignores encoding.

blending decrypted messages through utf8_encode() doesn't make sense. function remaps iso-8559-1 codepoints (i.e. 0x00 through 0xff) utf-8 codepoints (i.e. 0x00 through 0x7f, 0xc280 through 0xc2bf , 0xc380 through 0xc3bf).

since php operates on raw binary default, don't need apply transformation @ all.

note: said by default. there's stupid feature in php called function overloading controlled mbstring.func_overload php.ini directive. if you're using feature, need rewrite every piece of cryptography code needs measure and/or slice strings not use strlen(), substr(), etc.

defuse security published , maintains secure authenticated encryption php library, contains replacements these functions resist function overloading.


security notice

first: your crypto code broken. in other words: not secure.

second: avoid ever using mcrypt if can it.

if need data encrypted on wire, use tls. trying reinvent wheel here lead disaster.

however, if (for example) need peer-to-peer encryption on top of tls (e.g. server never sees data), don't roll own. pick secure php cryptography library instead. if need 1 works cross-platform, use libsodium.


Comments

Popular posts from this blog

sublimetext3 - what keyboard shortcut is to comment/uncomment for this script tag in sublime -

dataset - MPAndroidchart returning no chart Data available -

post - imageshack API cURL -