Appearance
Signature Code Examples
Java
java
import lombok.extern.slf4j.Slf4j;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Map;
import java.util.TreeMap;
@Slf4j
public class RSASignatureUtil {
/**
* Sign with SHA256withRSA
* @param data The string to sign
* @param privateKeyBase64 PKCS#8 private key (Base64 encoded, without PEM header/footer)
* @return Base64-encoded signature result
*/
public static String sign(String data, String privateKeyBase64) throws Exception {
byte[] keyBytes = Base64.getDecoder().decode(privateKeyBase64);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(key);
signature.update(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(signature.sign());
}
/**
* Construct signature string
* @param bodyData Request body JSON string (pass null if no body)
* @param timestamp Unix timestamp (seconds)
* @param nonce Random string
* @param requestParams URL query parameters
* @return Concatenated signature string
*/
public static String constructSignatureString(
String bodyData, String timestamp, String nonce,
Map<String, String> requestParams) {
StringBuilder sortedParams = new StringBuilder();
new TreeMap<>(requestParams).forEach((key, value) ->
sortedParams.append(key).append("=").append(value).append("&"));
if (sortedParams.length() > 0) {
sortedParams.setLength(sortedParams.length() - 1);
}
return String.format("%s%s%s%s",
sortedParams, timestamp, nonce,
bodyData != null ? bodyData : "");
}
}Usage example:
java
Map<String, String> params = Map.of("param1", "value1", "param2", "value2");
String signatureString = RSASignatureUtil.constructSignatureString(
"{\"merchantUserNo\":\"U1000001\",\"email\":\"[email protected]\"}",
"1743478725", "a1b2c3", params);
String signature = RSASignatureUtil.sign(signatureString, PRIVATE_KEY);Python
TIP
Requires dependency: pip install pycryptodome
python
import base64
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
def construct_signature_string(body_data, timestamp, nonce, request_params):
"""Construct signature string"""
sorted_params = "&".join(
f"{k}={v}" for k, v in sorted(request_params.items())
)
return f"{sorted_params}{timestamp}{nonce}{body_data or ''}"
def sign(data, private_key_pem):
"""Sign with SHA256withRSA"""
key = RSA.import_key(private_key_pem)
h = SHA256.new(data.encode("utf-8"))
signature = pkcs1_15.new(key).sign(h)
return base64.b64encode(signature).decode("utf-8")
# Usage example
PRIVATE_KEY = """-----BEGIN PRIVATE KEY-----
<YOUR_PRIVATE_KEY>
-----END PRIVATE KEY-----"""
request_params = {"param1": "value1", "param2": "value2"}
body = '{"merchantUserNo":"U1000001","email":"[email protected]"}'
signature_string = construct_signature_string(body, "1743478725", "a1b2c3", request_params)
result = sign(signature_string, PRIVATE_KEY)
print("Signature:", result)Go
go
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"log"
"sort"
"strings"
)
// constructSignatureString constructs the signature string
func constructSignatureString(bodyData, timestamp, nonce string, params map[string]string) string {
keys := make([]string, 0, len(params))
for k := range params {
keys = append(keys, k)
}
sort.Strings(keys)
pairs := make([]string, 0, len(keys))
for _, k := range keys {
pairs = append(pairs, fmt.Sprintf("%s=%s", k, params[k]))
}
sortedParams := strings.Join(pairs, "&")
return sortedParams + timestamp + nonce + bodyData
}
// sign signs data with SHA256withRSA
func sign(data, pemKey string) (string, error) {
block, _ := pem.Decode([]byte(pemKey))
if block == nil {
return "", fmt.Errorf("failed to decode PEM block")
}
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return "", fmt.Errorf("failed to parse private key: %w", err)
}
rsaKey, ok := key.(*rsa.PrivateKey)
if !ok {
return "", fmt.Errorf("private key is not RSA")
}
hashed := sha256.Sum256([]byte(data))
sig, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, crypto.SHA256, hashed[:])
if err != nil {
return "", fmt.Errorf("failed to sign: %w", err)
}
return base64.StdEncoding.EncodeToString(sig), nil
}
func main() {
params := map[string]string{"param1": "value1", "param2": "value2"}
body := `{"merchantUserNo":"U1000001","email":"[email protected]"}`
sigStr := constructSignatureString(body, "1743478725", "a1b2c3", params)
signature, err := sign(sigStr, privateKeyPEM)
if err != nil {
log.Fatal(err)
}
fmt.Println("Signature:", signature)
}