NAV
go php js java

Welcome to CipherBC API

Preparing for API

1 Register APP_ID

Contact customer service to register for APP_ID,and provide relevant qualification information. Example:Company Name,domain name,IP, first person in charge and other business information needed。

2 Provide a list of main chains and contract currencies that needs to be supported.

Coin require basic information such as coin address、main chain、precision、name and other relevant information will be provided to business coordinator.

3 Debugging API test environment

API adopting RSA2048bit for two-way signature verification to ensures the credibility of communication. Merchants are required to give the public key to the platform, where platform uses it to verify request parameters sent to the platform. Merchants need to obtain the platform public key in advance, which can be used to verify platform response.

Supported Coin

Coin Name Full name Blockchain Explorer
btc btc https://blockchair.com/bitcoin
eth eth https://etherscan.io
bnb_bsc BSC(BNB Smart Chain) https://bscscan.com
qtum qtum https://explorer.qtum.org
trx Tron https://tronscan.io
a Vaulta(Upgraded from the EOS) https://vaultascan.io/
xrp xrp https://xrpscan.com
doge doge https://dogechain.info
ltc ltc https://litecoinblockexplorer.net
dash dash https://dashblockexplorer.com
dcr dcr https://dcrdata.decred.org
bch Bitcoin Cash https://blockchair.com/bitcoin-cash
fil fil https://filscan.io
sol solana https://explorer.solana.com
pol Polygon https://polygonscan.com
avax_c avax c chain https://snowtrace.io
avax_x X chain of avax https://explorer-xp.avax.network
lunc lunc https://finder.terra.money/classic
bsv Bitcoin SV https://www.bitcoinsv.io
atom atom https://www.mintscan.io/injective
eth_optimism optimism https://optimistic.etherscan.io
eth_arbitrum arbitrum https://arbiscan.io
ada cardano https://cardanoscan.io
core core https://scan.coredao.org
eth_zksync ZKsync Era https://explorer.zksync.io
algo Algorand https://algoexplorer.io
sui Sui https://suiexplorer.com
eth_base Base https://basescan.org
ton Toncoin https://tonviewer.com
smart smart https://smartexplorer.com
tfuel_theta TFuel on Theta https://www.thetascan.io
kas Kaspa https://explorer.kaspa.org
assethub_dot AssetHub Polkadot https://assethub-polkadot.subscan.io
apt aptos https://explorer.aptoslabs.com
dag dag https://mainnet.dagexplorer.io
eth_deriw Deriw https://explorer.deriw.com/
hype Hyperliquid https://app.hyperliquid.xyz/explorer
main_bnb opBNB https://opbnbscan.com/
mnt Mantle https://mantlescan.xyz/
s Sonic https://sonicscan.org/

Signature Regulations

<?php

$obj = new obj(); $obj->coin_list();

