API 接口签名验签

目录

一、为什么需要 API 接口签名

二、API 接口签名验签实现机制


一、为什么需要 API 接口签名

       对外开放的 API 接口都会面临一些安全问题,例如伪装攻击、篡改攻击、重放攻击以及数据信息泄漏的风险。利用 API 接口签名能方便的防范这些安全问题和风险。在设计 API 接口签名时主要考虑以下几点:

  • 保证请求数据正确

       当请求中的某一个字段的值变化时,原有的签名结果就会发生变化。所以,只要参数发生变化,签名就要发生变化,否则请求将会是一个无效的请求。

  • 保证请求来源合法

       一般情况下,生成签名的算法都会成对出现一个 appKey 和一个 appSecret,根据 appKey 能识别出调用者身份;根据 appSecret 能识别出签名是否合法。

  • 识别接口的时效性

       一般情况下,签名和参数中会包含时间戳,这样服务端就可以验证客户端请求是否在有效时间内,从而避免接口被长时间的重复调用。

二、API 接口签名验签实现机制

  • 签名验签流程图

 

1 客户端向服务端申请 appKey,appSecret ,服务端下发 appKey,appSecret。

2 客户端集成 SDK 产生 sign,将 appKey,请求参数,时间戳,sign发送到服务端,服务端根据请求参数使用 SDK 中的签名规则生成签名来验证sign的合法性,之后返回结果。

  • 代码实现
//签名
public static Map<String, String> generateSign(String appKey, String appSecret, String url, String method) throws NoSuchAlgorithmException, InvalidKeyException {
        Map<String, String> headers = new HashMap<String, String>();
        SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT_STRING);
        df.setTimeZone(new SimpleTimeZone(0, TIME_ZONE));
        String timestamp = df.format(new Date());
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append(method.toUpperCase()).append(url).append(timestamp);
        String signature = sign(appSecret, stringToSign.toString());
        headers.put("signature", signature);
        headers.put("appKey", appKey);
        headers.put("timestamp", timestamp);
        return headers;
    }

//验证签名
public static String validateSign(String appSecret, String url, String method, String timestamp) throws NoSuchAlgorithmException, InvalidKeyException {
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append(method.toUpperCase()).append(url).append(timestamp);
        return sign(appSecret, stringToSign.toString());
    }

//签名和验签公用方法
private static String sign(String appSecret, String stringToSign)
            throws InvalidKeyException, NoSuchAlgorithmException {
        SecretKeySpec signingKey = new SecretKeySpec(appSecret.getBytes(CHARSET), "HmacSHA1");
        Mac mac = Mac.getInstance(ALGORITHM_HMAC_SHA1);
        mac.init(signingKey);
        byte[] data = mac.doFinal(stringToSign.getBytes(CHARSET));
        return Base64.getEncoder().encodeToString(data);
    }

参考文档:请求签名 - 短信服务 - 阿里云

  • 13
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在 OpenSSL 3.1.0 版本中,新增了对 SM2 签名验签的支持。以下是使用 C++ 在 OpenSSL 3.1.0 中实现 SM2 签名验签的示例代码: ```cpp #include <iostream> #include <cstring> #include <openssl/evp.h> #include <openssl/ec.h> #include <openssl/sm2.h> int main() { // 待签名数据 std::string data = "Hello, world!"; // 生成 SM2 密钥对 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr); EVP_PKEY *pkey = nullptr; EVP_PKEY_keygen_init(ctx); EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_sm2); EVP_PKEY_keygen(ctx, &pkey); // 计算数据摘要 unsigned char digest[32]; EVP_Digest((const unsigned char *)data.c_str(), data.length(), digest, nullptr, EVP_sm3(), nullptr); // 执行签名操作 EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); EVP_DigestSignInit(md_ctx, nullptr, EVP_sm3(), nullptr, pkey); size_t signature_len = 0; EVP_DigestSign(md_ctx, nullptr, 0, nullptr, &signature_len); unsigned char *signature = new unsigned char[signature_len]; EVP_DigestSign(md_ctx, signature, &signature_len, digest, sizeof(digest)); EVP_MD_CTX_free(md_ctx); // 打印签名结果 std::cout << "Signature: "; for (int i = 0; i < signature_len; i++) { printf("%02x", signature[i]); } std::cout << std::endl; // 执行验签操作 md_ctx = EVP_MD_CTX_new(); EVP_DigestVerifyInit(md_ctx, nullptr, EVP_sm3(), nullptr, pkey); int verify_result = EVP_DigestVerify(md_ctx, signature, signature_len, digest, sizeof(digest)); EVP_MD_CTX_free(md_ctx); // 打印验签结果 std::cout << "Verify result: " << verify_result << std::endl; // 释放内存 delete[] signature; EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); return 0; } ``` 在上述代码中,我们首先定义了待签名的数据 `data`,然后通过 OpenSSL 中提供的 API 生成了一个 SM2 密钥对 `pkey`,接着使用 `EVP_Digest` 函数计算了数据的摘要,然后使用 `EVP_DigestSign` 函数对摘要进行签名,并将签名结果打印输出。最后,我们使用 `EVP_DigestVerify` 函数对签名结果进行验证,并将验证结果打印输出。 需要注意的是,在 OpenSSL 3.1.0 中,SM2 签名验签API 并不是直接提供的,而是通过 EVP 接口进行的封装。此外,实际应用中还需要考虑一系列安全性问题,例如密钥管理、签名验证等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值