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
}
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))