class obj { public $baseUrl = 'http://api.xxxxx.com/shopapi'; public $priKey = "-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8d6RGCeQkrobx +4xO1jXnHwiMU48UyOaRaNW2FMQrN9DcK/T2h58FyuA7kYN0CVNFEnaZQS9S8Nur Tl0lOVJcbwKfCSnu9nmFYDvPWqlCTqQW3F83sKNi9IWrMFFny3CX35eUHpeJahE2 R9wma2oJIFJv3ux/I3+w8fQQ6zMPIqpDx4Tcu9sCVpot+/siWJDpyiQBlbXfcxuH YOePUGx+tJ5HLXtJOUtPcgyhFTXRmW9r17DnnsjrT5Vc50IbN//JXbvr96eexQ/e /IXHZP6MZWdthjuv9y2TaxS+JMnpKLrXfgazoQEsKmchAsTLEyX6tHG5tHq+3MaK BSTFCoHHAgMBAAECggEAYodR1GPbZ+nuFpfhlF2ctIWe3G3awYz+LUrXX2ef3tBB WrmISVJBqq+TZtD+Hi254MR0SE6xxPSygu5m98zt5/EJN8d8qrckdLwIyLCnCElA s8rl5KFt6Y/YSdTq2g6bgGqePgt4QZi4At6yk0tYlgjV0DKFBTqzyPfVFvs/KEuZ o8le0XjgJA+Rnti35Gi5UDL1Tn9LcmCU/JcdpksFgPvU/wPmlNb8azM68ougXcrf hBebSRWbS0F2OXRJd7+hrTq+pwTNIH+IyzsUZHQCcH0tFe2Q304oDuVuwX5VxB3S tYG8+LoECW1nKalJbolkmdRqVxZRXG/Ho8/aRCHBcQKBgQDBmoZzUaKU2F4Sa6P+ 5vCQ5RAAiAATWao/WYfL9BBVnLzbkbzget3BNdJcJZKp1Avh6F/jeB0xUOD0aFgm rJAZjVAFu77damKWwiEPxKfdgSbBedV/KWCMASzr4m4cdYKOcmlLFsh+Du2+oZW5 3Mn35hyfbTf1OyYxrvOVrhSu+wKBgQD5NVfxWTBsugAE++d4CCy8TUL7QCqb1I1v EQ0FNdZsmXslPbCFlJ5UCFJXAF6s2x0MDKCl7y2ixlDo31H7DI6xlOP5kjYon7wr mB0U2bclGtlJ3FvCwDBFkfZykYZqPyey8A3D+kf4pnvZvn/0BgKfWCVSYnqEB4mp BI5WhywOpQKBgH4Mio8YTn8UZCMgG/UBDQ15ZbLC2THABj0aoHRkoiHrW3ala1DI DgsWbLB78gJKQbZCofOqp28NVnkqWoJLhcJtI/Wnp/vmoOvA1t+6TQTFaqM7HIqf OPHObh3iHYi/5VGzIeS2n7CbLaUY9S++lWymUGpoJK+wZAyi+IqyfVrzAoGAPKmI g75zNDQ+pvfuy2AqC5g/Esv200H1P7EF21vUm1DtEg6nNo0L0WbJLFZxtWAM/Q7h 2CKVmEbwEQ+zdAoFfiLBL9Iwjsj7VB1ODvJES6ryc7FJQOnpljXGqPLVpm1DK6KV pzv4YwWbplBh8zO3VbRuOVSxgAwZrWPnhhaXWeUCgYEAwVHYXN1qGTBS1uyrldDr OMuXyfvE7lbfJlg2EfG2A7PtTooPkh1IbRjlJ8ACbiadM0pYhnGGPk0D1WSKvRxU SmSc6PgW2weANQ8QCemo2V/zZ0DlWFZDdCV+7jMbAFBhQHcVh0qUr+uNyntjLTjj OPdMSnhKLoKtleu+NiMIogc= -----END PRIVATE KEY-----"; public $pubKey = "-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk7K9s+r82lofBFaj3KWp o/5E1ryDPDlLGZ4Rv68DcoCxV/bv0IvYX3cleC0WvTpwbdTpGtLjS6RHj89JREhi svv5qmk5YTfjEqd3RmtYDmOVz2Ry6E76wLh9qi1pqpneMGr3shvEzZC6gkieXRCA MOlEYbE7TSzxxDJxmovdeElowdRZcvwwPLvh/BLmCn+H1MXfdx01c/eFpTvu8BZG 1m7AqDOqnaPcR1ru/ekJoIwotF1jCPM2E5kAbQQutNaeSXhLbkfom4bxqF2/ni6k Cwnz3fbBYcXP3Ww3/AdI1dn0iLr6450qn72yBpDtQY8OZ7+Krff4Fa5jOBY7OHEN FwIDAQAB -----END PUBLIC KEY-----";

public function coin_list() { $data = $this->get_public_data(); $data["chain"] = "eth"; $data["coin"] = "eth"; $data['sign'] = Signature::encryption($data, $this->priKey); $res = self::curlByPost($this->baseUrl . '/coin/list', $data); print_r($res); // verification $resp = json_decode($res, true); if (Signature::checkSignature($resp["sign"], $resp, $this->pubKey)) { print_r("verification successful"); } else { print_r("verification failed"); } }

public static function curlByPost($url, $data = null, $timeout = 60) { $SSL = substr($url, 0, 8) == "https://" ? TRUE : FALSE; $ch = curl_init(); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_URL, $url); if ($SSL) { curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); } $data = json_encode($data);

$headers = [ 'Content-Type: application/json; charset=utf-8', 'Content-Length:' . strlen($data) ]; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $output = curl_exec($ch); return $output;

}

public function get_public_data() { $data['app_id'] = "xxxxxx";
$data['version'] = '1.0'; $data['key_version'] = 'admin'; $data['time'] = time(); return $data; } }

