Skip to main content

Examples

Note: The following code examples are provided solely for demonstrating the signature calculation process. In real-world applications, you must implement proper error handling, securely load and manage private keys, and follow best security practices. Do not hardcode sensitive information such as private keys in production environments. This document provides example code for implementing MidasPay signature calculation in different programming languages. Each example includes the complete signature calculation process:

  1. Constructing the signature string
  2. Signing with private key
  3. Generating the final Authorization header

Java Example

import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import javax.crypto.Cipher;

public class MidasPaySignature {
private static final String PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" +
"MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDJxDq2/Y1nZFJh\n" +
// ... Your private key content here ...
"-----END PRIVATE KEY-----";

public static String generateSignature(String httpMethod, String url, String timestamp,
String nonceStr, String requestBody) throws Exception {
// Construct signature string
String signatureStr = String.format("%s\n%s\n%s\n%s\n%s\n",
httpMethod.toUpperCase(), url, timestamp, nonceStr, requestBody);

// Load private key
String privateKeyPEM = PRIVATE_KEY
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s", "");

byte[] encoded = Base64.getDecoder().decode(privateKeyPEM);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

// Calculate signature
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(signatureStr.getBytes("UTF-8"));
byte[] signed = signature.sign();

// Base64 encode
return Base64.getEncoder().encodeToString(signed);
}

public static String generateAuthHeader(String merchantId, String serialNo,
String nonceStr, String timestamp,
String signature) {
return String.format("TXGW-SHA256-RSA2048 auth_id=\"%s\",auth_id_type=MERCHANT_ID," +
"nonce_str=\"%s\",signature=\"%s\",timestamp=\"%s\",serial_no=\"%s\"",
merchantId, nonceStr, signature, timestamp, serialNo);
}

public static void main(String[] args) throws Exception {
String httpMethod = "POST";
String url = "/v1/mor/token/create";
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String nonceStr = generateNonceStr();
String requestBody = "{}";
String merchantId = "TestMerchant";
String serialNo = "6C6E66C7F23578C09E8ACE0C20D36F11A678C836";

String signature = generateSignature(httpMethod, url, timestamp, nonceStr, requestBody);
String authHeader = generateAuthHeader(merchantId, serialNo, nonceStr, timestamp, signature);

System.out.println("Authorization: " + authHeader);
}

private static String generateNonceStr() {
byte[] randomBytes = new byte[16];
new SecureRandom().nextBytes(randomBytes);
StringBuilder sb = new StringBuilder();
for (byte b : randomBytes) {
sb.append(String.format("%02X", b));
}
return sb.toString();
}
}

Python Example

import base64
import hashlib
import os
import time
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.hazmat.backends import default_backend

class MidasPaySignature:
def __init__(self, private_key_path=None, private_key_string=None):
if private_key_path:
with open(private_key_path, 'rb') as key_file:
self.private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
elif private_key_string:
self.private_key = serialization.load_pem_private_key(
private_key_string.encode(),
password=None,
backend=default_backend()
)
else:
raise ValueError("Either private_key_path or private_key_string must be provided")

def generate_signature(self, http_method, url, timestamp, nonce_str, request_body):
# Construct signature string
signature_str = f"{http_method.upper()}\n{url}\n{timestamp}\n{nonce_str}\n{request_body}\n"

# Calculate signature
signature = self.private_key.sign(
signature_str.encode(),
padding.PKCS1v15(),
hashes.SHA256()
)

# Base64 encode
return base64.b64encode(signature).decode()

def generate_auth_header(self, merchant_id, serial_no, nonce_str, timestamp, signature):
return (f'TXGW-SHA256-RSA2048 auth_id="{merchant_id}",auth_id_type=MERCHANT_ID,'
f'nonce_str="{nonce_str}",signature="{signature}",timestamp="{timestamp}",'
f'serial_no="{serial_no}"')

def generate_nonce_str():
return ''.join([format(b, '02X') for b in os.urandom(16)])

# Usage example
if __name__ == "__main__":
private_key = """-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDJxDq2/Y1nZFJh
# ... Your private key content here ...
-----END PRIVATE KEY-----"""

