javascripttypescriptgocloudinary

Cloudinary signature call error - Invalid signature


I'm trying to upload image from frontend using signature call approach but can't get this into work. The only parameter I'm assigning is timestamp. There's more I want to assign if i figure this out but I'm only doing timestamp for now just to get this work.

I get "Invalid Signature MY_HASHED_STRING. String to sign - 'timestamp=1730359693'." when I call Cloudinary's api.

Here's my frontend part in typescript:

const formData = new FormData();
formData.append("api_key", import.meta.env.VITE_CLOUDINARY_API_KEY);
formData.append("file", resizedImage as Blob);
formData.append("signature", signature);
formData.append("timestamp", timestamp);

axios
   .post(
      `https://api.cloudinary.com/v1_1/${cloudName}/image/upload`,
      formData,
   )
   .then((res) => {
      setTrimImg(res.data.secure_url);
   })
   .catch((error) => {
      console.error("Error uploading image:", error);
      onError && onError();
   });

And here's my backend part written in go:

handler

func (h *ClientSideHandler) GetUploadSignature(w http.ResponseWriter, r *http.Request) {
    timestamp := strconv.FormatInt(time.Now().Unix(), 10)
    params := map[string]string{
        "timestamp": timestamp,
    }

    signature, err := utils.GenerateUploadSignature(params)
    if err != nil {
        logger.Error.Printf("Failed to generate signature: %v", err.Error())
        http.Error(w, "Failed to generate signature", http.StatusInternalServerError)
        return
    }

    res := map[string]interface{}{
        "signature": signature,
        "timestamp": timestamp,
    }
    utils.JsonRes(w, res, "success", false)
   return
}

function that creates signature:

func GenerateUploadSignature(params map[string]string) (string, error) {
    keys := make([]string, 0, len(params))
    for key := range params {
        keys = append(keys, key)
    }
    sort.Strings(keys)

    stringToSign := ""
    for _, key := range keys {
        value := params[key]
        stringToSign += fmt.Sprintf("%s=%s&", key, value)
    }
    // Remove the trailing '&'
    stringToSign = stringToSign[:len(stringToSign)-1]

    stringToSign += secret
    fmt.Println("stingsssssss", stringToSign)

    mac := hmac.New(sha1.New, []byte(secret))
    mac.Write([]byte(stringToSign))
    signature := hex.EncodeToString(mac.Sum(nil))

    return signature, nil
}


Solution

  • The signature is not a HMAC, but a simple SHA1 hash.

    You should use

        sum := sha1.Sum([]byte(stringToSign))
        signature := hex.EncodeToString(sum[:])
    

    instead of

        mac := hmac.New(sha1.New, []byte(secret))
        mac.Write([]byte(stringToSign))
        signature := hex.EncodeToString(mac.Sum(nil))