Netzme vSNAP
  • Introducing
  • Getting Started
  • API Reference
    • Toko Netzme
      • Credentials & Signature
      • Authentication
      • Create pin
      • Forgot pin
      • Get Balance Detail
      • Get Transaction List
      • Get Merchant Detail
      • Withdraw Inquiry
      • Get Information Withdraw
      • Get QRIS Acquire Transaction
      • Create Invoice
      • Create Invoice Transaction
      • Create Invoice QR MPM
      • Get Invoice Transaction
      • Payment Success Callback (Invoice)
      • Payment Success Callback (QRIS Non Invoice )
      • Payment Success Callback V2
        • Payment Success Callback QRIS
        • SNAP Payment Success Callback QRIS
      • Withdraw Status Notification
      • Deduct Deposit and Split Fee
      • Deposit
        • Create Invoice Transaction Topup Deposit
        • Inquiry Withdraw Deposit
        • Withdraw Deposit
        • Get Information Withdraw Deposit
        • Get Deposit Transaction
        • Get Balance Deposit
      • Withdraw Process
      • SNAP Asymmetric Signature
    • Netzme
      • Connect to Netzme
      • Credentials & Signature
      • Authentication
      • Get Account Status
      • Get Balance
      • Get History
      • Get Fixed Topup VA
      • Get Detail Qris
        • QRIS Static
        • QRIS Static With Amount & Percentage Fee
        • QRIS Dynamic
        • QRIS Dynamic with Fee
      • QRIS Payment
      • QRIS Payment Notification
      • Payment Bill
      • Payment Bill Notification
      • Payment Netzme Seamless
      • Upgrade Account Notification
      • Upgrade Account
Powered by GitBook
On this page
  1. API Reference
  2. Toko Netzme

SNAP Asymmetric Signature

Signature Generation and Validation

Asymetric Signature is used to ensure data integrity and authenticity of the request or response for each API. The signature needs to be provided using a private key. Netzme's system supports the use of PKCS#8 for the private key. The generated signature will be verified using a public key. The algorithm used by NETZME is SHA256withRSA and the format type is Base64.

Asymmetric Key Generation

  1. Prepare the data to do signature, the data are:

    No
    Data
    Remarks
    Example

    1

    HTTP METHOD

    Method on each API, for instance GET, POST, PUT, PATCH, and DELETE

    POST

    2

    RELATIVE PATH URL

    URL on each API

    /v1.0/balance-inquiry.htm

    3

    HTTP BODY

    Minify request body and hash the request body with SHA-256, refer to step no ii and iii for the detail

    e9295c3253c05560273ff305d9eea6abf7 7fff65229bf90b1781383c09c29d98

    4

    X-TIMESTAMP

    Transaction date time, in format YYYY-MM-DDTHH:mm:ss+07:00. Time must be in GMT+7 (Jakarta time)

    2022-11-30T09:45:35+07:00

    1. Minify the request body

      Refer to the tools section number 1 for the example process. The following are the example value before and after minify the request body:

      (<HTTP BODY>) before minify

      {
          "partnerReferenceNo":"2020102900000000000001",
          "balanceTypes":["BALANCE"],
          "additionalInfo":{
            "accessToken" : "fa8sjjEj813Y9JGoqwOeOPWbnt4CUpvIJbU1mMU4a11MNDZ7Sg5u9a"
          }
      } 

      (<HTTP BODY>) after minify

      {"partnerReferenceNo":"2020102900000000000001","balanceTypes":["BALANCE"],"additionalInfo":{"accessToken":"fa8sjjEj813Y9JGoqwOeOPWbnt4CUpvIJbU1mMU4a11MNDZ7Sg5u9a"}} 
    2. Lowercase(HexEncode(SHA-256(RequestBody)))

      Refer to the tools section number 3 for the example process. The following is the example value:

      e9295c3253c05560273ff305d9eea6abf77fff65229bf90b1781383c09c29d98
    3. Compose the string to sign

      <HTTP METHOD> + ”:” + <RELATIVE PATH URL> + “:“ + LowerCase(HexEncode(SHA-256(Minify(<HTTP BODY>)))) + “:“ + <X-TIMESTAMP>

      The following is the example:

      POST:/v1.0/balance-inquiry.htm:e9295c3253c05560273ff305d9eea6abf77fff65229bf90b1781383c09c29d98:2022-11-30T09:45:35+07:00
    4. The signature string is generated from string to sign above with applying SHA-256 with RSA-2048 encryption using PKCS#8 or PKCS#1 private key, and then encode the result to base64.

      The following is the example value:

      iSkd8HPpdeeQSnq5lSRM46l8w/C4ZhNq7ordOv2dfDC0A0rGWxqz+9j864gcuVhu0tgTHJUuV9k5wsluig/sJ4W5Yy1EZPzbpeeUwFxSK0WgnW5LLq/h5RQAgVEyJL5MI1KrByzBQIv+5IYgKaLFmTLeo4xy7ToLJKND/6Ja+HRuo+SpnzNA2NNJEcc+PI87pAo0yXItZhjUXhyz9rkv0P8Ra8tDar2asHVGxA5BiGthy/eyPbe9VYavfMrOKAZpISw9VVoZ1axHgqvLCVEPodIx45nWUqF96PUyIB2H51VZCTPaxeefpdKzgPR0Ji24zIeFhaowk7i2znPnNDINvA==
    5. Put the signature string into HTTP header “ X-SIGNATURE“.

      The following is the example value:

      X-SIGNATURE: iSkd8HPpdeeQSnq5lSRM46l8w/C4ZhNq7ordOv2dfDC0A0rGWxqz+9j864gcuVhu0tgTHJUuV9k5wsluig/sJ4W5Yy1EZPzbpeeUwFxSK0WgnW5LLq/h5RQAgVEyJL5MI1KrByzBQIv+5IYgKaLFmTLeo4xy7ToLJKND/6Ja+HRuo+SpnzNA2NNJEcc+PI87pAo0yXItZhjUXhyz9rkv0P8Ra8tDar2asHVGxA5BiGthy/eyPbe9VYavfMrOKAZpISw9VVoZ1axHgqvLCVEPodIx45nWUqF96PUyIB2H51VZCTPaxeefpdKzgPR0Ji24zIeFhaowk7i2znPnNDINvA==

