邮递员:使用 SHA256 和 RSA 的自定义签名请求
Postman: custom signing request with SHA256 and RSA
我写了一个接口,用 python 向内部音频 api 发出请求。每个 API 请求都需要使用 RSA SHA256 签名。
现在我想用 Postman 测试 API 的端点并使用预请求脚本功能。但我对 javascript 并不坚定。也许有人可以帮助我将以下 python 函数翻译成 Postman 脚本:
def sign_request(
request: httpx.Request, adp_token: str, private_key: str
) -> httpx.Request:
"""
Helper function who creates a signed requests for authentication.
:param request: The request to be signed
:param adp_token: the token is obtained after register as device
:param private_key: the rsa key obtained after register as device
:returns: The signed request
"""
method = request.method
path = request.url.path
query = request.url.query
body = request.content.decode("utf-8")
date = datetime.utcnow().isoformat("T") + "Z"
if query:
path += f"?{query}"
data = f"{method}\n{path}\n{date}\n{body}\n{adp_token}"
key = rsa.PrivateKey.load_pkcs1(private_key.encode())
cipher = rsa.pkcs1.sign(data.encode(), key, "SHA-256")
signed_encoded = base64.b64encode(cipher)
signed_header = {
"x-adp-token": adp_token,
"x-adp-alg": "SHA256withRSA:1.0",
"x-adp-signature": f"{signed_encoded.decode()}:{date}"
}
request.headers.update(signed_header)
return request
我找到了如何获取请求方法和 body。我可以使用 pm.request.url.getPathWithQuery()
获取路径和查询。要将 headers 添加到请求中,我使用 pm.request.headers.add
.
但我不知道如何获取等格式的日期时间、连接字符串和签署数据。
在 Postman 中执行此操作的问题是您只能使用 sandbox. So for this, you have crypto-js 中可用的那些包作为加密操作的唯一包助手。
var CryptoJS = require("crypto-js");
var moment = require("moment");
signRequest(pm.request, "yourAdpToken", "yourPrivateKey")
function signRequest(request, adpToken, privateKey) {
const method = request.method;
const path = request.url.getPathWithQuery();
const body = request.body.raw;
const date = moment.utc().format();
const data = `${method}\n${path}\n${date}\n${body}\n${adpToken}`
const hash = CryptoJS.HmacSHA256(data, privateKey);
const signedEncoded = CryptoJS.enc.Base64.stringify(hash);
pm.request.headers.add({
key: 'x-adp-token',
value: adpToken
});
pm.request.headers.add({
key: 'x-adp-alg',
value: 'SHA256withRSA:1.0'
});
pm.request.headers.add({
key: 'x-adp-signature',
value: `${CryptoJS.enc.Base64.parse(signedEncoded)}:${date}`
});
}
将以上内容添加到 Pre-request 脚本会将您想要的 headers 添加到请求中,如下所示:
您可能需要更改编码部分,检查encode options
我明白了 运行 pm lib。感谢您的帮助。
唯一的问题是从 env var 中获取包含换行符的私有证书会出现错误,这些代码 sig.init(privateKey);
。我不得不直接在预请求脚本中写入私有证书字符串。
这是我的脚本。
eval( pm.globals.get('pmlib_code') );
var CryptoJS = require("crypto-js");
var moment = require("moment");
const adpToken = pm.environment.get("adp-token")
// private-key loaded from env var doesn't work because of newlines in it; bugfix
const privateKey = pm.environment.get("private-key")
// use private-key in pre request script directly make use of newline correctly
const privateKey2 = "-----BEGIN RSA PRIVATE KEY-----\nMIIE...==\n-----END RSA PRIVATE KEY-----\n"
signRequest(pm.request, adpToken, privateKey);
function signRequest(request, adpToken, privateKey2) {
const method = request.method;
const path = request.url.getPathWithQuery();
const body = request.body || "";
const date = moment.utc().format();
const data = `${method}\n${path}\n${date}\n${body}\n${adpToken}`;
var sig = new pmlib.rs.KJUR.crypto.Signature({"alg": "SHA256withRSA"});
sig.init(privateKey);
var hash = sig.signString(data);
const signedEncoded = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(hash));
pm.request.headers.add({
key: 'x-adp-token',
value: adpToken
});
pm.request.headers.add({
key: 'x-adp-alg',
value: 'SHA256withRSA:1.0'
});
pm.request.headers.add({
key: 'x-adp-signature',
value: `${signedEncoded}:${date}`
});
}
更新:
现在可以从 env var 读取设备证书了。我不得不用 const privateKey = pm.environment.get("private-key").replace(/\n/g, "\n")
替换 const privateKey = pm.environment.get("private-key")
我写了一个接口,用 python 向内部音频 api 发出请求。每个 API 请求都需要使用 RSA SHA256 签名。
现在我想用 Postman 测试 API 的端点并使用预请求脚本功能。但我对 javascript 并不坚定。也许有人可以帮助我将以下 python 函数翻译成 Postman 脚本:
def sign_request(
request: httpx.Request, adp_token: str, private_key: str
) -> httpx.Request:
"""
Helper function who creates a signed requests for authentication.
:param request: The request to be signed
:param adp_token: the token is obtained after register as device
:param private_key: the rsa key obtained after register as device
:returns: The signed request
"""
method = request.method
path = request.url.path
query = request.url.query
body = request.content.decode("utf-8")
date = datetime.utcnow().isoformat("T") + "Z"
if query:
path += f"?{query}"
data = f"{method}\n{path}\n{date}\n{body}\n{adp_token}"
key = rsa.PrivateKey.load_pkcs1(private_key.encode())
cipher = rsa.pkcs1.sign(data.encode(), key, "SHA-256")
signed_encoded = base64.b64encode(cipher)
signed_header = {
"x-adp-token": adp_token,
"x-adp-alg": "SHA256withRSA:1.0",
"x-adp-signature": f"{signed_encoded.decode()}:{date}"
}
request.headers.update(signed_header)
return request
我找到了如何获取请求方法和 body。我可以使用 pm.request.url.getPathWithQuery()
获取路径和查询。要将 headers 添加到请求中,我使用 pm.request.headers.add
.
但我不知道如何获取等格式的日期时间、连接字符串和签署数据。
在 Postman 中执行此操作的问题是您只能使用 sandbox. So for this, you have crypto-js 中可用的那些包作为加密操作的唯一包助手。
var CryptoJS = require("crypto-js");
var moment = require("moment");
signRequest(pm.request, "yourAdpToken", "yourPrivateKey")
function signRequest(request, adpToken, privateKey) {
const method = request.method;
const path = request.url.getPathWithQuery();
const body = request.body.raw;
const date = moment.utc().format();
const data = `${method}\n${path}\n${date}\n${body}\n${adpToken}`
const hash = CryptoJS.HmacSHA256(data, privateKey);
const signedEncoded = CryptoJS.enc.Base64.stringify(hash);
pm.request.headers.add({
key: 'x-adp-token',
value: adpToken
});
pm.request.headers.add({
key: 'x-adp-alg',
value: 'SHA256withRSA:1.0'
});
pm.request.headers.add({
key: 'x-adp-signature',
value: `${CryptoJS.enc.Base64.parse(signedEncoded)}:${date}`
});
}
将以上内容添加到 Pre-request 脚本会将您想要的 headers 添加到请求中,如下所示:
您可能需要更改编码部分,检查encode options
我明白了 运行 pm lib。感谢您的帮助。
唯一的问题是从 env var 中获取包含换行符的私有证书会出现错误,这些代码 sig.init(privateKey);
。我不得不直接在预请求脚本中写入私有证书字符串。
这是我的脚本。
eval( pm.globals.get('pmlib_code') );
var CryptoJS = require("crypto-js");
var moment = require("moment");
const adpToken = pm.environment.get("adp-token")
// private-key loaded from env var doesn't work because of newlines in it; bugfix
const privateKey = pm.environment.get("private-key")
// use private-key in pre request script directly make use of newline correctly
const privateKey2 = "-----BEGIN RSA PRIVATE KEY-----\nMIIE...==\n-----END RSA PRIVATE KEY-----\n"
signRequest(pm.request, adpToken, privateKey);
function signRequest(request, adpToken, privateKey2) {
const method = request.method;
const path = request.url.getPathWithQuery();
const body = request.body || "";
const date = moment.utc().format();
const data = `${method}\n${path}\n${date}\n${body}\n${adpToken}`;
var sig = new pmlib.rs.KJUR.crypto.Signature({"alg": "SHA256withRSA"});
sig.init(privateKey);
var hash = sig.signString(data);
const signedEncoded = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(hash));
pm.request.headers.add({
key: 'x-adp-token',
value: adpToken
});
pm.request.headers.add({
key: 'x-adp-alg',
value: 'SHA256withRSA:1.0'
});
pm.request.headers.add({
key: 'x-adp-signature',
value: `${signedEncoded}:${date}`
});
}
更新:
现在可以从 env var 读取设备证书了。我不得不用 const privateKey = pm.environment.get("private-key").replace(/\n/g, "\n")
const privateKey = pm.environment.get("private-key")