PHP's "walking micro channel data", and the decryption process of obtaining practical operation (key code)

Scenarios

In the development of the micro channel small program, we often need to be obtained from the micro-channel end of some processing to facilitate our program operation processing, such as "Get walking data from the micro channel side", "acquired phone number from the micro-channel side," and the like, and these data , taking into account security issues, usually related documents need to micro-channel, data acquisition, decryption, and then, in order for us to use! However, micro letter written document is really disappointing, so today, "walking data" to obtain decryption key to the code, simply talk!

Knowledge Point

Symmetric encryption: encryption and decryption using the same key, or the two may simply be another key encryption algorithm estimated (the number of micro-walking, using symmetric encryption is []). 
Asymmetric Encryption: also known as to open encryption, which requires a key pair, one public and one private, one for encryption and one for decryption. 
symmetric encryption on a better performance than asymmetric encryption, but less secure than asymmetric encryption.

Key Functions

A symmetric encryption function 
openssl_encrypt ($ data, $ method, $ key, $ options = 0, $ iv = ''): in targeting method and encryption key KEY Data, return false data or encryption. 
2, symmetric decryption function 
. openssl_decrypt ($ data, $ method , $ key, $ options = 0, $ iv = ''): decrypting the data 

parameter annotation 
$ data: plaintext 
$ method: encryption algorithm 
$ key: key 
$ Options: 
- 0: automatically plaintext padding, the data returned through the base64 encoded. 
-. 1: OPENSSL_RAW_DATA, automatically plaintext padding, but the results returned have not been base64 encoded. 
- 2: OPENSSL_ZERO_PADDING, automatically plaintext zero padding, the result returned through base64 encoding However, openssl is not recommended way to fill 0, even if this choice does not automatically padding, still need to manually padding. 
$ iv: initialization vector is non-empty, do not use this throws a warning if it is not carried out. manual filling, the encryption failed to return.

Other functions

1, openssl_cipher_iv_length ($ method): method gets the length of the required initialization vector. 
2, openssl_random_pseudo_bytes ($ length): generating a pseudorandom string of specified length. 
. 3, hash_mac ($ method, $ Data, Key $, $ raw_out) : generating the hash value with the private key. 
parameters annotation: 
- method: encryption algorithm 
- data: plaintext 
- key: key 
- raw_output: 
- TRUE: outputting raw binary data 
- FALSE: fixed length output lowercase hexadecimal characters. string

Encryption

Mainstream symmetric encryption methods are DES, AES. Both belong to encryption block cipher, the specific operation, the first plaintext block into a plurality of equal length, then encrypted. 
DES encryption 
DES encryption secret key is 64 bits (bit), but the actual application, the valid 56-bit (bit), the remaining 8 bits (bit) as a parity bit. If the secret key length is less than eight bytes (Byte, 1Byte = 8bit), 
it will be with "\ 0" added to 8 bytes, for example, the secret key is "ABCDE", full complement, is "abcde / 0/0 / 0 ", i.e.," ABCDE "encrypted cipher text" ABCDE / 0/0/0 "encrypted ciphertext is the same. 
64 in accordance with the plaintext (bit) packets 64 in the UTF-8 encoding of a length of 8 bytes, the last group is less than 64-bit data needs to be filled, and the group secret key plaintext grouped, bitwise (bit) replaced , or exchanged to form ciphertext group. 
AES encryption 
AES encryption of 128-bit packet length (bit), i.e., each packet is 16 bytes Byte (8 bits per byte bit). The length of the secret key, depending on the encryption method, and may be 128, 192, 256. As with DES encryption, the secret key, exceeds the specified length, beyond the will invalid, insufficient to "\ 0", adds the specified length. 
AES encryption table length
AEC Key length (bits) Packet length (bits)
AES-128 128 128
AES-192 192 128
AES-256 256 128

 

Code section

A Code : This part of the code responsible for receiving parameters, to avoid detecting some special cases, in preparation for subsequent decrypted data (encrypted data, returned by the front end, where the operation is not acquired)
/**
 * 每次进入小程序,把前端推送的走步数据,存入到【组成员表】
 */
public function save_member_steps()
{
    $request = $this->get;
    //$request['step_data'] = "M4OKIk0kX8Zmx5E/y0xfzyVD+wWgGhcLcd+7GrMyXSmhnXTljZxLqpkNB8Smut1nj440Amdrc3HlI/g5VqY";
    //$request['iv'] = "QUzF4rs6Khat27nZE8Px9w==";
    //$request['openid'] = "oqahZ5LbByVHYBrH5PldKoruXtPI";

    // 获取相关的参数,并判断
    $userid = isset($request['userid']) ? $request['userid'] : 0;
    if(!$userid){
        return $this->export->get_export($this->errors[506]['error_code'], $this->errors, []);
    }
    // 从微信获取步数
    $step_data_str = isset($request['step_data']) && !empty($request['step_data']) ? strval($request['step_data']) : '';
    if(!$step_data_str){
        return $this->export->get_export($this->errors[512]['error_code'], $this->errors, []);
    }
    // 获取步数微信端参数
    $iv = !empty($request['iv']) ? strval($request['iv']) : '';
    // 获取步数微信端参数
    $openid = !empty($request['openid']) ? strval($request['openid']) : '';
    $this->load->dao('active_step_dao');
    // 解密微信端获取步数数据
    $step_datas = $this->process_wx_step_data($openid, $iv, $step_data_str);
    // 步数数据更新到user_step_everyday_log表
    $update_everyday_log = $this->update_step_log_data($userid, $step_datas);
    return  $update_everyday_log ? true : false;
}

