REST API数字签名实现疑难:API密钥格式与验证问题
带数字签名的REST API实现问题:密钥类型与验证困惑
我正在实现一个带数字签名的极简REST API,后端采用PHP开发,客户端使用Python。原本误以为核心逻辑是发送方用私钥通过HMAC对载荷签名,接收方用公钥验证,但落地实现时遇到了密钥相关的问题。
PHP端验证逻辑
public function verify_request(Request $request) { $method = $request->method(); $timestamp = $request->header("timestamp"); $public_key = $request->header("api-key"); $signature = $request->header("signature"); $url = $request->fullUrl(); $data = $method.$timestamp.$url; $result = openssl_verify($data, $signature, $public_key, OPENSSL_ALGO_SHA256); Logger::info("Result : ".$result); return $result; }
曾成功对接其他API的Python客户端代码
import requests import hashlib import hmac import time public_key = "" private_key = "" method = "GET" base_url = "https://testing-api.com" endpoint = "/private/test" url = base_url + endpoint timestamp = str(int(time.time())) signature_data = method + timestamp + url signature = hmac.new(private_key.encode("utf-8"), signature_data.encode("utf-8"), hashlib.sha256).hexdigest() headers = { "api-key": public_key, "timestamp": timestamp, "signature": signature, } response = requests.request(method, url, headers=headers) print(response)
遇到的密钥相关问题
1. RSA多行密钥的请求头报错
我生成的RSA密钥为多行格式:
public_key = """-----BEGIN PUBLIC KEY----- MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL7Jz6mHX1cau3wlc6QrGW+kcVHO0HPj iwUDxdM1B8KSLgkfle4+Snq6HhOp5VXdQXZkYF4u9ctWbx/sB2oiD1sCAwEAAQ== -----END PUBLIC KEY-----""" private_key = """-----BEGIN PRIVATE KEY----- MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAvsnPqYdfVxq7fCVz pCsZb6RxUc7Qc+OLBQPF0zUHwpIuCR+V7j5KeroeE6nlVd1BdmRgXi71y1ZvH+wH aiIPWwIDAQABAkAnxyvkzLS0FH7Cg4x4zgOfo0l9JQGRJ//0K7UzM/tKNZOy881O +qEDld7XMaUOmyGd/FxSskrJrzWTSqEZtQ8BAiEA7wsKUjGWFyTfuMkj/3/E0XI2 YYEaTRpROl4NN6FUttcCIQDMUnn7JDovxYlp17QhyOb41qc1I402QZ6zNiz33ytP HQIgA2rr/drZo4ESdcjia9++x6PTZTd8Ucfji2sW00nKNUcCIFo7Oh9Mml2qcMrL NYOOA2J0+RaggqYpSHqAPE+iwK+JAiB2YbMutRh5EDyTcI2ql/hYFLlAJVT/E1AN /ItM1KCQQQ== -----END PRIVATE KEY-----"""
将其放入请求头时触发错误:
requests.exceptions.InvalidHeader: Invalid return character or leading space in header: api-key
2. 短字符串密钥的PHP验证报错
其他API使用的是短字符串格式密钥:
public_key = "Tub3FH4CLjHezvRcSKdeE18a9VrtzL" private_key = "tBssW3InKRq09OMLkveyuZ65LDRokjVX8FXO0CL5VpdaV73NWayUvJSSAtCs"
但用这类密钥在我的PHP验证逻辑中会报错:
ErrorException: openssl_verify(): supplied key param cannot be coerced into a public key
核心问题
- 这类使用短字符串格式密钥的API,采用的是什么密钥类型?
- 为什么这类短字符串密钥无法被
openssl_verify识别为有效公钥?
补充说明
后来纠正了之前的误解:这类API并非使用非对称密钥(RSA),而是使用两个独立的对称密钥——一个作为api-key用于身份标识,另一个作为签名密钥,通过HMAC算法生成签名。
内容的提问来源于stack exchange,提问作者Arkaik
相关产品推荐
相关产品推荐

