背景
开发了一个短信验证码接口,为了防止被攻击,在接口层面上加了一个签名。
签名的算法是使用HmacSHA256加密,Base64编码。
加密字符串就以【手机号】+【随机数】的格式举例。
客户端有Android、iOS、H5-js、小程序,都需要进行验签。
secret秘钥随机生成一个
XnvmtittKmvelZSIlmewagwxkWiSNFPn
各平台代码实现逻辑
iOS
import CryptoKit
func generateSignature(data: String, key: String) -> String? {
let key = SymmetricKey(data: key.data(using: .utf8)!)
let signature = HMAC<SHA256>.authenticationCode(for: data.data(using: .utf8)!, using: key)
return Data(signature).base64EncodedString()
}
// 使用
let secret = "" // 后端提供
let data = mobile + nonce; // data是 手机号 + 随机数
if let signature = generateSignature(data: data, key: secret) {
print(signature)
}
Android
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public String generateSignature(String data, String secretKey) throws Exception {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
sha256_HMAC.init(secretKeySpec);
return Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(data.getBytes()));
}
// data是请求参数按照一定规则排序后拼接成的字符串
String secret = "" // 后端提供
String data = mobile + nonce; // data是 手机号 + 随机数
String signature = generateSignature(data, secret);
H5-js
async function generateSignature(data, secretKey) {
const encoder = new TextEncoder();
const keyData = encoder.encode(secretKey);
const dataToSign = encoder.encode(data);
const key = await window.crypto.subtle.importKey("raw", keyData, { name: "HMAC", hash: { name: "SHA-256" } }, true, ["sign"]);
const signature = await window.crypto.subtle.sign("HMAC", key, dataToSign);
return window.btoa(String.fromCharCode(...new Uint8Array(signature)));
}
// 使用示例
const secret = "" // 后端提供
const data = mobile + nonce; // data是 手机号 + 随机数
generateSignature(data, secret).then(signature => console.log(signature));
小程序
小程序需要在小程序后台,第三方服务,插件管理中搜索并添加【crypto】
参考:https://developers.weixin.qq.com/miniprogram/dev/framework/plugin/using.html
// 在app.json中添加
"plugins": {
"crypto": {
"version": "0.0.003",
"provider": "wxxxxxxxxxx" // 替换成自己插件的id
}
}
// 引入代码
const crypto = requirePlugin("crypto");
// 假设 data 是你要签名的数据,key 是你的密钥
const data = "data_to_sign";
const key = "secret_key";
// 生成 HMAC SHA256 签名
function generateSignature(data, key) {
let hmac256 = new crypto.HmacSHA256(data, key);
return hmac256.toString(crypto.Base64);
}
// 调用函数生成签名
generateSignature(data, key);