【转载】Android移动端与PHP服务端对称加密解密的实现
原文出处:Encryption between Java/Android And PHP 转载请注明原出处,尊重作者的原创,谢谢。
在网上找了很多实现,绝大多数都是不可用的,即android端和PHP端对同一字符串加密生成不一样的密文。但这个版本经测试是可用的,android版本:4.0.4,PHP5。
PHP类实现
1 <? 2 class ApiCrypter 3 { 4 private $iv = 'fdsfds85435nfdfs'; #与JAVA实现类中的设置必须一致 5 private $key = '89432hjfsd891787'; #与JAVA实现类中的设置必须一致 6 7 public function __construct() { 8 } 9 10 public function encrypt($str) { 11 $str = $this->pkcs5_pad($str); 12 $iv = $this->iv; 13 $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv); 14 mcrypt_generic_init($td, $this->key, $iv); 15 $encrypted = mcrypt_generic($td, $str); 16 mcrypt_generic_deinit($td); 17 mcrypt_module_close($td); 18 return bin2hex($encrypted); 19 } 20 21 public function decrypt($code) { 22 $code = $this->hex2bin($code); 23 $iv = $this->iv; 24 $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv); 25 mcrypt_generic_init($td, $this->key, $iv); 26 $decrypted = mdecrypt_generic($td, $code); 27 mcrypt_generic_deinit($td); 28 mcrypt_module_close($td); 29 $ut = utf8_encode(trim($decrypted)); 30 return $this->pkcs5_unpad($ut); 31 } 32 33 protected function hex2bin($hexdata) { 34 $bindata = ''; 35 for ($i = 0; $i < strlen($hexdata); $i += 2) { 36 $bindata .= chr(hexdec(substr($hexdata, $i, 2))); 37 } 38 return $bindata; 39 } 40 41 protected function pkcs5_pad ($text) { 42 $blocksize = 16; 43 $pad = $blocksize - (strlen($text) % $blocksize); 44 return $text . str_repeat(chr($pad), $pad); 45 } 46 47 protected function pkcs5_unpad($text) { 48 $pad = ord($text{strlen($text)-1}); 49 if ($pad > strlen($text)) { 50 return false; 51 } 52 if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) { 53 return false; 54 } 55 return substr($text, 0, -1 * $pad); 56 } 57 } 58 ?>
JAVA类实现
1 package com.cwilldev.crypt; 2 3 import java.security.NoSuchAlgorithmException; 4 import javax.crypto.Cipher; 5 import javax.crypto.NoSuchPaddingException; 6 import javax.crypto.spec.IvParameterSpec; 7 import javax.crypto.spec.SecretKeySpec; 8 9 public class ApiCrypter { 10 11 private String iv = "fdsfds85435nfdfs"; //根据实际需要更改 12 private String secretkey = "89432hjfsd891787"; //根据实际需要更改 13 private IvParameterSpec ivspec; 14 private SecretKeySpec keyspec; 15 private Cipher cipher; 16 17 public ApiCrypter() 18 { 19 ivspec = new IvParameterSpec(iv.getBytes()); 20 keyspec = new SecretKeySpec(secretkey.getBytes(), "AES"); 21 22 try { 23 cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 24 } catch (NoSuchAlgorithmException e) { 25 e.printStackTrace(); 26 } catch (NoSuchPaddingException e) { 27 e.printStackTrace(); 28 } 29 } 30 31 public byte[] encrypt(String text) throws Exception 32 { 33 if(text == null || text.length() == 0) { 34 throw new Exception("Empty string"); 35 } 36 byte[] encrypted = null; 37 try { 38 cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); 39 encrypted = cipher.doFinal(text.getBytes("UTF-8")); 40 } 41 catch (Exception e) { 42 throw new Exception("[encrypt] " + e.getMessage()); 43 } 44 return encrypted; 45 } 46 47 public byte[] decrypt(String code) throws Exception 48 { 49 if(code == null || code.length() == 0) { 50 throw new Exception("Empty string"); 51 } 52 byte[] decrypted = null; 53 try { 54 cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); 55 decrypted = cipher.doFinal(hexToBytes(code)); 56 } 57 catch (Exception e) { 58 throw new Exception("[decrypt] " + e.getMessage()); 59 } 60 return decrypted; 61 } 62 63 public static String bytesToHex(byte[] data) 64 { 65 if (data==null) { 66 return null; 67 } 68 int len = data.length; 69 String str = ""; 70 for (int i=0; i<len; i++) { 71 if ((data[i]&0xFF)<16) { 72 str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF); 73 } 74 else { 75 str = str + java.lang.Integer.toHexString(data[i]&0xFF); 76 } 77 } 78 return str; 79 } 80 81 public static byte[] hexToBytes(String str) { 82 if (str==null) { 83 return null; 84 } 85 else if (str.length() < 2) { 86 return null; 87 } 88 else { 89 int len = str.length() / 2; 90 byte[] buffer = new byte[len]; 91 for (int i=0; i<len; i++) { 92 buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16); 93 } 94 return buffer; 95 } 96 } 97 98 }
PHP加密解密方法:
1 $original_text = 'test'; 2 $mdes = new ApiCrypterUtil(); 3 //加密 4 $encrypt_text = $mdes->encrypt($original_text); 5 $this->log($encrypt_text, LOG_DEBUG); 6 //解密 7 $this->log($mdes->decrypt($encrypt_text), LOG_DEBUG);
Java加密解密方法:
1 //加密: 2 ApiCrypter apiCrypter = new ApiCrypter(); 3 String originalText = "test"; 4 String encryptedText = ApiCrypter.bytesToHex(apiCrypter.encrypt(jsonParams.toString())); 5 //解密: 6 String res = new String(apiCrypter.decrypt(encryptedText), "UTF-8"); 7 String decryptedText = URLDecoder.decode(res, "UTF-8");