云服务器 199 / 年,新老同享,开发者力荐特惠渠道
阿里云推广

记录下公司内部接口对接加密验签技术方案

  • 内容
  • 评论
  • 相关
加密逻辑,先生成16位随机串每次都不一样,作为aes加密的key和iv,明文先经过aes加密(有填充物),作为msg,aes的秘钥以及iv经过公钥加密后为code,然后使用私钥对msg签名得到sign,然后把这三个参数传递给接口
解密逻辑,先通过公钥验证签名(传入密文msg和sign),在通过私钥把code解密出来得到aes的秘钥以及iv,然后把msg根据得到的aes的key和iv解密出来得到消息体文明(得到明文后去掉填充)。
        $rt['sta'] = "1";
        $rt['msg'] = "算你狠";
        $returnjson = json_encode($rt);
        $rt1=zs_clear2cipher($returnjson, $logname = '');
        print_r($rt1);

        $rt2=zs_cipher2clear($rt1['rs']['sign'], $rt1['rs']['code'], $rt1['rs']['msg']);
        print_r($rt2);
        die;


//真诚软件内部接口对接代替mcrypt_decrypt的方案wl@20230803
function zs_clear2cipher($json_str, $logname = '')
{
    //从配置文件读取rsa公钥和私钥,并且把一行的转化成多行的php能使用的格式
    $private_key = format_rsa_pri(config("zhensoft_api")['private_key']);
    $public_key = format_rsa_pub(config("zhensoft_api")['public_key']);

    //先转化成数组,然后把null转化成空字符串在转化为json字符串
    $arr = json_decode($json_str, 1);
    $cleanarr = null_filter($arr); //把null转化成空字符串
    $json_str = json_encode($cleanarr, JSON_UNESCAPED_UNICODE);

    //$content为原文,使用函数生成16位的随机串,作为aes的加密的key和iv
    $msg_cleartext = $json_str;
    $randstr = random(16);
    $iv = $randstr;
    $key = $randstr;

    //php低版本aes加密方式(已废弃)
    //$aes_msg_ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $msg_cleartext, MCRYPT_MODE_CBC, $iv);
    //$base64_aes_msg_ciphertext = base64_encode($aes_msg_ciphertext);
   
    //这段代码的作用是将字符串 $cleartext 进行填充,使其长度变为 16 的倍数。如果 $cleartext 的长度不是 16 的倍数,那么会使用空字符 \0 进行填充,直到长度满足要求。这是为了确保使用 AES 加密算法时,输入的数据长度符合要求,因为 AES 加密算法要求输入的数据长度必须是 16 的倍数。
    $str_padded = $msg_cleartext;
    if (strlen($str_padded) % 16) {
        $str_padded = str_pad($str_padded, strlen($str_padded) + 16 - strlen($str_padded) % 16, "\0");
    }
    $msg_cleartext = $str_padded;

    //使用aes对$cleartext进行aes加密然后base64得到$base64_aes_ciphertext
    //先进行上面的填充,然后再aes,无填充加密,php高版本aes加密方式openssl_encrypt代替mcrypt_encrypt
    $aes_msg_ciphertext = openssl_encrypt($msg_cleartext, 'AES-128-CBC', $key, OPENSSL_NO_PADDING, $iv);
    $base64_aes_msg_ciphertext = base64_encode($aes_msg_ciphertext);
   
    //测试代码
    //$aes_msg_ciphertext = openssl_encrypt($msg_cleartext, 'AES-128-CBC', $key, 1, $iv);
    //$base64_aes_msg_ciphertext = base64_encode($aes_msg_ciphertext);

    //使用公钥对key和iv加密然后再base64生成code,因为被加密串是16位,所以加密后的长度也是固定的。
    $pu_key = openssl_pkey_get_public($public_key); //这个函数可用来判断公钥是否是可用的
    openssl_public_encrypt($randstr, $pub_code_ciphertext, $pu_key); //公钥加密
    $base64_pub_code_ciphertext = base64_encode($pub_code_ciphertext);

    //使用私钥对加密后台的消息体进行签名,接口接受数据方需要先验证签名,判断加密消息体是否被篡改。
    $sign = sign($base64_aes_msg_ciphertext, $private_key);

    $data['msg'] = $base64_aes_msg_ciphertext;
    $data['sign'] = $sign;
    $data['code'] = $base64_pub_code_ciphertext;

    //记录日志
    logRes("明文:" . $json_str . "\r\n返回签名sign:" . $data['sign'] . "\r\n返回code:" . $data['code'] . "\r\n返回msg:" . $data['msg'], $logname);
    //返回参数
    $rt['sta'] = "1";
    $rt['msg'] = "ok";
    $rt['rs'] = $data;
    return $rt;
}


//真诚软件内部接口对接代替mcrypt_decrypt的方案wl@20230803
function zs_cipher2clear($resign, $recode, $remsg, $logname = '')
{
    //从配置文件读取rsa公钥和私钥,并且把一行的转化成多行的php能使用的格式
    $private_key = format_rsa_pri(config("zhensoft_api")['private_key']);
    $public_key = format_rsa_pub(config("zhensoft_api")['public_key']);

    $pri_key = openssl_pkey_get_private($private_key); //这个函数可用来判断私钥是否是可用的,可用返回资源id Resource id
    $pu_key = openssl_pkey_get_public($public_key); //这个函数可用来判断公钥是否是可用的
    //验证签名使用公钥
    $check_sign_flag = verity($remsg, $resign, $public_key);
    if (!$check_sign_flag) {
        $rt['sta'] = "0";
        $rt['msg'] = "签名验证失败!";
        return $rt;
    }

    //解密code拿到aes的iv和key
    openssl_private_decrypt(base64_decode($recode), $randstr, $pri_key); //私钥解密
    $key = $randstr;
    $iv = $randstr;

    //有了aes的key和iv在解密$remsg
    //$msg_cleartext = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key,  base64_decode($remsg), MCRYPT_MODE_CBC, $iv);
    $msg_cleartext = openssl_decrypt(base64_decode($remsg), 'aes-128-cbc', $key, OPENSSL_NO_PADDING, $iv);
    //过滤字符串中特殊字符
    $msg_cleartext = rtrim(rtrim($msg_cleartext, chr(0)), chr(7));
    //去掉最后大括号右侧的字符,填充物去掉,新增强逻辑20230802
    $msg_cleartext = removeRightCharactersAfterLastBracket($msg_cleartext);
    $msg_cleartext = str_replace(array("\r\n", "\r", "\n", "\0"), "", $msg_cleartext);
    //记录日志
    logRes("传入密文签名sign:" . $resign . "\r\n传入密文code:" . $recode . "\r\n传入密文msg:" . $remsg . "\r\n解析后的明文:" . $msg_cleartext, $logname = '');
    $rt['sta'] = "1";
    $rt['msg'] = "ok";
    $rt['rs'] = $msg_cleartext;
    return $rt;
}

本文标签:

版权声明:若无特殊注明,本文皆为《菜鸟站长》原创,转载请保留文章出处。

本文链接:记录下公司内部接口对接加密验签技术方案 - http://www.wlphp.com/?post=409

发表评论

电子邮件地址不会被公开。 必填项已用*标注