Digital Signature Validation

The following steps are used to explain how to validate the digital signature used by the receiver of APIs:

  1. Take the signature from HTTP header “ X-SIGNATURE“ from the sender of APIs.

    The following is the example:

    X-SIGNATURE: iSkd8HPpdeeQSnq5lSRM46l8w/C4ZhNq7ordOv2dfDC0A0rGWxqz+9j864gcuVhu0tgTHJUuV9k5wsluig/sJ4W5Yy1EZPzbpeeUwFxSK0WgnW5LLq/h5RQAgVEyJL5MI1KrByzBQIv+5IYgKaLFmTLeo4xy7ToLJKND/6Ja+HRuo+SpnzNA2NNJEcc+PI87pAo0yXItZhjUXhyz9rkv0P8Ra8tDar2asHVGxA5BiGthy/eyPbe9VYavfMrOKAZpISw9VVoZ1axHgqvLCVEPodIx45nWUqF96PUyIB2H51VZCTPaxeefpdKzgPR0Ji24zIeFhaowk7i2znPnNDINvA==
  2. Compose the string to verify

    <HTTP METHOD> + ”:” + <RELATIVE PATH URL> + “:“ + LowerCase(HexEncode(SHA-256(Minify(<HTTP BODY>)))) + “:“ + <X-TIMESTAMP>

    The following is the example:

    POST:/v1.0/balance-inquiry.htm:e9295c3253c05560273ff305d9eea6abf77fff65229bf90b1781383c09c29d98:2022-11-30T09:45:35+07:00
  3. Verify the correctness of the signature based on SHA-256 with RSA-2048 encryption signing against the string to sign with provided public key of sender of APIs. And don't forget to decode public key and signature before used it.

  4. If the verification is correct, then consume the request.

  5. Tools

    The following are the example tools which used to process the signature:

I will show you how to validate signature in several way : A. Go

package main
import (
	"crypto"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"strings"
)

// verifySignature verifies an asymmetric signature
func verifySignature(signature, payload, httpMethod, url, timestamp, publicKey string) bool {
	// Create string to sign
	stringToSign := createSignToKey(payload, url, httpMethod, timestamp)
	fmt.Printf("String to sign: %s\n", stringToSign)

	// Verify signature
	isVerified, err := verify(signature, publicKey, stringToSign)
	if err != nil {
		fmt.Printf("Error verifying signature: %v\n", err)
		return false
	}

	return isVerified
}

