Signing Method The Request Content

To secure the request content of Coin8 APIs. All the requests using API Keys must be signing the content before make the request

Generate the RSA pem keys and setting

  • OS: Linux/ MacOS
  • Preconditions: install openssl package
  • Cryptosystem: RSA

Generate the public and private keys:

# generate a private key with the correct length
openssl genrsa -out private-key.pem 1024

# generate corresponding public key
openssl rsa -in private-key.pem -pubout -out public-key.pem

Settings > Sign Key
Copy the content of public-key.pem to set to Sign Key setting

Generate the signing request content

  • Signature scheme: PSS
  • Hash: SHA256

Example:

  • Body payload and query param
curl --location --request POST 'https://api.coin8.io/api/deposit?param_1=1&param_2=2' --data-raw 'body'
=> data to sign: []byte("bodyparam_1=1&param_2=2")
  • Only body payload
curl --location --request POST 'https://api.coin8.io/api/deposit' --data-raw 'body'
=> data to sign: []byte("body")
  • Only query param
curl --location --request POST 'https://api.coin8.io/api/deposit?param_1=1&param_2=2' 
=> data to sign: []byte("param_1=1&param_2=2")
  • No params
curl --location --request POST 'https://api.coin8.io/api/deposit' 
=> data to sign: nil

=> Formula: {request_body_payload}+{request_query_param}

package main

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"fmt"
	"os"
)

func main() {
	privPEM, err := os.ReadFile("private-key.pem")
	if err != nil {
		panic(err)
	}

	payload := `{
		"merchant_deposit_id": "merchant_deposit_id",
		"deposit_amount": 1,
		"deposit_currency": "USDT",
		"merchant_data": "data 123",
		"redirect_url": "redirect_url",
		"deposit_merchant_callback_url": "deposit_merchant_callback_url",
		"payment_currency": "USDT",
		"payment_network": "TRC20"
	}`

	signature, err := RSASignPSS(privPEM, []byte(payload))
	if err != nil {
		panic(err)
	}

	fmt.Printf("Signature: %s", signature)
}

func RSASignPSS(privPEM, data []byte) (string, error) {
	block, _ := pem.Decode(privPEM)

	privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return "", err
	}

	rng := rand.Reader
	hashed := sha256.Sum256([]byte(data))

	signature, err := rsa.SignPSS(rng, privKey, crypto.SHA256, hashed[:], &rsa.PSSOptions{})
	if err != nil {
		return "", err
	}

	return base64.StdEncoding.EncodeToString(signature), nil
}
from Crypto.Hash import SHA256
from Crypto.Signature import PKCS1_PSS
from Crypto.PublicKey import RSA
import base64 

payload = """{
    "merchant_deposit_id": "merchant_deposit_id",
    "deposit_amount": 1,
    "deposit_currency": "USDT",
    "merchant_data": "data 123",
    "redirect_url": "redirect_url",
    "deposit_merchant_callback_url": "deposit_merchant_callback_url",
    "payment_currency": "USDT",
    "payment_network": "TRC20"
}"""
message = str.encode(payload)
digest = SHA256.new()
digest.update(message)
private_key = False

with open ("private-key.pem", "rb") as myfile:
    private_key = RSA.importKey(myfile.read())

signer = PKCS1_PSS.new(private_key)
sig = signer.sign(digest)
print(base64.b64encode(sig))
import java.security.KeyFactory;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

public class SHA256RSAPSS {
    public static void main(String[] args) throws Exception {
        String input = "Input Text to Sign here";

        // Not a real private key! Replace with your private key!
        String strPk = "Load RSA Private Key";

        String base64Signature = signSHA256RSAPSS(input,strPk);
        System.out.println(base64Signature);
    }
 
    // Create base64 encoded signature using SHA256withRSA/PSS.
    private static String signSHA256RSAPSS(String input, String strPk) throws Exception {
        // Remove markers and new line characters in private key
        String realPK = strPk.replaceAll("-----END RSA PRIVATE KEY-----", "")
                             .replaceAll("-----BEGIN RSA PRIVATE KEY-----", "")
                             .replaceAll("\n", "");

        java.security.Security.addProvider(
            new org.bouncycastle.jce.provider.BouncyCastleProvider()
        );

        byte[] b1 = Base64.getDecoder().decode(realPK);

        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(b1);
        KeyFactory kf = KeyFactory.getInstance("RSA");
 
        Signature privateSignature = Signature.getInstance("SHA256withRSA/PSS");
        privateSignature.initSign(kf.generatePrivate(spec));
        privateSignature.update(input.getBytes("UTF-8"));
        byte[] s = privateSignature.sign();
        return Base64.getEncoder().encodeToString(s);
    }
}