如何在PHP中复现OpenSSL SHA1签名及Base64编码的一致结果?
问题:PHP复现OpenSSL签名结果不一致
终端操作说明
执行以下两条命令可生成目标文件:
- 用私钥对
Register1.txt的SHA1哈希进行签名,输出二进制签名文件:
openssl dgst -sha1 -sign PrivateKey.pem -out Register1.sha1 Register1.txt
- 将二进制签名文件转为一行式Base64编码:
openssl enc -base64 -in Register1.sha1 -out Register1.b64 -A
当前PHP代码(无法得到正确结果)
$encrypt_method = "DES-EDE-ECB"; // PRIVATE KEY $private_key = openssl_pkey_get_private(file_get_contents('./hash_key/ChavePrivada.pem')); $private_key_details = openssl_pkey_get_details($private_key); // PRIVATE KEY $iv = substr(hash('sha1', $encrypt_method), 0, 16); $key = hash('sha1', $private_key_details['key']); // $encryptToken = openssl_encrypt($string, $encrypt_method, $key, OPENSSL_RAW_DATA, $iv); $encryptToken = openssl_encrypt($string, $encrypt_method, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);; $encryptToken = base64_encode($encryptToken);//STRING ENCRYPTED $decryptToken = openssl_decrypt(base64_decode($encryptToken), $encrypt_method, $key, OPENSSL_RAW_DATA, $iv);//STRING DECRYPTED $output = [ 'encryptToken' => $encryptToken, 'decryptToken' => $decryptToken, ]; return $output;
问题根源
你的PHP代码逻辑完全偏离了终端命令的操作:
- 终端做的是非对称签名(用私钥对哈希值进行签名),而PHP代码用的是对称加密(DES-EDE-ECB),两者完全不是同一类操作
- 错误地将私钥内容SHA1哈希后作为对称密钥使用,完全不符合签名的逻辑
- 引入了不必要的IV(ECB模式不需要IV)和零填充,这些和签名操作无关
正确的PHP实现代码
要复现终端命令的结果,直接使用PHP的openssl_sign函数即可,该函数会自动完成「计算哈希+私钥签名」的流程,和openssl dgst -sign的默认行为一致(PKCS#1 v1.5签名格式):
// 1. 读取私钥 $privateKey = file_get_contents('./hash_key/ChavePrivada.pem'); // 2. 读取要签名的文件内容(对应终端的Register1.txt) $content = file_get_contents('Register1.txt'); // 3. 生成二进制签名(对应终端的Register1.sha1) openssl_sign($content, $signature, $privateKey, OPENSSL_ALGO_SHA1); // 4. 转为一行式Base64编码(对应终端的openssl enc -base64 -A) $base64Signature = base64_encode($signature); // 输出结果,对应Register1.b64的内容 echo $base64Signature;
验证说明
你可以将PHP输出的Base64字符串保存为文件,然后用终端命令验证:
# 将Base64解码为二进制签名 echo "PHP输出的Base64字符串" | base64 -d > php_sign.sha1 # 用公钥验证两个签名是否一致 openssl dgst -sha1 -verify PublicKey.pem -signature Register1.sha1 Register1.txt openssl dgst -sha1 -verify PublicKey.pem -signature php_sign.sha1 Register1.txt
如果两条验证命令都输出Verified OK,说明PHP实现的结果和终端命令完全一致。
内容的提问来源于stack exchange,提问作者Edinho Rodrigues
相关产品推荐
相关产品推荐