signer = MidasPaySignature(private_key_string=private_key)

http_method = "POST"
url = "/v1/mor/token/create"
timestamp = str(int(time.time()))
nonce_str = generate_nonce_str()
request_body = "{}"
merchant_id = "TestMerchant"
serial_no = "6C6E66C7F23578C09E8ACE0C20D36F11A678C836"

signature = signer.generate_signature(http_method, url, timestamp, nonce_str, request_body)
auth_header = signer.generate_auth_header(merchant_id, serial_no, nonce_str, timestamp, signature)

print(f"Authorization: {auth_header}")

Node.js Example

const crypto = require('crypto');
const fs = require('fs');

class MidasPaySignature {
constructor(privateKeyPath = null, privateKeyString = null) {
if (privateKeyPath) {
this.privateKey = fs.readFileSync(privateKeyPath, 'utf8');
} else if (privateKeyString) {
this.privateKey = privateKeyString;
} else {
throw new Error('Either privateKeyPath or privateKeyString must be provided');
}
}

generateSignature(httpMethod, url, timestamp, nonceStr, requestBody) {
// Construct signature string
const signatureStr = `${httpMethod.toUpperCase()}\n${url}\n${timestamp}\n${nonceStr}\n${requestBody}\n`;

// Calculate signature
const sign = crypto.createSign('RSA-SHA256');
sign.update(signatureStr);
const signature = sign.sign(this.privateKey, 'base64');

return signature;
}

generateAuthHeader(merchantId, serialNo, nonceStr, timestamp, signature) {
return `TXGW-SHA256-RSA2048 auth_id="${merchantId}",auth_id_type=MERCHANT_ID,` +
`nonce_str="${nonceStr}",signature="${signature}",timestamp="${timestamp}",` +
`serial_no="${serialNo}"`;
}
}

function generateNonceStr() {
return crypto.randomBytes(16).toString('hex').toUpperCase();
}

// Usage example
const privateKey = `-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDJxDq2/Y1nZFJh
# ... Your private key content here ...
-----END PRIVATE KEY-----`;

const signer = new MidasPaySignature(null, privateKey);

const httpMethod = 'POST';
const url = '/v1/mor/token/create';
const timestamp = Math.floor(Date.now() / 1000).toString();
const nonceStr = generateNonceStr();
const requestBody = '{}';
const merchantId = 'TestMerchant';
const serialNo = '6C6E66C7F23578C09E8ACE0C20D36F11A678C836';

const signature = signer.generateSignature(httpMethod, url, timestamp, nonceStr, requestBody);
const authHeader = signer.generateAuthHeader(merchantId, serialNo, nonceStr, timestamp, signature);

console.log(`Authorization: ${authHeader}`);

Go Example

package main

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

type MidasPaySignature struct {
privateKey *rsa.PrivateKey
}

func NewMidasPaySignature(privateKeyPEM string) (*MidasPaySignature, error) {
block, _ := pem.Decode([]byte(privateKeyPEM))
if block == nil {
return nil, fmt.Errorf("failed to parse PEM block containing the key")
}

privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}

rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey)
if !ok {
return nil, fmt.Errorf("not an RSA private key")
}

return &MidasPaySignature{privateKey: rsaPrivateKey}, nil
}

func (s *MidasPaySignature) GenerateSignature(httpMethod, url, timestamp, nonceStr, requestBody string) (string, error) {
// Construct signature string
signatureStr := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n",
strings.ToUpper(httpMethod), url, timestamp, nonceStr, requestBody)


// Calculate signature
hashed := sha256.Sum256([]byte(signatureStr))
signature, err := rsa.SignPKCS1v15(rand.Reader, s.privateKey, crypto.SHA256, hashed[:])
if err != nil {
return "", err
}

// Base64 encode
return base64.StdEncoding.EncodeToString(signature), nil
}

