---
title: Java language demo
slug: ki/java-language-demo
description: Learn how to build and sign requests for a specific API with this Java code snippet. Discover methods for generating signatures for GET and POST requests, along with examples of header and payload generation. Explore the use of cryptographic algorithms li
docTags: 
createdAt: 2023-06-30T03:29:04.282Z
---

```java
import cn.hutool.core.util.HexUtil;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.TimeZone;

public class SignatureDemo {

    private final static String PARTNER_CODE = "AKIDz8krbsJ5yKBZQpn74WFkmLPx3*******";
    private final static String PARTNER_TOKEN = "Gu5t9xGARNpq86cd98joQYCN3*******";
    private final static Charset UTF8 = StandardCharsets.UTF_8;
    private final static String SECRET_ID = PARTNER_CODE;
    private final static String SECRET_KEY = PARTNER_TOKEN;

    // prod
//    private final static String HOST = "api.klavi.ai";

    // dev
    private final static String HOST = "api-testing.klavi.ai";

    public static void main(String[] args) throws Exception {
//        buildGetInstitutionListSignature();
        buildSubmitCredentialsSignature();
//        buildCheckStatusSignature();
//        buildSubmitMFAInfoSignature();
//        buildUpdateProductsSignature();
//        buildDeleteAccountSignature();
    }

    private static void buildGetInstitutionListSignature() throws Exception {
        String httpRequestMethod = "GET";
        String canonicalUri = "/link/external/v2/getInstitutionList";
        String canonicalQueryString = "";
        String canonicalHeaders = "content-type:application/x-www-form-urlencoded\n" + "host:" + HOST + "\n";
        String signedHeaders = "content-type;host";
        String payload = "";
        String timestamp = getTimestamp();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));

        buildSignature(httpRequestMethod, canonicalUri, canonicalQueryString, canonicalHeaders, signedHeaders,
                payload, date, timestamp);
    }

    private static void buildSubmitCredentialsSignature() throws Exception {
        String httpRequestMethod = "POST";
        String canonicalUri = "/link/external/v2/submitCredentials";
        String canonicalQueryString = "";
        String canonicalHeaders = "content-type:application/json;charset=UTF-8\n" + "host:" + HOST + "\n";
        String signedHeaders = "content-type;host";
        String payload = "{\"cpf\":\"aw/6B0KMZRVbBIdUp0uB/pZz97ZJfJgO4LaBRm7bBvRTo25HNwW0GkcELlFuMuw0krXDQO9gLqat49LA" +
                "/tgofERQrOJe0saTJt0bgue3FLSgjPP06HLdCHMgY2ApwUlIO/1otGuNYMa+m7zeT7+Cs3zEscPfwU3bC4pz39zLwNM=\"," +
                "\"agency\":\"DvZXoz6wMQHfys81ak4GHK+A2/F3ClQ7rV2JxXEGDDBjenQG3rb/MvX" +
                "+PKTLaUCiL92ym2bEkfEzvkzJTvdQuZV1dXwyVjbsSByFA" +
                "+JbOcRdn0LtyFxcJzYLmPUwnwAVarWhKiwguE2cNbKqpdxmxkGVAN6g2ghnC4zNPpXFsYA=\"," +
                "\"account\":\"evltwIAmaE12SPDKwKspH9D9PDA9HbAXq1xkaMShZflWPCIwODyXZx6alFAz7U443ZZX0wfuMc" +
                "+IHcFBKYvjDFoVds0NfQjVfBvx2lcj/WXx9ZQpUjkUsOfbZnfUg2SW79Y5Y7PEaPFxsKgYXb1yZNRQwvmLLrbRZyDDxNnDnIA" +
                "=\",\"password\":\"XfGzloZbejN+S/4+be31aJr8HWdImYuMUZkn1nudYHwVvzvM4se6CH89gekXOUFvn1w" +
                "/VFWHu1JHBEIoiP57Qc3eJ1YbnddKl0Px1QqwVVW/+9shxbPmNoM36WY6Uebn/kxB0iGlsyhNytyBwVPyjow298" +
                "/UMuNw0PRe7esZKSo=\",\"institutionCode\":\"237\"," +
                "\"accountLevel\":\"VmWC5cxnerhoiEAD4sYNEmjEmG87XYymV6f1MSULPY8ETnRN" +
                "+SQM3eUAKUshL6k05JGtkkKfou52RsCYa7Mtec8ZurRdx6k6C1+dRNyZmsrVl9OtQBtvwxgtdlENgzRaombKH" +
                "/18kxnDPEBXCBf3FV7dtRaXL7j6CXFq3O86a4g=\"}\n";
        String timestamp = getTimestamp();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));

        buildSignature(httpRequestMethod, canonicalUri, canonicalQueryString, canonicalHeaders, signedHeaders,
                payload, date, timestamp);
    }

    private static void buildCheckStatusSignature() throws Exception {
        String httpRequestMethod = "GET";
        String canonicalUri = "/link/external/v2/checkStatus";
        String canonicalQueryString = "traceId=kJuktDQkvHezWtYyiPYOKwxr2ddByeb8";
        String canonicalHeaders = "content-type:application/x-www-form-urlencoded\n" + "host:" + HOST + "\n";
        String signedHeaders = "content-type;host";
        String payload = "";
        String timestamp = getTimestamp();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));

        buildSignature(httpRequestMethod, canonicalUri, canonicalQueryString, canonicalHeaders, signedHeaders,
                payload, date, timestamp);
    }

    private static void buildSubmitMFAInfoSignature() throws Exception {
        String httpRequestMethod = "POST";
        String canonicalUri = "/link/external/v2/submitMFAInfo";
        String canonicalQueryString = "";
        String canonicalHeaders = "content-type:application/json;charset=UTF-8\n" + "host:" + HOST + "\n";
        String signedHeaders = "content-type;host";
        String payload = "{\"traceId\":\"kJuktDQkvHezWtYyiPYOKwxr2ddByeb8\"," +
                "\"code\":\"mb6kW19VXYU9ZvRb3TzUJ0jeei2ACETOZkt67J5zBTIbDW" +
                "+7Y3qnq7WI3gHckFCsebGxArhobZ78ZhTVOZpApiJ9fBUXA7AX3b9LK8daCHtAodQquT6TcW0Flt2v305ELB4HGNwLFR3EO9L" +
                "/vX5UU1VjSe3+pGGJFl7y554nwmM=\"}";
        System.out.println(payload);
        String timestamp = getTimestamp();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));

        buildSignature(httpRequestMethod, canonicalUri, canonicalQueryString, canonicalHeaders, signedHeaders,
                payload, date, timestamp);
    }

    private static void buildUpdateProductsSignature() throws Exception {
        String httpRequestMethod = "POST";
        String canonicalUri = "/link/external/v2/updateProducts";
        String canonicalQueryString = "";
        String canonicalHeaders = "content-type:application/json;charset=UTF-8\n" + "host:" + HOST + "\n";
        String signedHeaders = "content-type;host";
        String payload = "{\"connectionKey\":\"1033b652e0c84acab018a9482cae3176\"}";
        String timestamp = getTimestamp();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));

        buildSignature(httpRequestMethod, canonicalUri, canonicalQueryString, canonicalHeaders, signedHeaders,
                payload, date, timestamp);
    }

    private static void buildDeleteAccountSignature() throws Exception {
        String httpRequestMethod = "POST";
        String canonicalUri = "/link/external/v2/deleteAccount";
        String canonicalQueryString = "";
        String canonicalHeaders = "content-type:application/json;charset=UTF-8\n" + "host:" + HOST + "\n";
        String signedHeaders = "content-type;host";
        String payload = "{\"connectionKey\":\"1033b652e0c84acab018a9482cae3176\"}";
        String timestamp = getTimestamp();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));

        buildSignature(httpRequestMethod, canonicalUri, canonicalQueryString, canonicalHeaders, signedHeaders,
                payload, date, timestamp);
    }

    private static void buildSignature(String httpRequestMethod, String canonicalUri, String canonicalQueryString,
                                       String canonicalHeaders,
                                       String signedHeaders, String payload, String date, String timestamp) throws Exception {
        String algorithm = "K1-HMAC-SHA256";
        String service = "cbms";

        // step 1: build canonical request string
        System.out.println(payload);
        String hashedRequestPayload = sha256Hex(payload);
        String canonicalRequest = httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n"
                + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload;
        System.out.println("**********canonicalRequest**********");
        System.out.println(canonicalRequest);

        // step 2: build string to sign
        String credentialScope = date + "/" + service + "/" + "k1_request";
        String hashedCanonicalRequest = sha256Hex(canonicalRequest);
        String stringToSign = algorithm + "\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;
        System.out.println("\n\n**********stringToSign**********");
        System.out.println(stringToSign);

        // step 3: sign string
        byte[] secretDate = hmac256(("K1" + SECRET_KEY).getBytes(UTF8), date);
        System.out.println("secretDate:" + HexUtil.encodeHexStr(secretDate));
        byte[] secretService = hmac256(secretDate, service);
        System.out.println("secretService:" + HexUtil.encodeHexStr(secretService));
        byte[] secretSigning = hmac256(secretService, "k1_request");
        System.out.println("secretSigning:" + HexUtil.encodeHexStr(secretSigning));
        String signature = DatatypeConverter.printHexBinary(hmac256(secretSigning, stringToSign)).toLowerCase();
        System.out.println("\n\n************signature:" + signature);

        // step 4: build authorization
        String authorization = algorithm + " " + "Credential=" + SECRET_ID + "/" + credentialScope + ", "
                + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;
        System.out.println("************authorization:" + authorization);
    }

    private static byte[] hmac256(byte[] key, String msg) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
        mac.init(secretKeySpec);
        return mac.doFinal(msg.getBytes(UTF8));
    }

    private static String sha256Hex(String s) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] d = md.digest(s.getBytes(UTF8));
        return DatatypeConverter.printHexBinary(d).toLowerCase();
    }

    private static String getTimestamp() {
        return String.valueOf(System.currentTimeMillis() / 1000);
    }

}
```