class Signature { /** * Private key signing * * @param $data * @param $private_key */ public static function encryption($data, $private_key) { if (is_array($data)) $signString = self::getSignString($data); else $signString = $data; $privKeyId = openssl_pkey_get_private($private_key); $signature = ''; openssl_sign($signString, $signature, $privKeyId, OPENSSL_ALGO_MD5); openssl_free_key($privKeyId); return base64_encode($signature); }

/** * Use the other party's public key to verify the signature and check whether the signature matches * * @param $sign * @param $data * @param $public_key * @return bool */ public static function checkSignature($sign, $data, $public_key) { $toSign = self::getSignString($data); $publicKeyId = openssl_pkey_get_public($public_key); $result = openssl_verify($toSign, base64_decode($sign), $publicKeyId, OPENSSL_ALGO_MD5); openssl_free_key($publicKeyId); return $result === 1 ? true : false; }

public static function getSignString($data) { unset($data['sign']); ksort($data); reset($data); $pairs = array(); foreach ($data as $k => $v) { if (is_array($v)) $v = self::arrayToString($v); $pairs[] = "$k=$v"; }

return implode('&', $pairs); }

private static function arrayToString($data) { $str = ''; foreach ($data as $list) { if (is_array($list)) { $str .= self::arrayToString($list); } else { $str .= $list; } }

return $str; } }

package main

import ( "crypto" "crypto/md5" "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/base64" "encoding/json" "encoding/pem" "errors" "fmt" "github.com/imroc/req" "github.com/tidwall/gjson" "sort" "time" )

