签名验证
创思无界2024-11-07 12:30:52
当您通过上述步骤完成 签名 后,可通过如下方式验证签名内容是否正确。
请求地址
- 接口请求域名
https://chuangsi.model.svipc.cn
- 接口请求地址
/api/verify/signature
请求方式
POST
请求头
参考公共请求头部分即可
请求参数
{}
签名验证示例代码
const CryptoJS = require("crypto-js");
// ak和sk需要替换成自己的ak和sk
const ak = "ak_xxxxxx";
const sk = "sk_xxxxxx";
const host = "https://chuangsi.api.svipc.cn";
// 请求方法,必须大写
const method = "POST";
// 请求地址,必须以/开头
const url = "/api/verify/signature";
// 请求参数,需要转换为json字符串
const param = {};
// 请求参数转换为json字符串并进行 URL 编码。注意:待编码的字符串必须为 JSON 格式,并且json中的冒号、逗号前后不能有空格,否则可能导致签名错误。
const paramString = encodeURIComponent(JSON.stringify(param));
// 当前时间戳,单位毫秒
const timestamp = Date.now();
// 随机字符串,可根据业务需求自己生成,这里简单使用md5生成
const nonce = CryptoJS.MD5(Math.random().toString()).toString();
// 拼接待签名的字符串
const stringToSign = `${method}\n${url}\n${paramString}\n${timestamp}\n${nonce}`;
// 使用sk对stringToSign进行HmacSHA256加密
const hmac = CryptoJS.HmacSHA256(stringToSign, sk);
const signature = CryptoJS.enc.Hex.stringify(hmac);
const myHeaders = new Headers();
myHeaders.append("X-Timestamp", timestamp.toString());
myHeaders.append("X-Nonce", nonce);
myHeaders.append("Authorization", `${ak}:${signature}`);
myHeaders.append("Content-Type", "application/json");
const requestOptions = {
method: "POST",
headers: myHeaders,
body: JSON.stringify(param),
};
fetch(`${host}${url}`, requestOptions)
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.log("error", error));
import hashlib
import hmac
import json
import time
import random
import requests
from urllib.parse import quote
# ak、sk 需要替换成自己的
ak = "ak_xxxxxx"
sk = "sk_xxxxxx"
host = "https://chuangsi.api.svipc.cn"
# 请求方法,必须大写
method = "POST"
# 请求地址,必须以/开头
url = "/api/verify/signature"
# 请求参数,需要转换为json字符串
param = {}
# 请求参数转换为json字符串并进行 URL 编码 python 中的 json.dumps 默认使用 ascii 编码,需要指定 ensure_ascii=False,并且 separators=(',', ':') 可以去掉 json 字符串中的空格
param_string = quote(json.dumps(param,ensure_ascii=False,separators=(',', ':')))
# 当前时间戳,单位毫秒
timestamp = int(time.time() * 1000)
# 随机字符串
nonce = hashlib.md5(str(random.random()).encode('utf-8')).hexdigest()
# 拼接待签名的字符串
string_to_sign = f"{method}\n{url}\n{param_string}\n{timestamp}\n{nonce}"
# 使用sk对stringToSign进行HmacSHA256加密
signature = hmac.new(sk.encode('utf-8'), string_to_sign.encode('utf-8'), hashlib.sha256).hexdigest()
# 构建请求头
headers = {
"X-Timestamp": str(timestamp),
"X-Nonce": nonce,
"Authorization": f"{ak}:{signature}",
"Content-Type": "application/json"
}
# 请求体
body = json.dumps(param)
# 发送请求
try:
response = requests.post(f"{host}{url}", headers=headers, data=body)
response_data = response.json()
# 处理返回结果
print(response_data)
except requests.exceptions.RequestException as e:
print(f"Error during request: {e}")
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import com.google.gson.Gson;
public class ApiRequest {
public static void main(String[] args) {
// ak、sk 需要替换成自己的
String ak = "ak_xxxxxx";
String sk = "sk_xxxxxx";
String host = "https://chuangsi.api.svipc.cn";
// 请求方法,必须大写
String method = "POST";
// 请求地址,必须以/开头
String url = "/api/verify/signature";
// 请求参数,需要转换为json字符串
String param = new Gson().toJson(new RequestParam());
try {
// 请求参数转换为json字符串并进行 URL 编码
String paramString = URLEncoder.encode(param, StandardCharsets.UTF_8.toString());
// 当前时间戳,单位毫秒
long timestamp = System.currentTimeMillis();
// 随机字符串
String nonce = generateRandomString();
// 拼接待签名的字符串
String stringToSign = method + "\n" + url + "\n" + paramString + "\n" + timestamp + "\n" + nonce;
// 使用sk对stringToSign进行HmacSHA256加密
String signature = hmacSha256(stringToSign, sk);
// 构建请求头
HttpURLConnection connection = (HttpURLConnection) new URL(host + url).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("X-Timestamp", String.valueOf(timestamp));
connection.setRequestProperty("X-Nonce", nonce);
connection.setRequestProperty("Authorization", ak + ":" + signature);
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
// 发送请求体
try (OutputStream os = connection.getOutputStream()) {
byte[] input = param.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}
// 读取响应
try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
String response;
StringBuilder responseStr = new StringBuilder();
while ((response = br.readLine()) != null) {
responseStr.append(response);
}
System.out.println(responseStr.toString());
}
} catch (Exception e) {
System.out.println("Error during request: " + e.getMessage());
}
}
// 用于生成随机字符串
private static String generateRandomString() {
return String.format("%032x", new java.math.BigInteger(1, java.security.SecureRandom.getInstanceStrong().generateSeed(16)));
}
// HMAC SHA256 签名
private static String hmacSha256(String data, String key) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKeySpec);
byte[] rawHmac = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
return bytesToHex(rawHmac);
}
// 将字节数组转为十六进制字符串
private static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
hexString.append(String.format("%02x", b));
}
return hexString.toString();
}
// 请求参数类
static class RequestParam {
RequestParam() {
}
}
}
package main
import (
"bytes"
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"time"
)
// 请求参数结构体
type RequestParam struct {
}
func main() {
// ak、sk 需要替换成自己的
ak := "ak_xxxxxx"
sk := "sk_xxxxxx"
host := "https://chuangsi.api.svipc.cn"
// 请求方法,必须大写
method := "POST"
// 请求地址,必须以/开头
apiUrl := "/api/verify/signature"
// 请求参数
param := RequestParam{ }
// 请求参数转换为json字符串并进行 URL 编码
paramBytes, err := json.Marshal(param)
if err != nil {
fmt.Println("Error marshalling param:", err)
return
}
paramString := url.QueryEscape(string(paramBytes))
// 当前时间戳,单位毫秒
timestamp := time.Now().UnixMilli()
// 随机字符串
nonce := generateRandomString()
// 拼接待签名的字符串
stringToSign := fmt.Sprintf("%s\n%s\n%s\n%d\n%s", method, apiUrl, paramString, timestamp, nonce)
// 使用sk对stringToSign进行HmacSHA256加密
signature := hmacSha256(stringToSign, sk)
// 构建请求头
req, err := http.NewRequest(method, host+apiUrl, bytes.NewBuffer(paramBytes))
if err != nil {
fmt.Println("Error creating request:", err)
return
}
req.Header.Set("X-Timestamp", fmt.Sprintf("%d", timestamp))
req.Header.Set("X-Nonce", nonce)
req.Header.Set("Authorization", fmt.Sprintf("%s:%s", ak, signature))
req.Header.Set("Content-Type", "application/json")
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
return
}
defer resp.Body.Close()
// 读取响应
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response body:", err)
return
}
// 输出响应
fmt.Println(string(body))
}
// 生成随机字符串
func generateRandomString() string {
n := 32
b := make([]byte, n)
_, err := rand.Read(b)
if err != nil {
fmt.Println("Error generating random string:", err)
return ""
}
return hex.EncodeToString(b)
}
// HMAC SHA256 签名
func hmacSha256(data, key string) string {
h := hmac.New(sha256.New, []byte(key))
h.Write([]byte(data))
return hex.EncodeToString(h.Sum(nil))
}
#!/bin/bash
# ak、sk 需要替换成自己的
ak="ak_xxxxxx"
sk="sk_xxxxxx"
host="https://chuangsi.api.svipc.cn"
# 请求方法,必须大写
method="POST"
# 请求地址,必须以/开头
url="/api/verify/signature"
# 请求参数,转为 JSON 字符串
param="{}"
# 请求参数转换为 URL 编码
param_string=$(echo -n "$param" | jq -sRr @uri)
# 当前时间戳,单位毫秒
timestamp=$(($(date +%s) * 1000))
# 随机字符串
nonce=$(echo -n $(date +%s%N) | sha256sum | head -c 32)
# 拼接待签名的字符串
string_to_sign="${method}\n${url}\n${param_string}\n${timestamp}\n${nonce}"
# 使用 sk 对 string_to_sign 进行 HMAC SHA256 加密。
# 这里注意 echo -en $string_to_sign ,不要使用 echo -e $string_to_sign ,这样的参数会多一个换行符,导致签名错误
signature=$(echo -en $string_to_sign | openssl dgst -sha256 -hmac "$sk" | sed 's/^.* //')
# 构建请求头
headers=(
-H "X-Timestamp: $timestamp"
-H "X-Nonce: $nonce"
-H "Authorization: $ak:$signature"
-H "Content-Type: application/json"
)
# 发送请求
response=$(curl -X $method "$host$url" "${headers[@]}" -d "$param")
# 输出响应结果
echo "$response"
#include <iostream>
#include <string>
#include <ctime>
#include <random>
#include <sstream>
#include <iomanip>
#include <curl/curl.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
#include <nlohmann/json.hpp>
#include <curl/curl.h>
// 辅助函数:将字节数组转换为十六进制字符串
std::string to_hex(const unsigned char* data, size_t length) {
std::ostringstream hex_stream;
for (size_t i = 0; i < length; ++i) {
hex_stream << std::setw(2) << std::setfill('0') << std::hex << (int)data[i];
}
return hex_stream.str();
}
// 辅助函数:生成一个随机字符串 (nonce)
std::string generate_random_string() {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 15); // 生成 0x0 到 0xf 之间的随机数
std::stringstream ss;
for (int i = 0; i < 32; ++i) {
ss << std::hex << dis(gen); // 将每个随机数转为十六进制字符
}
return ss.str();
}
// 辅助函数:使用 HMAC-SHA256 算法进行加密
std::string hmac_sha256(const std::string& data, const std::string& key) {
unsigned char* result;
static unsigned char hmac_result[SHA256_DIGEST_LENGTH];
result = HMAC(EVP_sha256(), key.c_str(), key.length(), (unsigned char*)data.c_str(), data.length(), hmac_result, nullptr);
return to_hex(hmac_result, SHA256_DIGEST_LENGTH);
}
// 发送 API 请求的函数
void send_request(const std::string& ak, const std::string& sk) {
std::string host = "https://chuangsi.api.svipc.cn";
// 请求方法,必须大写
std::string method = "POST";
// 请求 URL,必须以 "/" 开头
std::string url = "/api/verify/signature";
// 创建 JSON 请求体
nlohmann::json param = {};
std::string param_string = param.dump(); // 将 JSON 对象序列化为字符串
// 当前时间戳(毫秒)
long long timestamp = std::time(nullptr) * 1000;
// 生成随机字符串(nonce)
std::string nonce = generate_random_string();
// 拼接待签名的字符串
std::string string_to_sign = method + "\n" + url + "\n" + param_string + "\n" + std::to_string(timestamp) + "\n" + nonce;
// 使用 HMAC-SHA256 算法生成签名
std::string signature = hmac_sha256(string_to_sign, sk);
// 准备请求头
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, ("X-Timestamp: " + std::to_string(timestamp)).c_str());
headers = curl_slist_append(headers, ("X-Nonce: " + nonce).c_str());
headers = curl_slist_append(headers, ("Authorization: " + ak + ":" + signature).c_str());
headers = curl_slist_append(headers, "Content-Type: application/json");
// 准备 CURL 请求
CURL* curl = curl_easy_init();
if (curl) {
std::string url_full = host + url;
// 设置 CURL 选项
curl_easy_setopt(curl, CURLOPT_URL, url_full.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, param_string.c_str());
// 执行请求
CURLcode res = curl_easy_perform(curl);
// 处理返回结果
if (res != CURLE_OK) {
std::cerr << "CURL 错误: " << curl_easy_strerror(res) << std::endl;
} else {
long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
std::cout << "响应码: " << http_code << std::endl;
}
// 清理
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
} else {
std::cerr << "CURL 初始化失败" << std::endl;
}
}
int main() {
// 需要的库:
// OpenSSL:用于进行 HMAC-SHA256 签名。
// nlohmann/json:用于处理 JSON 数据,C++ 中常用的 JSON 库。
// CURL:用于发送 HTTP 请求。
// ak、sk 需要替换成自己的值
std::string ak = "ak_xxxxxx";
std::string sk = "sk_xxxxxx";
// 发送请求
send_request(ak, sk);
return 0;
}