最近公司有個業務,須要對接第三方接口,可是參數是須要加密的,對方也只提供了一個java的demo,在網上處處搜索,沒有找到直接就能用的方法,後來仍是跟公司的Android工程師對接出來的,在這裏記錄一下大體的流程。
首先說明一下對方要求的接口請求方式,格式爲:http://ip:port/interface/method?data=摘要@@16進制字符串
說明:php
1. 請求參數須要組合成a=1&b=2&c=3格式的參數串; 2. 摘要的生成方法爲md5('a=1&b=2&c=3'); 3. 16進制字符串的生成方法是將參數串進行**對稱加密(DES-ECB)**後再轉成16進制字符串(bin2hex函數);
對方提供的demo(java版本)以下:java
public class DesUtils { /** 默認密鑰 */ private static String strDefaultKey = "seeyonssokey"; /** 加密工具 */ private Cipher encryptCipher; /** 解密工具 */ private Cipher decryptCipher; /** * 加密字符串 * @param strIn 需加密的字符串 * @return 加密後的字符串 * @throws Exception */ public String encrypt(String strIn) throws Exception { return byteArr2HexStr(encryptCipher.doFinal(strIn.getBytes())); } /** * 解密字符串 * @param strIn 需解密的字符串 * @return 解密後的字符串 * @throws Exception */ public String decrypt(String strIn) throws Exception { return new String(decryptCipher.doFinal(hexStr2ByteArr(strIn))); } /** * 將 byte 數組轉換爲表示 16 進制值的字符串, 如: byte[]{8,18} 轉換爲: 0813 , 和 public static * byte[] hexStr2ByteArr(String strIn) 互爲可逆的轉換過程 * @param arrB 須要轉換的 byte 數組 * @return 轉換後的字符串 * @throws Exception 本方法不處理任何異常,全部異常所有拋出 */ public static String byteArr2HexStr(byte[] arrB) throws Exception { int iLen = arrB.length; // 每一個byte用兩個字符才能表示,因此字符串的長度是數組長度的兩倍 StringBuffer sb = new StringBuffer(iLen * 2); for(int i = 0; i < iLen; i++) { int intTmp = arrB[i]; // 把負數轉換爲正數 while(intTmp < 0) { intTmp = intTmp + 256; } // 小於0F的數須要在前面補0 if(intTmp < 16) { sb.append("0"); } sb.append(Integer.toString(intTmp, 16)); } return sb.toString(); } /** * 將 表 示 16 進 制 值 的 字 符 串 轉 換 爲 byte 數 組 , 和 public static String * byteArr2HexStr(byte[] arrB) 互爲可逆的轉換過程 * @param strIn 須要轉換的字符串 * @return 轉換後的 byte 數組 * @throws Exception 本方法不處理任何異常,全部異常所有拋出 * @author <a href="mailto:leo841001@163.com">LiGuoQing</a> */ public static byte[] hexStr2ByteArr(String strIn) throws Exception { byte[] arrB = strIn.getBytes(); int iLen = arrB.length; // 兩個字符表示一個字節,因此字節數組長度是字符串長度除以2 byte[] arrOut = new byte[iLen / 2]; for(int i = 0; i < iLen; i = i + 2) { String strTmp = new String(arrB, i, 2); arrOut[i / 2] = (byte)Integer.parseInt(strTmp, 16); } return arrOut; } /** * 從指定字符串生成密鑰,密鑰所需的字節數組長度爲 8 位 不足 8 位時後面補 0 , 超出 8 位只取前 8 位 * @param arrBTmp 構成該字符串的字節數組 * @return 生成的密鑰 * @throws java.lang.Exception */ private static Key getKey(byte[] arrBTmp) throws Exception { // 建立一個空的8位字節數組(默認值爲0) byte[] arrB = new byte[8]; // 將原始字節數組轉換爲8位 for(int i = 0; i < arrBTmp.length && i < arrB.length; i++) { arrB[i] = arrBTmp[i]; } // 生成密鑰 Key key = new SecretKeySpec(arrB, "DES"); return key; } public static String encrypt(String strIn, String secretkey) throws Exception { Key key = getKey(secretkey.getBytes("utf-8")); Cipher cipher = Cipher.getInstance("DES"); cipher.init(Cipher.ENCRYPT_MODE, key); return byteArr2HexStr(cipher.doFinal(strIn.getBytes("utf-8"))); } public static String decrypt(String strIn, String secretkey) throws Exception { Key key = getKey(secretkey.getBytes("utf-8")); Cipher cipher = Cipher.getInstance("DES"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] param = cipher.doFinal(hexStr2ByteArr(strIn)); return new String(param, "utf-8"); } }
PHP實現加密功能的的方法有兩種:算法
<?php $text = 'a=1&b=2&c=3'; //參數串 $key = 'abcd1234'; // 密鑰 echo $ret = self::encryptForDES($text , $key); //加密 /** * 字符串加密(加密方法:DES-ECB) * @param string $input 待加密字符串 * @param string $key 對稱加密密鑰 * @return string */ function encryptData($input, $key) { $size = mcrypt_get_block_size('des','ecb'); // 計算加密算法的分組大小 $input = self::pkcs5_pad($input, $size); // 對字符串進行補碼 $td = mcrypt_module_open('des', '', 'ecb', ''); $iv = @mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND); @mcrypt_generic_init($td, $key, $iv); $data = mcrypt_generic($td, $input); mcrypt_generic_deinit($td); mcrypt_module_close($td); $data = bin2hex($data); // 將加密後的字符串轉化爲16進制 return $data; } /** - 對字符串進行補碼 - @param string $text 原字符串 - @param string $blockSize 加密算法的分組大小 - @return string */ function pkcs5_pad($text, $blockSize) { $pad = $blockSize - (strlen($text) % $blockSize); return $text . str_repeat(chr($pad), $pad); }
輸出爲:990389f0aad8d12014ca6a45cd72cdf7數組
<?php $text = 'a=1&b=2&c=3'; // 參數串 $key = 'abcd1234'; // 密鑰 echo encryptData($text, $key); // 加密 /** * 字符串加密(加密方法:DES-ECB) * @param string $input 待加密字符串 * @param string $key 對稱加密密鑰 * @return string */ function encryptData($input, $key) { $ivlen = openssl_cipher_iv_length('DES-ECB'); // 獲取密碼iv長度 $iv = openssl_random_pseudo_bytes($ivlen); // 生成一個僞隨機字節串 $data = openssl_encrypt($input, 'DES-ECB', $key, $options=OPENSSL_RAW_DATA, $iv); // 加密 return bin2hex($data); }
輸出爲:990389f0aad8d12014ca6a45cd72cdf7php7