PHP菜鸟博客_共同学习分享PHP技术心得【PHP爱好者】
记录下公司内部接口对接加密验签技术方案
2023-8-3 菜鸟站长
加密逻辑,先生成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;
}

发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容