var ( BaseUrl = "http://api.xxxxx.com/shopapi" signPrivateKey = -----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8d6RGCeQkrobx +4xO1jXnHwiMU48UyOaRaNW2FMQrN9DcK/T2h58FyuA7kYN0CVNFEnaZQS9S8Nur Tl0lOVJcbwKfCSnu9nmFYDvPWqlCTqQW3F83sKNi9IWrMFFny3CX35eUHpeJahE2 R9wma2oJIFJv3ux/I3+w8fQQ6zMPIqpDx4Tcu9sCVpot+/siWJDpyiQBlbXfcxuH YOePUGx+tJ5HLXtJOUtPcgyhFTXRmW9r17DnnsjrT5Vc50IbN//JXbvr96eexQ/e /IXHZP6MZWdthjuv9y2TaxS+JMnpKLrXfgazoQEsKmchAsTLEyX6tHG5tHq+3MaK BSTFCoHHAgMBAAECggEAYodR1GPbZ+nuFpfhlF2ctIWe3G3awYz+LUrXX2ef3tBB WrmISVJBqq+TZtD+Hi254MR0SE6xxPSygu5m98zt5/EJN8d8qrckdLwIyLCnCElA s8rl5KFt6Y/YSdTq2g6bgGqePgt4QZi4At6yk0tYlgjV0DKFBTqzyPfVFvs/KEuZ o8le0XjgJA+Rnti35Gi5UDL1Tn9LcmCU/JcdpksFgPvU/wPmlNb8azM68ougXcrf hBebSRWbS0F2OXRJd7+hrTq+pwTNIH+IyzsUZHQCcH0tFe2Q304oDuVuwX5VxB3S tYG8+LoECW1nKalJbolkmdRqVxZRXG/Ho8/aRCHBcQKBgQDBmoZzUaKU2F4Sa6P+ 5vCQ5RAAiAATWao/WYfL9BBVnLzbkbzget3BNdJcJZKp1Avh6F/jeB0xUOD0aFgm rJAZjVAFu77damKWwiEPxKfdgSbBedV/KWCMASzr4m4cdYKOcmlLFsh+Du2+oZW5 3Mn35hyfbTf1OyYxrvOVrhSu+wKBgQD5NVfxWTBsugAE++d4CCy8TUL7QCqb1I1v EQ0FNdZsmXslPbCFlJ5UCFJXAF6s2x0MDKCl7y2ixlDo31H7DI6xlOP5kjYon7wr mB0U2bclGtlJ3FvCwDBFkfZykYZqPyey8A3D+kf4pnvZvn/0BgKfWCVSYnqEB4mp BI5WhywOpQKBgH4Mio8YTn8UZCMgG/UBDQ15ZbLC2THABj0aoHRkoiHrW3ala1DI DgsWbLB78gJKQbZCofOqp28NVnkqWoJLhcJtI/Wnp/vmoOvA1t+6TQTFaqM7HIqf OPHObh3iHYi/5VGzIeS2n7CbLaUY9S++lWymUGpoJK+wZAyi+IqyfVrzAoGAPKmI g75zNDQ+pvfuy2AqC5g/Esv200H1P7EF21vUm1DtEg6nNo0L0WbJLFZxtWAM/Q7h 2CKVmEbwEQ+zdAoFfiLBL9Iwjsj7VB1ODvJES6ryc7FJQOnpljXGqPLVpm1DK6KV pzv4YwWbplBh8zO3VbRuOVSxgAwZrWPnhhaXWeUCgYEAwVHYXN1qGTBS1uyrldDr OMuXyfvE7lbfJlg2EfG2A7PtTooPkh1IbRjlJ8ACbiadM0pYhnGGPk0D1WSKvRxU SmSc6PgW2weANQ8QCemo2V/zZ0DlWFZDdCV+7jMbAFBhQHcVh0qUr+uNyntjLTjj OPdMSnhKLoKtleu+NiMIogc= -----END PRIVATE KEY----- signPublicKey = -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk7K9s+r82lofBFaj3KWp o/5E1ryDPDlLGZ4Rv68DcoCxV/bv0IvYX3cleC0WvTpwbdTpGtLjS6RHj89JREhi svv5qmk5YTfjEqd3RmtYDmOVz2Ry6E76wLh9qi1pqpneMGr3shvEzZC6gkieXRCA MOlEYbE7TSzxxDJxmovdeElowdRZcvwwPLvh/BLmCn+H1MXfdx01c/eFpTvu8BZG 1m7AqDOqnaPcR1ru/ekJoIwotF1jCPM2E5kAbQQutNaeSXhLbkfom4bxqF2/ni6k Cwnz3fbBYcXP3Ww3/AdI1dn0iLr6450qn72yBpDtQY8OZ7+Krff4Fa5jOBY7OHEN FwIDAQAB -----END PUBLIC KEY----- )

func main() { pub := make(map[string]string) // Open Parameter pub["app_id"] = "xxxxxxxxx" pub["version"] = "1.0" pub["key_version"] = "admin" pub["time"] = fmt.Sprintf("%d", time.Now().Unix()) // Business Coin Parameter pub["chain"] = "eth" pub["coin"] = "eth" pub["sign"] = getSign(pub)

url := fmt.Sprintf("%s/coin/list", BaseUrl) r := req.New() r.EnableInsecureTLS(true) post, err := r.Post(url, req.BodyJSON(&pub)) if err != nil { panic(err) } fmt.Println("return", post.String()) // verification checkSign(post.String()) }

// Getting signature string func getSign(data map[string]string) string { err, signStr := ApiSign(data, signPrivateKey) if err != nil { panic(err) } fmt.Println("signature string:", signStr) return signStr }

// verifying signature func checkSign(resp string) { var res map[string]interface{} err := json.Unmarshal([]byte(resp), &res) if err != nil { panic(err) } sign := res["sign"].(string) data := ParseJsonToClassMap(resp) err = ApiVerifySign(data, signPublicKey, sign) if err != nil { fmt.Println("verification failed") return } fmt.Println("verification successful") }

/** * Local private key signature * @param data parameter * @param priKey local private key * @return error * @return string / func ApiSign(data map[string]string, priKey string) (error, string) { hashed := getSignString(data) // rsa block, _ := pem.Decode([]byte(priKey)) if block == nil { return errors.New("private key error"), "" } privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { return err, "" } signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey.(rsa.PrivateKey), crypto.MD5, hashed) if err != nil { return err, "" } ciphertext := base64.StdEncoding.EncodeToString(signature)

return nil, ciphertext }

/** * Using other party's public key to verify the signature, and determine whether the signature matches * @param data parameter * @param signed signature body * @param pubKey public key * @return error / func ApiVerifySign(data map[string]string, pubKey string, signed string) error { hashed := getSignString(data) block, _ := pem.Decode([]byte(pubKey)) if block == nil { return errors.New("public key error") } // Parse public key pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return err } pub := pubInterface.(rsa.PublicKey)

decodeString, err := base64.StdEncoding.DecodeString(signed) if err != nil { return err } err = rsa.VerifyPKCS1v15(pub, crypto.MD5, hashed, decodeString) if err != nil { return err }

return nil }

// Splice parameter func getSignString(data map[string]string) []byte { delete(data, "sign") var keys []string for k := range data { keys = append(keys, k) } sort.Strings(keys)

var signStr string for _, k := range keys { if signStr != "" { signStr = signStr + "&" + k + "=" + data[k] } else { signStr = k + "=" + data[k] } }

hashMd5 := md5.Sum([]byte(signStr)) hashed := hashMd5[:]

return hashed }

func ParseJsonToClassMap(jsonStr string) (m map[string]string) { m = make(map[string]string) result := gjson.Parse(jsonStr) result.ForEach(func(key, value gjson.Result) bool { if value.Type == gjson.JSON && gjson.Valid(value.String()) { m[key.String()] = JsonToString(value.String()) } else { m[key.String()] = value.String() } return true }) return }

func JsonToString(jsonStr string) string { str := "" r := gjson.Parse(jsonStr) r.ForEach(func(key, value gjson.Result) bool { if value.Type == gjson.JSON && gjson.Valid(value.String()) { str += JsonToString(value.String()) } else { str += value.String() } return true }) return str }

var crypto = require('crypto');

var priKey = -----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8d6RGCeQkrobx +4xO1jXnHwiMU48UyOaRaNW2FMQrN9DcK/T2h58FyuA7kYN0CVNFEnaZQS9S8Nur Tl0lOVJcbwKfCSnu9nmFYDvPWqlCTqQW3F83sKNi9IWrMFFny3CX35eUHpeJahE2 R9wma2oJIFJv3ux/I3+w8fQQ6zMPIqpDx4Tcu9sCVpot+/siWJDpyiQBlbXfcxuH YOePUGx+tJ5HLXtJOUtPcgyhFTXRmW9r17DnnsjrT5Vc50IbN//JXbvr96eexQ/e /IXHZP6MZWdthjuv9y2TaxS+JMnpKLrXfgazoQEsKmchAsTLEyX6tHG5tHq+3MaK BSTFCoHHAgMBAAECggEAYodR1GPbZ+nuFpfhlF2ctIWe3G3awYz+LUrXX2ef3tBB WrmISVJBqq+TZtD+Hi254MR0SE6xxPSygu5m98zt5/EJN8d8qrckdLwIyLCnCElA s8rl5KFt6Y/YSdTq2g6bgGqePgt4QZi4At6yk0tYlgjV0DKFBTqzyPfVFvs/KEuZ o8le0XjgJA+Rnti35Gi5UDL1Tn9LcmCU/JcdpksFgPvU/wPmlNb8azM68ougXcrf hBebSRWbS0F2OXRJd7+hrTq+pwTNIH+IyzsUZHQCcH0tFe2Q304oDuVuwX5VxB3S tYG8+LoECW1nKalJbolkmdRqVxZRXG/Ho8/aRCHBcQKBgQDBmoZzUaKU2F4Sa6P+ 5vCQ5RAAiAATWao/WYfL9BBVnLzbkbzget3BNdJcJZKp1Avh6F/jeB0xUOD0aFgm rJAZjVAFu77damKWwiEPxKfdgSbBedV/KWCMASzr4m4cdYKOcmlLFsh+Du2+oZW5 3Mn35hyfbTf1OyYxrvOVrhSu+wKBgQD5NVfxWTBsugAE++d4CCy8TUL7QCqb1I1v EQ0FNdZsmXslPbCFlJ5UCFJXAF6s2x0MDKCl7y2ixlDo31H7DI6xlOP5kjYon7wr mB0U2bclGtlJ3FvCwDBFkfZykYZqPyey8A3D+kf4pnvZvn/0BgKfWCVSYnqEB4mp BI5WhywOpQKBgH4Mio8YTn8UZCMgG/UBDQ15ZbLC2THABj0aoHRkoiHrW3ala1DI DgsWbLB78gJKQbZCofOqp28NVnkqWoJLhcJtI/Wnp/vmoOvA1t+6TQTFaqM7HIqf OPHObh3iHYi/5VGzIeS2n7CbLaUY9S++lWymUGpoJK+wZAyi+IqyfVrzAoGAPKmI g75zNDQ+pvfuy2AqC5g/Esv200H1P7EF21vUm1DtEg6nNo0L0WbJLFZxtWAM/Q7h 2CKVmEbwEQ+zdAoFfiLBL9Iwjsj7VB1ODvJES6ryc7FJQOnpljXGqPLVpm1DK6KV pzv4YwWbplBh8zO3VbRuOVSxgAwZrWPnhhaXWeUCgYEAwVHYXN1qGTBS1uyrldDr OMuXyfvE7lbfJlg2EfG2A7PtTooPkh1IbRjlJ8ACbiadM0pYhnGGPk0D1WSKvRxU SmSc6PgW2weANQ8QCemo2V/zZ0DlWFZDdCV+7jMbAFBhQHcVh0qUr+uNyntjLTjj OPdMSnhKLoKtleu+NiMIogc= -----END PRIVATE KEY----- var pubKey = -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk7K9s+r82lofBFaj3KWp o/5E1ryDPDlLGZ4Rv68DcoCxV/bv0IvYX3cleC0WvTpwbdTpGtLjS6RHj89JREhi svv5qmk5YTfjEqd3RmtYDmOVz2Ry6E76wLh9qi1pqpneMGr3shvEzZC6gkieXRCA MOlEYbE7TSzxxDJxmovdeElowdRZcvwwPLvh/BLmCn+H1MXfdx01c/eFpTvu8BZG 1m7AqDOqnaPcR1ru/ekJoIwotF1jCPM2E5kAbQQutNaeSXhLbkfom4bxqF2/ni6k Cwnz3fbBYcXP3Ww3/AdI1dn0iLr6450qn72yBpDtQY8OZ7+Krff4Fa5jOBY7OHEN FwIDAQAB -----END PUBLIC KEY-----

/** * Private key signing */ function encryption(data) { let signString = getSignString(data) let sign = crypto.createSign('md5WithRSAEncryption');

sign.update(signString, 'utf8'); sign.end(); let signature = sign.sign(priKey, 'base64');

return signature }

/** * Use the other party's public key to verify the signature and check whether the signature matches * @param sign * @param data * @return bool */ function checkSignature(sign, data) { let signString = getSignString(data) let verify = crypto.createVerify('md5WithRSAEncryption'); verify.update(signString, 'utf8'); verify.end(); return verify.verify(pubKey, sign, 'base64'); }

// Splice parameter function getSignString(data) { delete(data["sign"]) var keys = Object.keys(data) keys = keys.sort() let signStr = "" for(let k in keys) { if(typeof(data[keys[k]]) == "object") { signStr = keys[k] + "=" + arrayToString(data[keys[k]]) }else { if (signStr != "") { signStr = signStr + "&" + keys[k] + "=" + data[keys[k]] } else { signStr = keys[k] + "=" + data[keys[k]] } } } return signStr } function arrayToString(data) { let str = ''; for(let list in data) { if (typeof (data[list]) == "object") { str += arrayToString(data[list]); } else { str += data[list]; } } return str; }

//send http post function httpByPost(data) { let HTTP = require('http') let POST_OPTIONS = { port: 8888, host: "http://api.xxxxx.com/shopapi", path: "/coin/list", method: 'POST', headers: { "Content-Type": "application/json" } }; const REQUEST = HTTP.request(POST_OPTIONS, requestOnResponse) REQUEST.setTimeout(6000)

REQUEST.write(JSON.stringify(data), 'utf8') REQUEST.end() }

function requestOnResponse(incomingMessage){ let data = [] incomingMessage.on('data', chunk => { data.push(...chunk) })

incomingMessage.on('end', () => { let _date = JSON.parse( new TextDecoder().decode(new Uint8Array(data))) let res = checkSignature(_date["sign"], _date)

console.log(res) }) } /**testing*****/ let data = { 'app_id' : 'xxxxxxxxx', 'version' : '1.0', 'key_version' : 'admin', 'time' : Math.floor(Date.now()/1000), 'chain' :'eth', 'coin' : 'eth', } data['sign'] = encryption(data) httpByPost(data);

package com.junior.common;

import com.google.gson.*;

import java.io.; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.*; import java.util.stream.Collectors;

public class rsaSigner {

public static void main(String[] args) {

String baseUrl = "http://api.xxxxx.com/shopapi"; String priKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtdgvcfozY7fe/x6UlXR/Fff8+wX++CiG05YVRafDe90O8y5KJAMZ156TgajEUXSRyKZqASz7iVoMAcu5FqfK1KuOOdjTAg0LFe/twIZvKmAqHcCSS2pjUXk0fTpZEgQ5lmDCK12Mg07YXvr+BeHjF+kBpwRJMPMG/+DGBDYNFNeRSJqWyopt6yyF528soAykHIUQ7TTultJV5IPCrvjRQQrGdJ/QtCdE0vZg+tA09nFN7AqgraU99kIvzyS0sqysj+pP1SJRmTRSGtlVAO3mILfkXOekZl1KD60G7CF+7BIaaW83FPD55tZhAGhnbLMYyiq7OiIyU61LTRcNSaJ0tAgMBAAECggEBAIGgGKcSzxCBbMYdXLV6TPbZ/HeaRGrwyVWUu7cmc0E8CJu6iWvmb2jGzbiCwuCT5luF6ZZ8JKchvU4FlTfsE5r9TQY2IZ/Ht4s65qBaDUEts5iY3kv8HX9+ZSXDJZpV0ztqqsPmx4ZNj+NYwWXwcFiKdb5R8OmV8bgSsnPddD6wFhwewglUOBPRAjropHE4sqk1Vam6q1MlFq5kiekMn/CItyFYFFzST/ruqAtVTp7YIvazAMrfCKH+pvXWk6pYNHZmL/JZey0GglRyJ1nItiqL33X8Lji056FcbAclidq022h/KPLEJpZk6irWqYdqYZeF6YMLHtdZFDkTZ/hXY+UCgYEA5i794UTQ1Kd6K+iui/S8K5H8nGdiXb3+uZ5j5VKYfbRmzXhAdVYisYe8czeTECxhH+MeHgM4tLR4ifx9q60ylvZxl9Fav1p6EaE36YcvGVmpm7Gm3q6QDDBa4gB+X9u7CxCS4LpotV917YS1QvOIF9lnRonSj1zNzFtbXkywrN8CgYEAwOpx/mR40ZvgZxNCq9DsIdrSZYAFFKpw0xy0OtF1PpuwMaREoRabnlVw6Bb3Hofg50XA3JxemzAX6fB92ee+NfXfeL4UtC4vG1K9JyiXHtHq8p9Uw2W03ehIEeNa3xdoRRnLmD4VUpyfL19ViE2+7TM1Gd3TogjDT+AMOCSuq3MCgYBsurPH7gaq/LVT+mRAzgj4l8v4YUlwuGeTbIMJdvt7HXUWB4CDLH3U2CYnUpAQKrZyJok6ahEmIr1xiKggKP7lmmHL8eNo0icpHrtXfzi7Q8Q/PCpzs4dtioXTjaIkS5nNvzVyG/uL+RyuZmpsxrZ5dYM4KbAhchfwORMutxEZhwKBgQC5zpVw4jCEItBmNuTWO+nTScGvxTgfiXIVw+XLaQa2AJoZlhAL34yPWdffko79tv3lgweY9HsimZXO2rU8dbp8mo5c6ydhy8HPXUeWOcAkDSdv/ApWENW9jgYsRIC3swHY3Fl+Dv3Wjce8huQI3mjwaYvRmBhIToxfmHnscVhTBQKBgB9uciEHfz8hMI7ePrPo2PkyK/RbJDm3HnuWE2lFBp7MOUMlh53MXwv4dIRaYMbRrFuN1UIKEFxuKhWwTHSzZJufk/UENrha/81fpj2BoFsAKkEunKeETvaIh6fZSjec16h2+zxbzwkdS6b+yIYkSlaoAxmDYrMtae0C8G4e0YS9"; String pubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2RZZISModRzproL3eTxRtvVK/nToDbeLmAVdmaVtHgNCwjXMeNCZvHySZKO7+t7XySzBd2PhhQjvAkDd8HRKB5Y0uvP6TFwvhxOMkMydTeBFcUobQWNeAI7ttRms1txSNrmyrZr0WpWfk79VIsO+yI/jFN/Pj2gxD+vh5UUKU1LD2IQq/VxgtEpf8Vs6w7SvafPwYkpdPGCKUFkRvN1FrY2+tq0j1MRVJbB2rIunWDnT8cDUh2sWLXf4yNaJVOaaTFB0zbAk/qcoicGQyW7bVG7dVW8WywKmOAPeQCCQa+SJ4BhfI1k8eEAwFVRuxz/f9Ecfog9hZJ+RgELkpS8qhQIDAQAB";

rsaSigner signer = new rsaSigner();

Map<String, Object> params = new HashMap<>(); params.put("app_id", "hxgmau9imt86qky9"); params.put("version", "1.0"); params.put("key_version", "admin"); params.put("time", Long.toString(System.currentTimeMillis() / 1000)); params.put("coin", "trx");

try { params.put("sign", signer.genSign(params, priKey)); Gson gson = new GsonBuilder().create(); System.out.println("params = " + gson.toJson(params));

String res = doPost(baseUrl + "/address/getBatch", gson.toJson(params)); if (null == res) { throw new RuntimeException("http error"); } System.out.println("response = " + res);

JsonParser jp = new JsonParser(); JsonObject resEle = jp.parse(res).getAsJsonObject(); boolean retSignOK = signer.verifySign(resEle, resEle.get("sign").getAsString(), pubKey); if (!retSignOK) { throw new RuntimeException("verify response sign fail"); }

} catch (Exception e) { e.printStackTrace(); }

System.out.println("OK"); }

public String genSign(Map<String, Object> data, String priKey) throws NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, InvalidKeyException { Map<String, String> stringMap = toStringMap(new GsonBuilder().create().toJson(data)); return this.sign(this.genSignString(stringMap), priKey); }

public String genSignString(Map<String, String> params) { if (null == params || params.size() == 0) { return ""; }

List<String> sortedKeys = new ArrayList<>(params.keySet()); sortedKeys.remove("sign"); sortedKeys.sort(null); String sb = sortedKeys.stream().map(s -> s + "=" + params.get(s)).collect(Collectors.joining("&"));

System.out.println("genSignString = " + sb);

return sb; }

public String sign(String str, String priKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); byte[] decodedKey = Base64.getDecoder().decode(priKey.getBytes(StandardCharsets.UTF_8)); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey); PrivateKey pk = keyFactory.generatePrivate(keySpec);

Signature signature = Signature.getInstance("MD5withRSA"); signature.initSign(pk); signature.update(str.getBytes(StandardCharsets.UTF_8)); return new String(Base64.getEncoder().encode(signature.sign()), StandardCharsets.UTF_8); }

