Bryan
Bryan

Reputation: 119

How to implement API signature algorithm in Go for Kraken?

The Kraken API documentation shows usage of the API_KEY variable in two different headers.

req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
req.Header.Add("API-Key", "<API_KEY_VALUE>")
req.Header.Add("API-Sign", "<API_KEY_VALUE>")

Based on other example documentation in which they implement a much more complicated retrieval of the API signature (here: https://support.kraken.com/hc/en-us/articles/360029054811-What-is-the-authentication-algorithm-for-private-endpoints-#Example_Code), this seems incorrect.

What would be an equivalent implementation in Go?

Upvotes: 1

Views: 46

Answers (1)

Bryan
Bryan

Reputation: 119

After working on this for a while and spot-checking line-by-line for equivalence with the working Python, I got something working:


import (
    "crypto/hmac"
    "crypto/sha256"
    "crypto/sha512"
    "encoding/base64"
    "log"
    "strconv"
    "time"
)


func createAPISign(apiSecret string) (string, string, error) {

    apiPath := "/0/private/GetWebSocketsToken"
    nonce := strconv.FormatInt(time.Now().UnixMilli(), 10)
    postData := "nonce=" + nonce
    concatenatedNonce := nonce + postData

    apiSha256 := sha256.New()
    // write the concatenated nonce to the sha256 object
    apiSha256.Write([]byte(concatenatedNonce))
    // retrieve bytes for what's been written to the sha256 object
    apiSha256Bytes := apiSha256.Sum(nil)

    // decode the api secret into bytes
    encodedSecret, err := base64.StdEncoding.DecodeString(apiSecret)
    if err != nil {
        return "", "", err
    }

    // create the hmac object
    h := hmac.New(sha512.New, encodedSecret)
    // write the api path and the sha256 bytes to the hmac object
    h.Write(append([]byte(apiPath), apiSha256Bytes...))
    // retrieve the hmac digest
    hmacDigest := h.Sum(nil)

    // encode the hmac digest into a base64 string
    apiSignature := base64.StdEncoding.EncodeToString(hmacDigest)

    return postData, apiSignature, nil
}


func main() {
    apiSecret := "apiSecret"
    postData, apiSignature, err := createAPISign(apiSecret)
    if err != nil {
        log.Fatalf("Error creating API sign: %v", err)
    }
    log.Printf("postData: %s\napiSignature: %s\n", postData, apiSignature)
}

Upvotes: 1

Related Questions