// createSignToKey creates the content that was originally signed
// Implements the logic from the provided Kotlin function
func createSignToKey(payload, url, httpMethod, timestamp string) string {
	minifiedPayload := minifyJsonString(payload)
	payloadHash := digestHexSHA256(minifiedPayload)
	payloadHashLower := strings.ToLower(payloadHash)

	return httpMethod + ":" + url + ":" + payloadHashLower + ":" + timestamp
}

// minifyJsonString removes unnecessary whitespace from JSON string
func minifyJsonString(jsonStr string) string {
	var jsonObj interface{}
	err := json.Unmarshal([]byte(jsonStr), &jsonObj)
	if err != nil {
		// If there's an error parsing, return original string
		return jsonStr
	}

	// Re-marshal to get minified version
	minified, err := json.Marshal(jsonObj)
	if err != nil {
		return jsonStr
	}

	return string(minified)
}

// digestHexSHA256 computes SHA-256 hash and returns hex string
func digestHexSHA256(input string) string {
	hasher := sha256.New()
	hasher.Write([]byte(input))
	hashBytes := hasher.Sum(nil)
	return hex.EncodeToString(hashBytes)
}

// verify checks if the signature is valid
func verify(signature, publicKey, content string) (bool, error) {
	if signature == "" {
		return false, nil
	}

	contentBytes := []byte(content)

	// Decode base64 signature
	signatureBytes, err := base64.StdEncoding.DecodeString(signature)
	if err != nil {
		return false, fmt.Errorf("failed to decode signature: %w", err)
	}

	// Decode base64 public key
	publicKeyBytes, err := base64.StdEncoding.DecodeString(publicKey)
	if err != nil {
		return false, fmt.Errorf("failed to decode public key: %w", err)
	}

	// Verify using RSA
	return verifyRSA(contentBytes, signatureBytes, publicKeyBytes)
}

// verifyRSA performs RSA signature verification
func verifyRSA(data, signature, publicKeyBytes []byte) (bool, error) {
	// Transform public key bytes to rsa.PublicKey
	publicKey, err := parsePublicKey(publicKeyBytes)
	if err != nil {
		return false, err
	}

	// Hash the data using SHA-256
	hashed := sha256.Sum256(data)

	// Verify the signature
	err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hashed[:], signature)
	if err != nil {
		return false, err
	}

	return true, nil
}

// parsePublicKey converts raw public key bytes to an RSA public key
func parsePublicKey(data []byte) (*rsa.PublicKey, error) {
	pubKey, err := x509.ParsePKIXPublicKey(data)
	if err != nil {
		return nil, fmt.Errorf("failed to parse public key: %w", err)
	}

	rsaPublicKey, ok := pubKey.(*rsa.PublicKey)
	if !ok {
		return nil, fmt.Errorf("not an RSA public key")
	}

	return rsaPublicKey, nil
}

func main() {
	// Example usage
	signature := "YOUR_BASE64_SIGNATURE"
	payload := "{\"transactionId\":\"123\",\"amount\":\"100.00\"}"
	httpMethod := "POST"
	url := "/api/v2/payments/notification"
	timestamp := "1714465371"
	publicKey := "YOUR_BASE64_PUBLIC_KEY"

	// Verify signature
	isValid := verifySignature(signature, payload, httpMethod, url, timestamp, publicKey)

	if isValid {
		fmt.Println("Signature is valid!")
	} else {
		fmt.Println("Signature verification failed!")
	}
}

B. PHP

<?php

/**
 * Verify asymmetric signature
 * 
 * @param string $signature Base64 encoded signature
 * @param string $payload JSON payload
 * @param string $httpMethod HTTP method (e.g., "POST")
 * @param string $url Endpoint URL
 * @param string $timestamp Request timestamp
 * @param string $publicKey Base64 encoded public key
 * @return bool True if signature is valid, false otherwise
 */