public boolean verifySign(JsonElement data, String sign, String pubKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { Map<String, String> resMap = toStringMap(data); String signString = this.genSignString(resMap);

byte[] keyBytes = Base64.getDecoder().decode(pubKey.getBytes(StandardCharsets.UTF_8)); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey key = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance("MD5withRSA"); signature.initVerify(key); signature.update(signString.getBytes(StandardCharsets.UTF_8)); return signature.verify(Base64.getDecoder().decode(sign.getBytes(StandardCharsets.UTF_8))); }

public static Map<String, String> toStringMap(String str) { JsonParser jp = new JsonParser(); JsonElement jEle = jp.parse(str); return toStringMap(jEle); }

public static Map<String, String> toStringMap(JsonElement jEle) { Map<String, String> resMap = new HashMap<>(); if (null != jEle && jEle.isJsonObject()) { for (Map.Entry<String, JsonElement> entry : jEle.getAsJsonObject().entrySet()) { resMap.put(entry.getKey(), valueAsString(entry.getValue())); } } return resMap; }

public static String valueAsString(JsonElement element) { if (element.isJsonNull()) { return ""; } else if (element.isJsonPrimitive()) { return element.getAsJsonPrimitive().getAsString(); } else if (element.isJsonObject()) { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, JsonElement> entry : element.getAsJsonObject().entrySet()) { sb.append(valueAsString(entry.getValue())); } return sb.toString(); } else if (element.isJsonArray()) { StringBuilder sb = new StringBuilder(); for (JsonElement vv : element.getAsJsonArray()) { sb.append(valueAsString(vv)); } return sb.toString(); } return ""; }

