Issue in creating signature in Go Lang


I am trying to access Rapyd API and having problem creating signature.

To Create signature:

func sign(secret string, data []byte) string {
	hash := hmac.New(sha256.New, []byte(secret))

	return hex.EncodeToString(hash.Sum(nil))

To create to_sign data:

//http_method e.g "get"
//path e.g "v1/data/countries"
//body e.g ""
//sample return value in string "get/v1/data/countriesa3d88998fcc545b41651211157_ accesskey_secret"
func to_sign(http_method, path, body, access_key, secret string) []byte {
	//timestamp to string
	ts := fmt.Sprintf("%d", time.Now().Unix())

	//salt generation
	key := make([]byte, 6)
	salt := fmt.Sprintf("%x", key)

	http_method = strings.ToLower(http_method)

	data := []byte(http_method + path + salt + ts + access_key + secret + body)

	return data

Error returned
{"status":{"error_code":"UNAUTHENTICATED_API_CALL","status":"ERROR","message":"The API received a request, but the signature did not match. The request was rejected. Corrective action: (1) Remove all whitespace that is not inside a string. (2) Remove trailing zeroes and decimal points, or wrap numbers in a string.","response_code":"UNAUTHENTICATED_API_CALL","operation_id":"9306d5ea-8c39-4898-afaa-47fc06170aaa"}}

Go Version 1.18

Hi @Abdul_Waheed,

From the error response, this may be due to a couple things:

  1. All spaces and other whitespace outside of strings must be removed.
  2. Numbers should be sent in strings, not as integers/numbers.

Here are some resources that may help:

I would also take a look around your body and and how it may not be parsed correctly.

Passing empty body as making only get request.

	request, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%v%v", baseUrl, countryUrl), bytes.NewBufferString(""))
	request.Header.Add("access_key", access_key)
	request.Header.Add("Content-Type", "application/json")
	request.Header.Add("salt", salt)
	request.Header.Add("timestamp", ts)
	request.Header.Add("signature", signature)

Is there any sample code in Go, it would be very useful.

Thanks for your help Kyle, just need to convert it base64 after converting value into hex and add “==” at the end as in Go we need to manage trailing bit on our own.

Updated sign method.

func sign(secret string, data []byte) string {
	hash := hmac.New(sha256.New, []byte(secret))

	return base64.RawStdEncoding.EncodeToString([]byte(hex.EncodeToString(hash.Sum(nil)))) +"=="