function verifySignature($signature, $payload, $httpMethod, $url, $timestamp, $publicKey) {
    try {
        // Create string to sign
        $stringToSign = createSignToKey($payload, $url, $httpMethod, $timestamp);
        echo "String to sign: " . $stringToSign . PHP_EOL;
        
        // Verify signature
        $isVerified = verify($signature, $publicKey, $stringToSign);
        if (!$isVerified) {
            echo "Failed to verify signature: " . $signature . PHP_EOL;
            return false;
        }
        
        return true;
    } catch (Exception $e) {
        echo "Error verifying signature: " . $e->getMessage() . PHP_EOL;
        return false;
    }
}

/**
 * Create the string to be signed
 * 
 * @param string $payload JSON payload
 * @param string $url Endpoint URL
 * @param string $httpMethod HTTP method
 * @param string $timestamp Request timestamp
 * @return string String to be signed
 */
function createSignToKey($payload, $url, $httpMethod, $timestamp) {
    $minifiedPayload = minifyJsonString($payload);
    $payloadHash = digestHexSHA256($minifiedPayload);
    $payloadHashLower = strtolower($payloadHash);
    
    return $httpMethod . ":" . $url . ":" . $payloadHashLower . ":" . $timestamp;
}

/**
 * Minify JSON string
 * 
 * @param string $jsonStr JSON string
 * @return string Minified JSON string
 */
function minifyJsonString($jsonStr) {
    $jsonObj = json_decode($jsonStr);
    if (json_last_error() !== JSON_ERROR_NONE) {
        // If there's an error parsing, return original string
        return $jsonStr;
    }
    
    // Re-encode to get minified version
    return json_encode($jsonObj, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

/**
 * Compute SHA-256 hash and return as hex string
 * 
 * @param string $input Input string
 * @return string Hex encoded SHA-256 hash
 */
function digestHexSHA256($input) {
    return hash('sha256', $input);
}

/**
 * Verify signature with public key
 * 
 * @param string $signature Base64 encoded signature
 * @param string $publicKey Base64 encoded public key
 * @param string $content Content that was signed
 * @return bool True if signature is valid
 */
function verify($signature, $publicKey, $content) {
    if (empty($signature)) {
        return false;
    }
    
    // Decode base64 signature and public key
    $signatureBytes = base64_decode($signature);
    $publicKeyBytes = base64_decode($publicKey);
    
    if ($signatureBytes === false || $publicKeyBytes === false) {
        throw new Exception("Failed to decode base64 signature or public key");
    }
    
    // Create public key resource
    $publicKeyResource = openssl_pkey_get_public($publicKeyBytes);
    if ($publicKeyResource === false) {
        throw new Exception("Failed to parse public key: " . openssl_error_string());
    }
    
    // Verify signature
    $result = openssl_verify($content, $signatureBytes, $publicKeyResource, OPENSSL_ALGO_SHA256);
    
    // Free the key resource
    openssl_free_key($publicKeyResource);
    
    if ($result === 1) {
        return true;
    } else if ($result === 0) {
        return false;
    } else {
        throw new Exception("Error during signature verification: " . openssl_error_string());
    }
}

// Example usage
function main() {
    $signature = "YOUR_BASE64_SIGNATURE";
    $payload = '{"transactionId":"123","amount":"100.00"}';
    $httpMethod = "POST";
    $url = "/api/v2/payments/notification";
    $timestamp = "1714465371";
    $publicKey = "YOUR_BASE64_PUBLIC_KEY";
    
    $isValid = verifySignature($signature, $payload, $httpMethod, $url, $timestamp, $publicKey);
    
    if ($isValid) {
        echo "Signature is valid!" . PHP_EOL;
    } else {
        echo "Signature verification failed!" . PHP_EOL;
    }
}

// Run the example
main();
?>

C. Java

import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import com.fasterxml.jackson.databind.ObjectMapper;

public class SignatureVerifier {
    
    // verifySignature verifies an asymmetric signature
    public static boolean verifySignature(String signature, String payload, String httpMethod, 
                                         String url, String timestamp, String publicKey) {
        // Create string to sign
        String stringToSign = createSignToKey(payload, url, httpMethod, timestamp);
        System.out.printf("String to sign: %s\n", stringToSign);
        
        // Verify signature
        try {
            return verify(signature, publicKey, stringToSign);
        } catch (Exception e) {
            System.out.printf("Error verifying signature: %s\n", e.getMessage());
            return false;
        }
    }
    
    // createSignToKey creates the content that was originally signed
    private static String createSignToKey(String payload, String url, String httpMethod, String timestamp) {
        String minifiedPayload = minifyJsonString(payload);
        String payloadHash = digestHexSHA256(minifiedPayload);
        String payloadHashLower = payloadHash.toLowerCase();
        return httpMethod + ":" + url + ":" + payloadHashLower + ":" + timestamp;
    }
    
    // minifyJsonString removes unnecessary whitespace from JSON string
    private static String minifyJsonString(String jsonStr) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            Object jsonObj = mapper.readValue(jsonStr, Object.class);
            return mapper.writeValueAsString(jsonObj);
        } catch (Exception e) {
            // If there's an error parsing, return original string
            return jsonStr;
        }
    }
    
    // digestHexSHA256 computes SHA-256 hash and returns hex string
    private static String digestHexSHA256(String input) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = digest.digest(input.getBytes(StandardCharsets.UTF_8));
            return bytesToHex(hashBytes);
        } catch (Exception e) {
            throw new RuntimeException("Failed to compute SHA-256 hash", e);
        }
    }
    
    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
    
    // verify checks if the signature is valid
    private static boolean verify(String signature, String publicKey, String content) throws Exception {
        if (signature == null || signature.isEmpty()) {
            return false;
        }
        
        byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8);
        
        // Decode base64 signature
        byte[] signatureBytes = Base64.getDecoder().decode(signature);
        
        // Decode base64 public key
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey);
        
        // Verify using RSA
        return verifyRSA(contentBytes, signatureBytes, publicKeyBytes);
    }
    
    // verifyRSA performs RSA signature verification
    private static boolean verifyRSA(byte[] data, byte[] signature, byte[] publicKeyBytes) throws Exception {
        // Transform public key bytes to PublicKey
        PublicKey publicKey = parsePublicKey(publicKeyBytes);
        
        // Create Signature instance for RSA with SHA-256
        Signature sig = Signature.getInstance("SHA256withRSA");
        sig.initVerify(publicKey);
        sig.update(data);
        
        // Verify the signature
        return sig.verify(signature);
    }
    
    // parsePublicKey converts raw public key bytes to a PublicKey
    private static PublicKey parsePublicKey(byte[] data) throws Exception {
        X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePublic(spec);
    }
    
    public static void main(String[] args) {
        // Example usage
        String signature = "YOUR_BASE64_SIGNATURE";
        String payload = "{\"transactionId\":\"123\",\"amount\":\"100.00\"}";
        String httpMethod = "POST";
        String url = "/api/v2/payments/notification";
        String timestamp = "1714465371";
        String publicKey = "YOUR_BASE64_PUBLIC_KEY";
        
        // Verify signature
        boolean isValid = verifySignature(signature, payload, httpMethod, url, timestamp, publicKey);
        if (isValid) {
            System.out.println("Signature is valid!");
        } else {
            System.out.println("Signature verification failed!");
        }
    }
}

