Docs

Examples

Signature authentication examples for various languages

C#

This makes use of the BouncyCastle.Cryptography and Newtonsoft.Json NuGet Packages

using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.OpenSsl;

// Make sure to include the BEGIN/END headers AND the newlines
var privateKeyText = "-----BEGIN EC PRIVATE KEY-----\nXXXXX-----\nEND EC PRIVATE KEY-----";

// Simple POCO object to represent a transfer
InternalTransfer internalTransfer = new()
{
    FromAccount = "1234",
    ToAccount = "4321",
    Amount = 300,
    Description = "Test transfer"
};
var nonce = Guid.NewGuid().ToString();
var date = DateTime.UtcNow.ToString("R");
var body = JsonConvert.SerializeObject(internalTransfer, new JsonSerializerSettings()
{
    ContractResolver = new DefaultContractResolver()
    {
        NamingStrategy = new SnakeCaseNamingStrategy()
    }
});
var rawSignature= body + date + nonce;

var pemKeyPair = (AsymmetricCipherKeyPair)new PemReader(new StringReader(privateKeyText)).ReadObject();
ISigner? signer = SignerUtilities.GetSigner("SHA256withECDSA");
var ecPrivKey = (ECPrivateKeyParameters)pemKeyPair.Private;
signer.Init(true, ecPrivKey);
signer.BlockUpdate(Encoding.UTF8.GetBytes(rawSignature), 0, rawSignature.Length);
var signature = Convert.ToBase64String(signer.GenerateSignature());

var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api-sandbox.utb.com/api/v1/transfer/internal");
request.Headers.Add("Accept", "application/json");
request.Headers.Add("X-UTB-Subscription-Key", "SUBSCRIPTION_KEY");
request.Headers.Add("X-UTB-Signature", signature);
request.Headers.Add("X-UTB-Signature-Nonce", nonce);
request.Headers.Add("Date", date);
request.Headers.Add("X-UTB-Signature-Version", "v1");
request.Content = new StringContent(body, null, "application/json");
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());

Python

This makes uses of the ecdsa package

import ecdsa
from ecdsa.util import sigencode_der
from hashlib import sha256
import base64
import uuid
import locale, datetime
import http.client
import hashlib
import json

# Make sure to include the BEGIN/END headers AND the newlines
private_key = "-----BEGIN EC PRIVATE KEY-----\nXXXXX\n-----END EC PRIVATE KEY-----"

internal_transfer = {
  "from_account": "1234",
  "to_account": "4321",
  "amount": 300,
  "description": "Test transfer"
}
body = json.dumps(internal_transfer)
nonce = str(uuid.uuid4())
date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
rawsignature = body + date + nonce

sk = ecdsa.SigningKey.from_pem(private_key)
signed_message = sk.sign(rawsignature.encode(encoding='utf-8'), hashfunc = hashlib.sha256, sigencode=sigencode_der)
signature = base64.b64encode(signed_message)

conn = http.client.HTTPSConnection("api-sandbox.utb.com")
headers = {
  'Accept': 'application/json',
  'Content-Type': 'application/json',
  'X-UTB-Subscription-Key': "SUBSCRIPTION_KEY",
  'X-UTB-Signature': signature,
  'X-UTB-Signature-Nonce': nonce,
  'Date': date,
  'X-UTB-Signature-Version': "v1"
}
conn.request("POST", "/api/v1/transfer/internal", body, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

Java

This makes use of the org.bouncycastle:bcpkix-jdk15on:1.58, com.squareup.okhttp:okhttp:2.7.5 and com.google.code.gson:gson:2.9.0 libraries

import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.squareup.okhttp.*;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import java.io.IOException;
import java.io.StringReader;
import java.math.BigDecimal;
import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.text.SimpleDateFormat;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        // Make sure to include the BEGIN/END headers AND the newlines
        String privatekey = "-----BEGIN EC PRIVATE KEY-----\nXXXXX\n-----END EC PRIVATE KEY-----";
        PEMParser parser = new PEMParser(new StringReader(privatekey));
        KeyPair keyPair = new JcaPEMKeyConverter().setProvider("BC").getKeyPair((PEMKeyPair) parser.readObject());
        ECPrivateKey key = (ECPrivateKey) keyPair.getPrivate();
        Signature signer = Signature.getInstance("SHA256withECDSA");
        signer.initSign(key);

        SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));

        // Simple POJO object to represent a transfer
        InternalTransfer internalTransfer = new InternalTransfer();
        internalTransfer.setFromAccount("1234");
        internalTransfer.setToAccount("4321");
        internalTransfer.setAmount(new BigDecimal(300));
        internalTransfer.setDescription("Test transfer");

        Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
        String body = gson.toJson(internalTransfer);
        String date = dateFormat.format(Calendar.getInstance().getTime());
        String nonce = UUID.randomUUID().toString();
        String rawSignature = body + date + nonce;

        signer.update(rawSignature.getBytes("UTF8"));

        String signature = Base64.getEncoder().encodeToString(signer.sign());

        MediaType mediaType = MediaType.parse("application/json");
        RequestBody requestBody = RequestBody.create(mediaType, body);

        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("https://api-sandbox.utb.com/api/v1/transfer/internal")
                .method("POST", requestBody)
                .addHeader("Accept", "application/json")
                .addHeader("X-UTB-Subscription-Key", "SUBSCRIPTION_KEY")
                .addHeader("X-UTB-Signature", signature)
                .addHeader("X-UTB-Signature-Nonce", nonce)
                .addHeader("Date", date)
                .addHeader("X-UTB-Signature-Version", "v1")
                .build();
        Response response = client.newCall(request).execute();
        System.out.println(response.body().string());
    }
}

Node.js

This makes use of the jsrsasign, request and uuid packages

let request = require('request')
let rs = require('jsrsasign')
let uuid = require('uuid');

// Make sure to include the BEGIN/END headers AND the newlines
let privateKey = "-----BEGIN EC PRIVATE KEY-----\nXXXXX\n-----END EC PRIVATE KEY-----"

let body = JSON.stringify({
    "from_account": "1234",
    "to_account": "4321",
    "amount": 300,
    "description": "Test transfer"
})
let date = new Date().toUTCString();
let nonce = uuid.v4();
let rawSignature = body + date + nonce;

let sign = new rs.KJUR.crypto.Signature({"alg": "SHA256withECDSA"})
sign.init(privateKey)
let signature = Buffer.from(sign.signString(rawSignature), 'hex').toString('base64')
console.log(signature)

let options = {
    'method': 'POST',
    'url': 'https://api-sandbox.utb.com/api/v1/transfer/internal',
    'headers': {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'X-UTB-Subscription-Key': "SUBSCRIPTION_KEY",
        'X-UTB-Signature': signature,
        'X-UTB-Signature-Nonce': nonce,
        'Date': date,
        'X-UTB-Signature-Version': "v1"
    },
    body: body
};
request(options, function (error, response) {
    if (error) throw new Error(error);
    console.log(response.body);
});