func (s *MidasPaySignature) GenerateAuthHeader(merchantId, serialNo, nonceStr, timestamp, signature string) string {
return fmt.Sprintf(`TXGW-SHA256-RSA2048 auth_id="%s",auth_id_type=MERCHANT_ID,`+
`nonce_str="%s",signature="%s",timestamp="%s",serial_no="%s"`,
merchantId, nonceStr, signature, timestamp, serialNo)
}

func generateNonceStr() string {
b := make([]byte, 16)
rand.Read(b)
return fmt.Sprintf("%X", b)
}

func main() {
privateKey := `-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDJxDq2/Y1nZFJh
# ... Your private key content here ...
-----END PRIVATE KEY-----`

signer, err := NewMidasPaySignature(privateKey)
if err != nil {
fmt.Printf("Error creating signer: %v\n", err)
return
}

httpMethod := "POST"
url := "/v1/mor/token/create"
timestamp := fmt.Sprintf("%d", time.Now().Unix())
nonceStr := generateNonceStr()
requestBody := "{}"
merchantId := "TestMerchant"
serialNo := "6C6E66C7F23578C09E8ACE0C20D36F11A678C836"

signature, err := signer.GenerateSignature(httpMethod, url, timestamp, nonceStr, requestBody)
if err != nil {
fmt.Printf("Error generating signature: %v\n", err)
return
}

authHeader := signer.GenerateAuthHeader(merchantId, serialNo, nonceStr, timestamp, signature)
fmt.Printf("Authorization: %s\n", authHeader)
}

PHP Example

<?php
class MidasPaySignature {
private $privateKey;

public function __construct($privateKeyPath = null, $privateKeyString = null) {
if ($privateKeyPath) {
$this->privateKey = file_get_contents($privateKeyPath);
} elseif ($privateKeyString) {
$this->privateKey = $privateKeyString;
} else {
throw new Exception("Either privateKeyPath or privateKeyString must be provided");
}
}

public function generateSignature($httpMethod, $url, $timestamp, $nonceStr, $requestBody) {
$signatureStr = sprintf("%s\n%s\n%s\n%s\n%s\n",
strtoupper($httpMethod), $url, $timestamp, $nonceStr, $requestBody);

$privateKey = openssl_pkey_get_private($this->privateKey);
if (!$privateKey) {
throw new Exception("Invalid private key");
}

openssl_sign($signatureStr, $signature, $privateKey, OPENSSL_ALGO_SHA256);
openssl_free_key($privateKey);

return base64_encode($signature);
}

public function generateAuthHeader($merchantId, $serialNo, $nonceStr, $timestamp, $signature) {
return sprintf('TXGW-SHA256-RSA2048 auth_id="%s",auth_id_type=MERCHANT_ID,nonce_str="%s",signature="%s",timestamp="%s",serial_no="%s"',
$merchantId, $nonceStr, $signature, $timestamp, $serialNo);
}
}

function generateNonceStr() {
return strtoupper(bin2hex(random_bytes(16)));
}

// Usage example
$privateKey = <<<EOD
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDJxDq2/Y1nZFJh
# ... Your private key content here ...
-----END PRIVATE KEY-----
EOD;

// WARNING: Do NOT hardcode your private key in production. Load it securely and handle errors properly.
$signer = new MidasPaySignature(null, $privateKey);
$httpMethod = "POST";
$url = "/v1/mor/token/create";
$timestamp = strval(time());
$nonceStr = generateNonceStr();
$requestBody = "{}";
$merchantId = "TestMerchant";
$serialNo = "6C6E66C7F23578C09E8ACE0C20D36F11A678C836";

$signature = $signer->generateSignature($httpMethod, $url, $timestamp, $nonceStr, $requestBody);
// In production, check if $signature is generated successfully and handle errors/logging as needed.
$authHeader = $signer->generateAuthHeader($merchantId, $serialNo, $nonceStr, $timestamp, $signature);

echo "Authorization: $authHeader\n";
?>

C# Example

using System;
using System.Security.Cryptography;
using System.Text;