D. Kotlin

import com.fasterxml.jackson.databind.ObjectMapper
import java.nio.charset.StandardCharsets
import java.security.KeyFactory
import java.security.MessageDigest
import java.security.PublicKey
import java.security.Signature
import java.security.spec.X509EncodedKeySpec
import java.util.Base64

class SignatureVerifier {
    companion object {
        /**
         * Verifies an asymmetric signature
         */
        fun verifySignature(
            signature: String,
            payload: String,
            httpMethod: String,
            url: String,
            timestamp: String,
            publicKey: String
        ): Boolean {
            // Create string to sign
            val stringToSign = createSignToKey(payload, url, httpMethod, timestamp)
            println("String to sign: $stringToSign")
            
            // Verify signature
            return try {
                verify(signature, publicKey, stringToSign)
            } catch (e: Exception) {
                println("Error verifying signature: ${e.message}")
                false
            }
        }
        
        /**
         * Creates the content that was originally signed
         */
        private fun createSignToKey(payload: String, url: String, httpMethod: String, timestamp: String): String {
            val minifiedPayload = minifyJsonString(payload)
            val payloadHash = digestHexSHA256(minifiedPayload)
            val payloadHashLower = payloadHash.lowercase()
            return "$httpMethod:$url:$payloadHashLower:$timestamp"
        }
        
        /**
         * Removes unnecessary whitespace from JSON string
         */
        private fun minifyJsonString(jsonStr: String): String {
            return try {
                val mapper = ObjectMapper()
                val jsonObj = mapper.readValue(jsonStr, Any::class.java)
                mapper.writeValueAsString(jsonObj)
            } catch (e: Exception) {
                // If there's an error parsing, return original string
                jsonStr
            }
        }
        
        /**
         * Computes SHA-256 hash and returns hex string
         */
        private fun digestHexSHA256(input: String): String {
            val digest = MessageDigest.getInstance("SHA-256")
            val hashBytes = digest.digest(input.toByteArray(StandardCharsets.UTF_8))
            return bytesToHex(hashBytes)
        }
        
        private fun bytesToHex(bytes: ByteArray): String {
            return bytes.joinToString("") { byte -> "%02x".format(byte.toInt() and 0xFF) }
        }
        
        /**
         * Checks if the signature is valid
         */
        private fun verify(signature: String, publicKey: String, content: String): Boolean {
            if (signature.isEmpty()) {
                return false
            }
            
            val contentBytes = content.toByteArray(StandardCharsets.UTF_8)
            
            // Decode base64 signature
            val signatureBytes = Base64.getDecoder().decode(signature)
            
            // Decode base64 public key
            val publicKeyBytes = Base64.getDecoder().decode(publicKey)
            
            // Verify using RSA
            return verifyRSA(contentBytes, signatureBytes, publicKeyBytes)
        }
        
        /**
         * Performs RSA signature verification
         */
        private fun verifyRSA(data: ByteArray, signature: ByteArray, publicKeyBytes: ByteArray): Boolean {
            // Transform public key bytes to PublicKey
            val publicKey = parsePublicKey(publicKeyBytes)
            
            // Create Signature instance for RSA with SHA-256
            val sig = Signature.getInstance("SHA256withRSA")
            sig.initVerify(publicKey)
            sig.update(data)
            
            // Verify the signature
            return sig.verify(signature)
        }
        
        /**
         * Converts raw public key bytes to a PublicKey
         */
        private fun parsePublicKey(data: ByteArray): PublicKey {
            val spec = X509EncodedKeySpec(data)
            val kf = KeyFactory.getInstance("RSA")
            return kf.generatePublic(spec)
        }
    }
}