/**
 * 获取用户的走步数据,更新到成员表
 * @param $openid
 * @param $iv
 * @param $step_data_str
 * @return array
 */
public function process_wx_step_data($openid, $iv, $step_data_str)
{
    // 从微信记录里获取数据,比对一下,是否正确,如果不正确,更新【组成员步数】,团表里的总步数累加
    $this->load->service('user_wechat_service');
    $step_data = $this->user_wechat_service->auth_step_data($openid, $iv, $step_data_str, 1);
    $stepInfoList = [];
    if(isset($step_data['stepInfoList']) && !empty($step_data['stepInfoList'])){
        $stepInfoList = $step_data['stepInfoList'];
        foreach ($stepInfoList as $key=>$val) {
            $stepInfoList[$key]['time'] = date('Y-m-d', $val['timestamp']);
        }
        $stepInfoList = array_column($stepInfoList, null, 'time');
    }
    return $stepInfoList;
}
Code two data in this part of the code, the code connected user_wechat_service-> auth_step_data, is mainly responsible for the micro-channel data is decrypted, the decrypted return
/**
 * 获取微信端用户【走步】数据
 * @param $openid 用户小程序openid
 * @param $iv 小程序返回的iv字段
 * @param $step_data_str 小程序返回的走步加密字段
 * @param $plat_type 1 用户端  2 教练端
 * @return array
 */
public function auth_step_data($openid, $iv, $step_data_str, $plat_type)
{
    if (empty($openid) || empty($iv) || empty($step_data_str) || empty($plat_type)) {
        return [];
    }
    $decrypt_data = $this->_get_encrypted_data($openid, $step_data_str, $iv, $plat_type);
    return $decrypt_data;
}

/**
 * 对微信加密的数据进行解密
 * @param $openid
 * @param $encrypted_data
 * @param $iv
 * @return string
 */
private function _get_encrypted_data($openid, $encrypted_data, $iv, $plat_type)
{
    $result = '';
    if (empty($openid) || empty($encrypted_data) || empty($iv) || empty($plat_type)) {
        return $result;
    }
    $this->load->dao('user_wechat_dao');
    $user = $this->user_wechat_dao->get_userid($openid, $plat_type);
    if (empty($user)) {
        return $result;
    }
    $this->load->config('dict/wechat_config');
    $dict_name = $plat_type == self::PLAT_TYPE_USER ? 'dict_wechat_user' : 'dict_wechat_coach';
    $app_config = $this->config->item($dict_name);
    $result = $this->_decrypt_data($app_config['app_id'], $user['sessionkey'], $encrypted_data, $iv);
    return $result;
}

/**
 * 最终的步骤 - 解密数据
 * @param $appid
 * @param $session_key
 * @param $encrypted_data
 * @param $iv
 * @desc VALIDATE_LEN_NUM = 24 (长度限制)
 * @return mixed|string
 */
private function _decrypt_data($appid, $session_key, $encrypted_data, $iv)
{
    $result = '';
    if (strlen($session_key) != self::VALIDATE_LEN_NUM || strlen($iv) != self::VALIDATE_LEN_NUM) {
        return $result;
    }

    $aes_key = base64_decode(str_replace(' ','+',$session_key));
    $aes_iv = base64_decode(str_replace(' ','+',$iv));
    $aes_cipher = base64_decode(str_replace(' ','+',$encrypted_data));
    $data = openssl_decrypt($aes_cipher, "AES-128-CBC", $aes_key, 1, $aes_iv);
    $data = json_decode($data, TRUE);

    if (empty($data)) {
        return $result;
    }
    if (!isset($data['watermark']['appid']) || $data['watermark']['appid'] != $appid) {
        return $result;
    }
    return $data;
}

to sum up

    Decryption, the key portion of the micro-data, is that _decrypt_data method, where the characters of useless Alternatively, decoding, and the key part, using a decryption function openssl_decrypt () to decrypt the data, corresponding to the function is the encryption function openssl_encrypt ( ), Talia parameters are the same, namely, [plaintext, encryption algorithm, keys, operation type (0,1,2), a non-null initialization vector], decryption, encryption, to rely on them. Thus, micro-channel processing encrypted data, the key is "symmetric encryption" understanding and operating practices!
Published 59 original articles · won praise 2 · Views 5589

Guess you like

Origin blog.csdn.net/LDR1109/article/details/100932938