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
Post a Comment