public static String doPost(String httpUrl, String param) { //send http post request } }

Create private key

openssl genrsa -out rsa_private_key.pem 2048

Create public key from private key

openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout

Signature Algorithm Details

Generate the signature string, for the following parameter array: user_id = 1 coin = eth address = 0x038B8E7406dED2Be112B6c7E4681Df5316957cad amount = 10.001 trade_id = 20220131012030274786

Sort each key in the array in order from a to z. If the same first letter is encountered, look at the second letter, and so on. After sorting, connect all array values ​​with "&" characters, such as $dataString:

address=0x038B8E7406dED2Be112B6c7E4681Df5316957cad&amount=10.001&coin=eth&trade_id=20220131012030274786&user_id=1
This string is the transfromed string.

Public information description

The following information is common to all interfaces, and the description of each interface is not repeated

Production Environment

Please contact customer service to obtain the API address

test environment

Please contact customer service to obtain the API address

Common paremeter in Request

Parameter Name Required Type Constraint Case Description
app_id Yes string Generated by the system A6vZLiqyRYxu Merchant ID assigned by the system when docking
version yes string fixed 1.0 interface version number - fixed according to the agreement at the time of access
sign yes string length 344 bits Dr7MnhPYh… RSA-2048 bit key mode
time yes string length 10 digits 1578829811 timestamp - ignoring timezone timestamp in seconds
key_version no string dynamic enumeration type default: admin key version number: admin / read / arbitrary - can be authorized for any 1-n interfaces

Public Information Notice

Name Type Case Description
time1 timeStamp 1578829811 UTC time unified time without time zone
Time 2 DateTime 2020-01-09 15:48:42 The global system defaults to Beijing time if this format appears
Request Method POST — All requests are POST
Encoding UTF-8 — Other encodings may produce garbled characters and errors
Communication Protocol HTTPS https Currently only HTTPS is supported
Signature Type RSA-2048-bit Dr7MnhPYh… Click to view rule details
Request and Return JSON — All request and response parameters are in JSON format
Note on the amount parameter string — The number of digits after the decimal point exceeds 8, and the number of digits before the decimal point exceeds 12, which cannot be passed, and the last invalid 0 must be deleted.