签名算法 v1(将废弃)
签名算法 v1 (将废弃)
::: tip
Deprecated since 2023 March 01
To be terminated since 2024 March 01
:::
步骤
- 所有非空参数(包括path, query, body)以key value的JSON String按字典序排列作为签名的数据。
- 数据作SHA1摘要。
- 用RSA私钥进行签名运算。
- Base64编码结果。
sign= Sign( data, algo=sha1withRSA, key=privateKey)
构造需要签名的数据
需要签名的数据构造为JSON键值对
{
"key1"=value1, //int
"key2"="value2", //string
}
全局参数
下面列出的全局参数需要作为签名数据的一部分进行构造。值的数据类型与参数的数据类型相同。
- 使用POST/PUT/DELETE方法时,全局参数在
body
中。 - 使用GET方法时,全局参数在
query
中。
参数 | 示例 | 数据类型 | 描述 |
---|---|---|---|
timestamp | 1640917845984 | String | Epoc时间UTC0时间戳,单位为毫秒。服务器允许的最大时差为10分钟 |
nonce | 23 | Integer | 随机正整数 |
{"timestamp":1674197059220,nonce:13} //NOTE that nonce is Integer
路径参数
路径参数需要作为签名数据的一部分进行构造。值的数据类型与参数的数据类型相同。
//for example: /sims/{sim_id}/usage
{"sim_id":"892030318384848290"}
查询参数
查询参数需要作为签名数据的一部分进行构造。值的数据类型与参数的数据类型相同。
//for example: ?begin_from=2023-01&type=1
{"begin_from":"2023-01","type":1}
Body
The body json parameters should be included in the data as well
Body中的JSOM参数同样需要作为签名数据的一部分进行构造。值的数据类型与参数的数据类型相同。
数据结构
示例:
api:GET /sims/{sim_id}/usage
请求:GET https://api.linksfield.net/cube/v4/sims/89852002021102915651/usage?begin_from=2023-01&category=data&end_by=2023-01&period_type=2×tamp=1674197059220&nonce=128
参与签名计算的数据 (应用排序之后) :
{"begin_from":"2023-01","category_type":"data","end_by":"2023-01","nonce":128,"period_type":2,"sim_id":"89852002021102915651","timestamp":"1674197059220"}
注意:
- 签名数据是JSON格式
- 不应该有行分隔符,例如'\n', '\t'等。
- 全局参数
timestamp
数据类型为String
,nonce
数据类型为Integer
。
代码示例
Java
/**
*
* @param data json in lexicographic order
* incl. query parameters ?xxx=yyy
* incl. path_variable: sims/{sim_id}; zzz :sim_id value
* incl. body {"a":"va","b":"vb"}
* excl. “” or null
* {"a":"va","b":"vb","xxx":"yyy","sim_id":"zzz"}
* @param privateKey
* @return
* @throws Exception
*/
public static String sign(String data, String privateKey) throws Exception {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance("SHA1WithRSA");
signature.initSign(key);
signature.update(data.getBytes());
return new String(Base64.getEncoder().encode(signature.sign()));
}
Python
# Author:luoyang
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA
from Crypto.Signature import PKCS1_v1_5 as Sig_pk
import base64
import os
import json
#
def get_sign(data):
"""
sign
"""
path = os.path.dirname(os.path.abspath(__file__))
doc = os.path.join(path, 'private.pem')
with open(doc) as pk:
key_data = pk.read()
# private key
rsakey = RSA.importKey(key_data)
# sha
print("data:", data)
en_data = SHA.new(data.encode())
# sign
sig_pk = Sig_pk.new(rsakey)
sign = sig_pk.sign(en_data)
# base64
result = base64.b64encode(sign)
# result
data = result.decode()
print("decode-sign:", data)
return data
# format
def format_data(data):
return data.replace(' ','')
#
if __name__ =='__main__':
data ={
"title":"4.0",
"timestamp":"1493893971",
"query_type":"imei",
"value":"12345"
}
sx_data = json.dumps(data, sort_keys=True, ensure_ascii=False)
fdata = format_data(sx_data)
get_sign(fdata)
JavaScript
postman, apifox
//TODO might not accomodate nested json object..!!
paramsString = JSON.stringify(params, Object.keys(params).sort());
console.log("sorted string to sign:", paramsString);
//get key
var rsa = require('jsrsasign');
var pem = privateKey;
try {
var keyhex = rsa.pemtohex(pem, "RSA PRIVATE KEY");
var rsakey = rsa.KEYUTIL.getKeyFromPlainPrivatePKCS8Hex(keyhex);
} catch (e) {
console.log("key error:", e);
}
var sig = new rsa.KJUR.crypto.Signature({ "alg": "SHA1withRSA" });
sig.init(rsakey);
sig.updateString(paramsString);
try {
var sign = sig.sign();
sign = rsa.hextob64(sign);
//token
var token = "LF " + accessKeyId + "/" + sign;
pm.environment.set("lfToken", token);
} catch (e) {
console.log("sign error:", e);
}
最后修改时间: 1 年前