public class MidasPaySignature
{
private RSA _privateKey;

public MidasPaySignature(string privateKeyPem)
{
_privateKey = RSA.Create();
_privateKey.ImportFromPem(privateKeyPem.ToCharArray());
}

public string GenerateSignature(string httpMethod, string url, string timestamp, string nonceStr, string requestBody)
{
string signatureStr = $"{httpMethod.ToUpper()}\n{url}\n{timestamp}\n{nonceStr}\n{requestBody}\n";
byte[] data = Encoding.UTF8.GetBytes(signatureStr);
byte[] signed = _privateKey.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
return Convert.ToBase64String(signed);
}

public string GenerateAuthHeader(string merchantId, string serialNo, string nonceStr, string timestamp, string signature)
{
return $"TXGW-SHA256-RSA2048 auth_id=\"{merchantId}\",auth_id_type=MERCHANT_ID,nonce_str=\"{nonceStr}\",signature=\"{signature}\",timestamp=\"{timestamp}\",serial_no=\"{serialNo}\"";
}

public static string GenerateNonceStr()
{
var rng = RandomNumberGenerator.Create();
byte[] bytes = new byte[16];
rng.GetBytes(bytes);
StringBuilder sb = new StringBuilder();
foreach (var b in bytes)
sb.Append(b.ToString("X2"));
return sb.ToString();
}
}

// Usage example
string privateKey = @"-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDJxDq2/Y1nZFJh
# ... Your private key content here ...
-----END PRIVATE KEY-----";

// WARNING: Do NOT hardcode your private key in production. Load it securely and add proper error handling and logging.
var signer = new MidasPaySignature(privateKey);
string httpMethod = "POST";
string url = "/v1/mor/token/create";
string timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
string nonceStr = MidasPaySignature.GenerateNonceStr();
string requestBody = "{}";
string merchantId = "TestMerchant";
string serialNo = "6C6E66C7F23578C09E8ACE0C20D36F11A678C836";

string signature = signer.GenerateSignature(httpMethod, url, timestamp, nonceStr, requestBody);
// In production, check if signature is generated successfully and handle errors/logging as needed
string authHeader = signer.GenerateAuthHeader(merchantId, serialNo, nonceStr, timestamp, signature);

Console.WriteLine($"Authorization: {authHeader}");

Ruby Example

require 'openssl'
require 'base64'
require 'securerandom'

class MidasPaySignature
def initialize(private_key_pem)
@private_key = OpenSSL::PKey::RSA.new(private_key_pem)
end

def generate_signature(http_method, url, timestamp, nonce_str, request_body)
signature_str = "#{http_method.upcase}\n#{url}\n#{timestamp}\n#{nonce_str}\n#{request_body}\n"
signature = @private_key.sign(OpenSSL::Digest::SHA256.new, signature_str)
Base64.strict_encode64(signature)
end

def generate_auth_header(merchant_id, serial_no, nonce_str, timestamp, signature)
"TXGW-SHA256-RSA2048 auth_id=\"#{merchant_id}\",auth_id_type=MERCHANT_ID,nonce_str=\"#{nonce_str}\",signature=\"#{signature}\",timestamp=\"#{timestamp}\",serial_no=\"#{serial_no}\""
end
end

def generate_nonce_str
SecureRandom.hex(16).upcase
end

# Usage example
private_key = <<~KEY
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDJxDq2/Y1nZFJh
# ... Your private key content here ...
-----END PRIVATE KEY-----
KEY

# WARNING: Do NOT hardcode your private key in production. Load it securely and add proper error handling and logging.
signer = MidasPaySignature.new(private_key)
http_method = "POST"
url = "/v1/mor/token/create"
timestamp = Time.now.to_i.to_s
nonce_str = generate_nonce_str
request_body = "{}"
merchant_id = "TestMerchant"
serial_no = "6C6E66C7F23578C09E8ACE0C20D36F11A678C836"

signature = signer.generate_signature(http_method, url, timestamp, nonce_str, request_body)
# In production, check if signature is generated successfully and handle errors/logging as needed
auth_header = signer.generate_auth_header(merchant_id, serial_no, nonce_str, timestamp, signature)

puts "Authorization: #{auth_header}"