fun main() {
    // Example usage
    val signature = "YOUR_BASE64_SIGNATURE"
    val payload = """{"transactionId":"123","amount":"100.00"}"""
    val httpMethod = "POST"
    val url = "/api/v2/payments/notification"
    val timestamp = "1714465371"
    val publicKey = "YOUR_BASE64_PUBLIC_KEY"
    
    // Verify signature
    val isValid = SignatureVerifier.verifySignature(signature, payload, httpMethod, url, timestamp, publicKey)
    if (isValid) {
        println("Signature is valid!")
    } else {
        println("Signature verification failed!")
    }
}

PreviousWithdraw ProcessNextNetzme

Last updated 22 days ago

No
Name
URL
Description
Step

1

JSON Minify

This tool is used to minify the request body

  1. Put the request body

  2. Select “Minify JSON”

  3. Grab and copy the value

2

SHA256

This tool is used to do Lowercase(HexEncode(SHA-256(RequestBody)))

  1. Select UTF-8 on Input Type

  2. Put the minify the request body

  3. Grab and copy the value

3

RSA Signature/Generation & Validation

This tool is used to do signature and validation of signature

  1. Generation

    • Select 2048 bit on Generate RSA Key Size

    • Select Generate Signature

    • Put the ClearText Message with string to sign

    • Select SHA256withRSA on RSA Signature Algorithms

    • Grab and copy the value

    • Select 2048 bit on Generate RSA Key Size

    • Select Generate Signature

    • Put the Private Key

    • Put the ClearText Message with string to sign

    • Select SHA256withRSA on RSA Signature Algorithms

    • Grab and copy the value

  2. Validation

    1. Select 2048 bit on Generate RSA Key Size

    2. Select Verify Signature

    3. Put the provided Public Key

    4. Put the Private Key

    5. Put the ClearText Message with string to sign

    6. Put the Provide Signature Value (Base64) with the provided X-SIGNATURE

    7. Select SHA256withRSA on RSA Signature Algorithms

    8. See the result, either verification passed or failed

https://jsonformatter.org/json-minify
https://emn178.github.io/online-tools/sha256.html
https://8gwifi.org/rsasignverifyfunctions. jsp#google_vignette