Signature v1 (Deprecated)
Signature v1 (Deprecated)
::: tip
Deprecated since 2023 March 01
To be terminated since 2024 March 01
:::
Process
- All non-empty parameters (including path, query, and body) are to be rearranged in lexicographic order as the data to be signed. Convert to JSON string.
- Data is digested by SHA1 first
- Sign using RSA private key
- Base64 encode the result
sign= Sign( data, algo=sha1withRSA, key=privateKey)
Construct the data to be signed
Data is to be constructed as JSON key-value:
{
"key1"=value1, //int
"key2"="value2", //string
}
Global Parameters
Global parameters listed below are required to be constructed as part of the data. Value's data type is the same as the parameter's data type.
- For the POST/PUT/DELETE method, the global parameters are in the
body
- For GET method, the global parameters are present in
query
string
Parameter | Example | Data Type | Description |
---|---|---|---|
timestamp | 1640917845984 | String | Epoc time UTC0 timestamp in millisecond. Maximum time difference allowed by the server is 10 minutes. |
nonce | 23 | Integer | Random positive integer |
{"timestamp":1674197059220,nonce:13} //NOTE that nonce is Integer
Path Parameters
Path parameters are required to be part of the data. Value's data type is the same as the parameter's data type.
//for example: /sims/{sim_id}/usage
{"sim_id":"892030318384848290"}
Query Parameters
Likewise,
//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
The data structure
Example:
api:GET /sims/{sim_id}/usage
request: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
The data to be signed (after applying ordering) in JSON:
{"begin_from":"2023-01","category_type":"data","end_by":"2023-01","nonce":128,"period_type":2,"sim_id":"89852002021102915651","timestamp":"1674197059220"}
Notes:
- Data is in JSON format
- There should be NO line separators, such as
\n
,\t
etc. - Global parameter
timestamp
isString
type andnonce
isInteger
type
The coding examples
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);
}