RSA
RSA Signature Demo Code
- Java
- Python
- JS
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.management.RuntimeErrorException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
@Slf4j
public class CheckSign {
public static void main(String[] args) throws Exception {
//GET sign example
// String timestamp = "1684814440729";
// String queryString = "marginCoin=usdt&symbol=btcusdt"; // Need to be sorted in ascending alphabetical order by key
// String signContent = timestamp + "GET" + "/api/v2/spot/account/account?" + queryString;
// String sign = generate(signContent);
// log.info("sign:{}",sign);
//POST sign example
String timestamp = "1684814440729";
String preContent = timestamp + "POST" + "/api/v2/spot/trade/place-order";
String body = "{\"symbol\":\"btcusdt\",\"quantity\":\"8\",\"side\":\"buy\",\"price\":\"1\",\"orderType\":\"limit\",\"clientOid\":\"channel1233456\"}";
String signContent = preContent + body;
String sign = generate(signContent);
log.info("sign:{}",sign);
}
/**
*
* @param content: the string to be signed
* @return
*/
private String generate(String content) {
String privateKey = "-----BEGIN PRIVATE KEY-----\n" +
"xxxxxxxxxxxxxxxxxxxx9w0BAQEFAASCBKgwggSkAgEAAoIBAQD5C1iP01MC9fh5\n" +
"xxxxxxxxxxxxxxx9Tcqfz6HzoSg+zd8HVxKXRTXBwMDBfLxfQXobptz1tDlPUs+g\n" +
"xxxxxxxxxxxxxxxBaZ5qHxArBTimyNXX6WNL6hTw0MI238cGKiW0WvWd9v6Z6/LX\n" +
"xxxxxxxxxxxxxxxcO7EKGuvBrVIRl57FzvOPD5QKfhVxcHr63NfEViAEQfQH4IN2\n" +
"xxxxxxxxxxxxxxx4jILUP+LXvHN7ZMiWP9bouw3r4l6v0NJ4XyucSYJL9fJ81rsI\n" +
"xxxxxxxxxxxxxxx4RSsFZKFyurE1c8XiU2aZ2qq+6vjby0ncE4dKVu5x/iJZ4gsL\n" +
"xxxxxxxxxxxxxxxCggEAD6cF5uw6QGpjNo30emMd6aXKsUbpbyYvgQHUxPIxDFl2\n" +
"xxxxxxxxxxxxxxxJjhcYbJp9MrgkDfc/c23+HomKbXqIkcVMy2DvAu523q1SVTE0\n" +
"xxxxxxxxxxxxxxxs6BdIDWDWJRp8AAKTXba6jgOOrg/Xbwq25aOeyerNPHv/N3m3\n" +
"xxxxxxxxxxxxxxx2UdX7NkvV4qmRi8se47OXUT9aypzpvGbSukkqXuE4GtKGoybR\n" +
"xxxxxxxxxxxxxxxNshn2QJnRd3GN2UENDvZS3ZvSY6f/Cq7K/EAmrsstOdUB2Ihn\n" +
"xxxxxxxxxxxxxxx3ekuArWc54bDai0deKFl9KvI2oQKBgQD9ekRFMB6ueRCCeoyg\n" +
"xxxxxxxxxxxxxxxKL1xKhrg6mYh65hfQaxbihfOcrneFOoc3BgZwnbAZpF+hlq9J\n" +
"xxxxxxxxxxxxxxxF3PGj5vPln9/rd6/gcFFE9o7zZhI166PsmlxQ7/N0SCnlao7y\n" +
"xxxxxxxxxxxxxxxlNsTR+XZ88QKBgQD7hckVvGxIftcZsHChP8TFcDAn1IsaVbyt\n" +
"xxxxxxxxxxxxxxx8YPtFr9afiCJ4b2NqRe8gCpUCUi+urnoMMsqMxTUMopiLPh2S\n" +
"xxxxxxxxxxxxxxxWx06krbOOyXVZ8RtgYLMpMhFCsRyzovqe8/LZQfQKWfQGTAXS\n" +
"xxxxxxxxxxxxxxx7DMDYdbwOcFRYlOq1WEarExTCUoHdfZfIrc5jSKsmwynN14H3\n" +
"xxxxxxxxxxxxxxxKzO1vqU3Mfln7umC73/9FJgZQfOh7TRpW4saGduXAq4voDTiC\n" +
"xxxxxxxxxxxxxxxsozRAnfF/+8i+/TVjQaSVgetYPB63uXw4JoRzlq1zYQKBgQDJ\n" +
"xxxxxxxxxxxxxxxGaNBKhR9TypEFylDXreTbDaMtTzg3Mcwa/qyarGiL2Fl8AEh6\n" +
"xxxxxxxxxxxxxxxUFO6BBozpINt/5ZUN7NL7w92qi25qkAQt4sGi+QQOnHMGisak\n" +
"xxxxxxxxxxxxxxxzsXqDqiwF52M9bui5zthbWfkj4wKBgEFVT+jf235aihaS88Oj\n" +
"xxxxxxxxxxxxxxxHlYCIef7/a+gt7N1u9sEGlPspY3HuPamA39201BuItD9X83VR\n" +
"xxxxxxxxxxxxxxxZn1O8/l+ItSNUzQhX6T0cSdCo6KtmZLBQ6Zaw7r63GcdvSdR2\n" +
"xxxxxxxxxxxxxxxxxxxxxxx\n" +
"-----END PRIVATE KEY-----\n";
try {
String parsedPem = privateKey.replace("\n", "").trim();
parsedPem = parsedPem
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "");
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64Utils.decodeFromString(parsedPem));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey priKey = keyFactory.generatePrivate(priPKCS8);
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initSign(priKey);
signature.update(content.getBytes(StandardCharsets.UTF_8));
String sign = Base64Utils.encodeToString(signature.sign());
return sign;
} catch (Exception ex) {
throw new RuntimeException("create sign failed", ex);
}
}
}
import base64
import json
import time
import base64
from Crypto.Hash import SHA256
from Crypto.Signature import PKCS1_v1_5
from Crypto.PublicKey import RSA
def get_timestamp():
return int(time.time() * 1000)
def rsa_sign(message, private_key):
pri_key = RSA.importKey(private_key)
encoded_param = SHA256.new(bytes(message, encoding='utf-8'))
sign_str = PKCS1_v1_5.new(pri_key).sign(encoded_param)
return base64.b64encode(sign_str).decode()
def pre_hash(timestamp, method, request_path, body):
return str(timestamp) + str.upper(method) + request_path + body
def parse_params_to_str(params):
params = [(key, val) for key, val in params.items()]
params.sort(key=lambda x: x[0])
from urllib.parse import urlencode
url = '?' +urlencode(params);
if url == '?':
return ''
return url
if __name__ == '__main__':
private_key = '''-----BEGIN PRIVATE KEY-----
XXXXXXXXXXANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCdTR5gmwGH77wE
xxxxxxxxxxiw7fPXWhMh7gZwurQQ8M/I9/VA8lDjwwoGuuJ6enurdfwhpZxeZH
xxxxxxxxxxSEXVuxJv5hdpI9m6ydInK9SA8IbaF4yYWp0l4N2mA44MzadA7QZq
xxxxxxxxxxa5q/NZHFWCrCbW2lGAAWwrhQq9LceVIW75e213xtnps0pGlII7Ye
xxxxxxxxxxYNSxlCdLOiz1GvOeVSeiSZx31o/O+rj7tDFpSgZJEXRmtGRoJkJy
xxxxxxxxxxVSOcb1hCExg4osK6rBKnDjFjwQvwvNNZq0JG+CkfH8eHAa7gSK50
xxxxxxxxxxAAECggEAEvYk30hQGu7PH0stQX3UhlVsR6HXnRlvgIrmJe7F/VLO
xxxxxxxxxx/heYY1nsX8+mIyjmvEOayqPgdkEmXevVlcuQf38Zbduynr3vlRCX
xxxxxxxxxxSxFBODuu/EAZc3mm27C2wUV7w6SAy9g0g6Os97ehZsSGAwHl4aye
xxxxxxxxxxEh5Ptq4YAfCYiUO7j10pQ+DJKqN9N1eyjyw5eixEgCpudcbpCc9X
xxxxxxxxxxANX8/LwvokqgYBK1UIL6ear0dtKmeFU+KwrmkKZfXk8/Amr/O8Ot
xxxxxxxxxxzq3La149LMmNkUYxaMSV/KGTEV7ukQKBgQDQl/fA3mxXtQg2IjTB
xxxxxxxxxxECWcP7TQWJDb30vxOKeq1k9YPUfegZga5zlyV28PAZnb0m5x07+0
xxxxxxxxxxe9OhQxfkAY6AtJaiIqhCcw5ew8Go/Ja1ML0jZESWG1MWBJtCcFTm
xxxxxxxxxxe0adilYmyu7zwwKBgQDBDPJZgSj7YssPyRmo3bO0MjknfYBqXvwi
xxxxxxxxxxJ9Rc2WXGfEm3DEn7TO/Wv0t7Yqm6/sXg5HzriN/PHlaVtE6wlXe7
xxxxxxxxxx7KKWYqP812mASl6ydLX9QWozlOXjVhWMuSGqMWjut4J3P8jlkOJ6
xxxxxxxxxxgQCxwvAl8ubNj78hsuDWgsddKIMkwvKrfdsvXrMOYouAdLjZJvjs
xxxxxxxxxxs9km8g/479pYlOn+Iv/Z7Lqke8/HdOFASoQ9h1nSuujgEgXUwkg1
xxxxxxxxxx2BY3FPnGGh8iQma1pdkUVn35fAq/m7e/S+kP1JY6lPIx1QKBgQCS
xxxxxxxxxxpot+ceGt2bseSd8l4jqU3nDZ0oW8+4Qnnu9QFhN4Hn9wIjpAOGaU
xxxxxxxxxxVbior98JxMSDHsHmuXKPA8DishumGlqV+vxsIzLQD1Ge/dbqsERB
xxxxxxxxxxiyUNqjk5kcPQeHIyJk5qQaF21udoTQKBgDOMbtM0Nq7cd/SAHISR
xxxxxxxxxxLJW7DRJGxw3AEwxKG+nxNLeG7GsQDyPCvZSKwRpdpXRTh+6mzXqe
xxxxxxxxxxz8Cwo6tgyKRi6QPObQk00vbrKEBTihP30m81rwBPzjwj7iKXxWgA
DJoVsaqGOaIf4qXXXXXXXXXX
-----END PRIVATE KEY-----'''
timestamp = get_timestamp()
request_path = "/api/v2/mix/order/place-order"
# POST
params = {"symbol": "TRXUSDT", "marginCoin": "USDT", "price": 0.0555, "size": 551, "side": "buy", "orderType": "limit", "force": "normal"}
body = json.dumps(params)
sign = rsa_sign(pre_hash(timestamp, "POST", request_path, str(body)), private_key)
print(sign)
# GET
body = ""
request_path = "/api/v2/mix/account/account"
params = {"symbol": "TRXUSDT", "marginCoin": "USDT"}
request_path = request_path + parse_params_to_str(params) # Need to be sorted in ascending alphabetical order by key
sign = rsa_sign(pre_hash(timestamp, "GET", request_path, str(body)), private_key)
print(sign)
export function sign() {
const private_key = '-----BEGIN PRIVATE KEY-----\n' +
'XXXXXXXXXXANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCdTR5gmwGH77wE\n' +
'XXXXXXXXXXVhiw7fPXWhMh7gZwurQQ8M/I9/VA8lDjwwoGuuJ6enurdfwhpZxeZH\n' +
'XXXXXXXXXXLESEXVuxJv5hdpI9m6ydInK9SA8IbaF4yYWp0l4N2mA44MzadA7QZq\n' +
'XXXXXXXXXXeia5q/NZHFWCrCbW2lGAAWwrhQq9LceVIW75e213xtnps0pGlII7Ye\n' +
'XXXXXXXXXXX8YNSxlCdLOiz1GvOeVSeiSZx31o/O+rj7tDFpSgZJEXRmtGRoJkJy\n' +
'XXXXXXXXXXzCVSOcb1hCExg4osK6rBKnDjFjwQvwvNNZq0JG+CkfH8eHAa7gSK50\n' +
'XXXXXXXXXXMBAAECggEAEvYk30hQGu7PH0stQX3UhlVsR6HXnRlvgIrmJe7F/VLO\n' +
'XXXXXXXXXXtU/heYY1nsX8+mIyjmvEOayqPgdkEmXevVlcuQf38Zbduynr3vlRCX\n' +
'XXXXXXXXXXucSxFBODuu/EAZc3mm27C2wUV7w6SAy9g0g6Os97ehZsSGAwHl4aye\n' +
'XXXXXXXXXX10Eh5Ptq4YAfCYiUO7j10pQ+DJKqN9N1eyjyw5eixEgCpudcbpCc9X\n' +
'XXXXXXXXXXr0ANX8/LwvokqgYBK1UIL6ear0dtKmeFU+KwrmkKZfXk8/Amr/O8Ot\n' +
'XXXXXXXXXXKRzq3La149LMmNkUYxaMSV/KGTEV7ukQKBgQDQl/fA3mxXtQg2IjTB\n' +
'XXXXXXXXXXhaECWcP7TQWJDb30vxOKeq1k9YPUfegZga5zlyV28PAZnb0m5x07+0\n' +
'XXXXXXXXXXpje9OhQxfkAY6AtJaiIqhCcw5ew8Go/Ja1ML0jZESWG1MWBJtCcFTm\n' +
'XXXXXXXXXX1Ze0adilYmyu7zwwKBgQDBDPJZgSj7YssPyRmo3bO0MjknfYBqXvwi\n' +
'XXXXXXXXXX5BJ9Rc2WXGfEm3DEn7TO/Wv0t7Yqm6/sXg5HzriN/PHlaVtE6wlXe7\n' +
'XXXXXXXXXXKO7KKWYqP812mASl6ydLX9QWozlOXjVhWMuSGqMWjut4J3P8jlkOJ6\n' +
'XXXXXXXXXXKBgQCxwvAl8ubNj78hsuDWgsddKIMkwvKrfdsvXrMOYouAdLjZJvjs\n' +
'XXXXXXXXXXl3s9km8g/479pYlOn+Iv/Z7Lqke8/HdOFASoQ9h1nSuujgEgXUwkg1\n' +
'XXXXXXXXXX0k2BY3FPnGGh8iQma1pdkUVn35fAq/m7e/S+kP1JY6lPIx1QKBgQCS\n' +
'XXXXXXXXXXNmpot+ceGt2bseSd8l4jqU3nDZ0oW8+4Qnnu9QFhN4Hn9wIjpAOGaU\n' +
'XXXXXXXXXXh+Vbior98JxMSDHsHmuXKPA8DishumGlqV+vxsIzLQD1Ge/dbqsERB\n' +
'XXXXXXXXXXyfiyUNqjk5kcPQeHIyJk5qQaF21udoTQKBgDOMbtM0Nq7cd/SAHISR\n' +
'XXXXXXXXXXAjLJW7DRJGxw3AEwxKG+nxNLeG7GsQDyPCvZSKwRpdpXRTh+6mzXqe\n' +
'XXXXXXXXXXtez8Cwo6tgyKRi6QPObQk00vbrKEBTihP30m81rwBPzjwj7iKXxWgA\n' +
'XXXXXXXXXXIf4qXXXXXXXXXX\n' +
'-----END PRIVATE KEY-----\n'
const ts = Date.now();
const NodeRSA = require('node-rsa')
const pri_key = new NodeRSA(private_key)
//GET
const ts = Date.now();
const params = 'clientOid=123&coin=USDT&endTime=1659076670000&pageNo=1&pageSize=20&startTime=1659036670000' // Need to be sorted in ascending alphabetical order by key
const endpoint = '/api/v2/spot/wallet/withdrawal-records'
const method = "GET"
const pre_hash = String(ts) + method + endpoint + '?' + params
const sign = pri_key.sign(pre_hash, 'base64', 'UTF-8')
//POST
const endpoint_post = '/api/v2/spot/trade/unfilled-orders'
const params_post = '{"symbol": "BTCUSDT"}'
const method_post = "POST"
const pre_hash_post = String(ts) + method_post + endpoint_post + params_post
const sign_post = pri_key.sign(pre_hash_post, 'base64', 'UTF-8')
return sign
}