1、HMAC-SHA256 加密(不可逆无法解密)
假设:
appkey 为:testappkey
appsecret 为:testappsecret
当前时间戳为:1562912285
拼装原串为:testappkey1562912285testappsecret
则 HMAC-SHA256 加密后得到的值:559c4fa92e47b7f148a788300c6a345feddbd327b9fc551f100de679bbb247c5
$string = hash_hmac("sha256",'testappkey1562912285testappsecret','testappsecret'); // 559c4fa92e47b7f148a788300c6a345feddbd327b9fc551f100de679bbb247c5
2、AES(CipherMode.CBC PaddingMode.PKCS7)加密
假设:
appsecret 为:0688f7a191da4fbab177fd1c8ef19901
aesIV 为:ff465fdecc764337
加密前数据示例:{"settlement_code":["JS19BUB14F5D8D4C"],"random_code":["19BUB14F5D8D4C","19BUAD0E89D780"]}
则 加密后的值为(以下三个方法都一样):{"data":"236agZcupcSsMZghtlmzhb7lEWzGZc3FO5GWQyrSB5kP/y1ESvd+CuBgQiWU/fwAICY/s0mideku/rXSKEb8In41F4SkUVLyLzYoYGed4QTjsqohTM0T6wmbkOiT1TH3"}
$string = '{"settlement_code":["JS19BUB14F5D8D4C"],"random_code":["19BUB14F5D8D4C","19BUAD0E89D780"]}'; $aesIV = 'ff465fdecc764337'; $appsecret = '0688f7a191da4fbab177fd1c8ef19901'; $newText = openssl_encrypt($string,'AES-256-CBC',$appsecret,false,$aesIV); $newText = openssl_encrypt($string,'AES-256-CBC-HMAC-SHA1',$appsecret,false,$aesIV); $newText = openssl_encrypt($string,'AES-256-CBC-HMAC-SHA256',$appsecret,false,$aesIV);
若不知道使openssl_encrypt的第二个参数传什么方法,则可以使用以下方法再for循环逐个尝试
$method = openssl_get_cipher_methods();
3、AES(CipherMode.CBC PaddingMode.PKCS7)解密
$data = openssl_decrypt($newText,'AES-256-CBC',$appsecret,false,$aesIV);
得到的data即为加密前数据:{"settlement_code":["JS19BUB14F5D8D4C"],"random_code":["19BUB14F5D8D4C","19BUAD0E89D780"]}
4、舌诊的aes加密示例
$key = 'y82caGkvfRvjtRNngcpHzA=='; $age_sex['age'] = $age; $age_sex['sex'] = $sex; $encrypt_data = openssl_encrypt(json_encode($age_sex), 'aes-128-ecb', base64_decode($key), OPENSSL_RAW_DATA); $data['encryptData'] = base64_encode($encrypt_data);
5、舌诊的aes解密示例
$key = 'y82caGkvfRvjtRNngcpHzA=='; $encrypted = base64_decode($param['encryptData']); // $param['encryptData']为舌诊接口返回的待解密数据 $data = json_decode(openssl_decrypt($encrypted, 'aes-128-ecb', base64_decode($key), OPENSSL_RAW_DATA),true);
6、rsa签名(使用私钥生成签名)
/**********************************私钥格式化*************************************/ private function formatPriKey($priKey) { $fKey = "-----BEGIN PRIVATE KEY-----\n"; $len = strlen($priKey); for($i = 0; $i < $len; ) { $fKey = $fKey . substr($priKey, $i, 64) . "\n"; $i += 64; } $fKey .= "-----END PRIVATE KEY-----"; return $fKey; } /**********************************公钥格式化*************************************/ private function formatPubKey($pubKey) { $fKey = "-----BEGIN PUBLIC KEY-----\n"; $len = strlen($pubKey); for($i = 0; $i < $len; ) { $fKey = $fKey . substr($pubKey, $i, 64) . "\n"; $i += 64; } $fKey .= "-----END PUBLIC KEY-----"; return $fKey; } /** * 配置私钥 * openssl_pkey_get_private这个函数可用来判断私钥是否是可用的,可用,返回资源 * @return bool|resource */ private function getPrivateKey() { $original_private_key = $this->private_key; return openssl_pkey_get_private($original_private_key); } /** * 配置公钥 * openssl_pkey_get_public这个函数可用来判断私钥是否是可用的,可用,返回资源 * @return resource */ public function getPublicKey() { $original_public_key = $this->public_key; return openssl_pkey_get_public($original_public_key); }
/** * 生成签名 * @param string $signString 待签名字符串 * @return string base64结果值 * OPENSSL_ALGO_DSS1 * OPENSSL_ALGO_SHA1 * OPENSSL_ALGO_SHA224 * OPENSSL_ALGO_SHA256 * OPENSSL_ALGO_SHA384 * OPENSSL_ALGO_SHA512 * OPENSSL_ALGO_RMD160 * OPENSSL_ALGO_MD5 * OPENSSL_ALGO_MD4 * OPENSSL_ALGO_MD2 */ public function getSign($signString){ $signature = ''; $this->private_key = $this->formatPriKey(config('tongue.rsa_devprivate_key')); $this->private_key = $this->getPrivateKey(); openssl_sign($signString, $signature, $this->private_key,OPENSSL_ALGO_MD5); return base64_encode($signature); }
7、rsa签名验签(使用公钥验签)
/** * 校验签名 * @param string $sign 签名 * @param string $toSign 待签名字符串 * OPENSSL_ALGO_DSS1 * OPENSSL_ALGO_SHA1 * OPENSSL_ALGO_SHA224 * OPENSSL_ALGO_SHA256 * OPENSSL_ALGO_SHA384 * OPENSSL_ALGO_SHA512 * OPENSSL_ALGO_RMD160 * OPENSSL_ALGO_MD5 * OPENSSL_ALGO_MD4 * OPENSSL_ALGO_MD2 * @return bool */ function checkSign($sign,$toSign){ $re = $this->formatPubKey(config('tongue.rsa_companypublic_key')); $re = openssl_pkey_get_public($re); $result = openssl_verify($toSign, base64_decode($sign), $re,OPENSSL_ALGO_MD5); return $result === 1 ? true : false; }
8、JWT加密&签名验证(简单的PHP示例),详情可参考JWT官网:https://jwt.io
与jwt官网中的base64UrlEncode中对应的php的实现方法为
/** * base64UrlEncode https://jwt.io/ 中base64UrlEncode编码实现 * @param string $input 需要编码的字符串 * @return string */ private static function base64UrlEncode(string $input) { return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); }
与jwt官网中的base64UrlEncode中对应的php的实现方法为
/** * base64UrlEncode https://jwt.io/ 中base64UrlEncode解码实现 * @param string $input 需要解码的字符串 * @return bool|string */ private static function base64UrlDecode(string $input) { $remainder = strlen($input) % 4; if ($remainder) { $addlen = 4 - $remainder; $input .= str_repeat('=', $addlen); } return base64_decode(strtr($input, '-_', '+/')); }
$header,$payload,$secret 3个参数分别如下
$header['alg'] = 'HS256'; $header['typ'] = 'JWT'; $payload['sub'] = '1234567890'; $payload['name'] = 'John!~#423▼Doe'; $payload['iat'] = 1516239022; $secret = '123456';
jwt加密后的值为
$re = hash_hmac( 'sha256', $this->base64UrlEncode(json_encode($header,JSON_UNESCAPED_UNICODE)) . "." . $this->base64UrlEncode(json_encode($payload,JSON_UNESCAPED_UNICODE)), $secret, true );
打印后对比官网的值,一致
print_dump($this->base64UrlEncode(json_encode($header,JSON_UNESCAPED_UNICODE)) . "." . $this->base64UrlEncode(json_encode($payload,JSON_UNESCAPED_UNICODE)) . "." . $this->base64UrlEncode($re));die;
注意:若官网中勾选“secret base64 encoded”选项,表示官网中secret的值要填base64加密后的值(最好用base64UrlEncode方法加密的而不是用php的base64_encode加密的,即这里的private static function base64UrlEncode方法),即例如此php例子中$secret = '123456',则官网中若勾选“secret base64 encoded”后填入的值为'MTIzNDU2',加密的结果一致
另:jwt的其他加密方法入HS384等,均与此类似
9、js、c#与php公用的aes加密解密方式,详情可参考https://www.cnblogs.com/zjbky/p/6065829.html
先设置好key,iv,以及待加密的字符串str
$key = "zhimeikm "; $iv = "1234567812345678"; $str = '{"d":"211022151725","u":"klfjeioadnfg"}'; $str_padded = '{"d":"211022151725","u":"klfjeioadnfg"}';
因为使用OPENSSL_NO_PADDING方式,所以待加密的字符串为16个字,不够的话要填充零
if (strlen($str) % 16) { $str = str_pad($str,strlen($str) + 16 - strlen($str) % 16, "\0"); }
加密的结果为
$en_data = base64_encode(openssl_encrypt($str, "AES-256-CBC", $key, OPENSSL_NO_PADDING, $iv)); print_dump($en_data); print_dump(openssl_error_string());
解密时,需要注意去除填充的零(貌似不去除也没问题)
$de_data = openssl_decrypt(base64_decode($en_data), "AES-256-CBC", $key, OPENSSL_NO_PADDING, $iv); print_dump(rtrim($de_data)); // 一般情况下rtrim一下即可得到想要的结果,无需以下的chr(0),chr(7)截取 print_dump( rtrim( rtrim( $de_data,chr(0) ), chr(7) ) ); print_dump(openssl_error_string());