+ Start a Discussion
Puja ChoudharyPuja Choudhary 

Hmac-sha1 Authentication in salesforce

I have used the online Hmac generator and tested an API. Now I want to do the same thing using apex code.

I am not getting the success method by using the mac code generated using the method "Crypto.generateMac()".

I am generating the mac code using the method generateHmacSHA1Signature and calling the endpoint url using the mac generated earlier.

Getting the response as invalid signature.
public class HMACGenearatorHandler {
     public void createJson(){
         String jsonString; // create json here
         String json = '{"hotel":{"version":"1.0","datetime":"2019-11-12T08:09:59","request":{"method":"wsauth","key":"5151BE0BE4A9B667C07C727602C2EF4589658741"}}}';
         String sText= json.replaceAll( '\\s+', '');
         String strMd5= EncodingUtil.base64Encode (Crypto.generateDigest('MD5', Blob.valueOf(sText)));
         sendRequest(sText);
      generateHmacSHA1Signature(sText,'8B434FB19209EEE32002073C8680464785236985');
     } 
    
    @future (callout=true)
	public static void sendRequest(String jsonString){
        HttpRequest req = new HttpRequest();
        req.setEndpoint(System.Label.EndPoint);
        req.setMethod('POST');
        req.setHeader('X-HAPI-Signature','b7ua89TY1m6hHawC8v+ETX/SK7o=');
        req.setHeader('Content-Type', System.label.Content_Type); 
        req.setBody(jsonString);
        Http http = new Http();
        if(!test.isRunningTest()){
            HTTPResponse res = http.send(req);
            System.debug(res);
            System.debug('resp body+++'+res.getBody());
        } 
    } 
     
    public static Blob generateHmacSHA1Signature(String canonical_str, String secreteKey){ 
             Blob mac = Crypto.generateMac('HMacSHA1', Blob.valueof(canonical_str), Blob.valueof(secreteKey));
        	 String strSignature = EncodingUtil.base64Encode(mac);
             System.debug('strSignature11++'+strSignature);
             return mac;
         }
 }


 
Best Answer chosen by Puja Choudhary
Puja ChoudharyPuja Choudhary
I got the answer.... I had to convert the blob value to hex and then use it for the authentication of wsauth method.
public static Blob generateHmacSHA1Signature(String canonical_str, String secreteKey){ 
        String privateKey = '8B434FB19209EEE32002073C8680859658';
        String input = '{"hotel":{"version":"1.0","datetime":"2019-11-13T05:41:43","request":{"method":"wsauth","key":"5151BE0BE4A9B667C07C727602C2EF56965412365"}}}';
        Blob Signature = Crypto.generateMac('hmacSHA1', Blob.ValueOf(input), Blob.ValueOf(privateKey));
        System.debug('Final sign => '+ EncodingUtil.convertToHex(Signature)); // gives the correct signature
        return Signature;
    }

 

All Answers

Danish HodaDanish Hoda
Hi Puja,
You should do like this:
Blob blobResult = generateHmacSHA1Signature(sText,'8B434FB19209EEE32002073C8680464785236985');
sendRequest(String.valueOf(blobResult ));

 
Puja ChoudharyPuja Choudhary
Hi Danish,
when I use String.valueof(blobResult) the result comes as blob[20] which can't be a hmac key.
Ajay K DubediAjay K Dubedi
Hi Puja,

Go through the bellow link for HMAC Authentication in Salesforce it may helpful for you
https://www.thinqloud.com/hmac-authentication-in-salesforce/

I hope you find the above solution helpful. If it does, please mark as Best Answer to help others too.

Thanks and Regards,
Ajay Dubedi
www.ajaydubedi.com
Puja ChoudharyPuja Choudhary
I got the answer.... I had to convert the blob value to hex and then use it for the authentication of wsauth method.
public static Blob generateHmacSHA1Signature(String canonical_str, String secreteKey){ 
        String privateKey = '8B434FB19209EEE32002073C8680859658';
        String input = '{"hotel":{"version":"1.0","datetime":"2019-11-13T05:41:43","request":{"method":"wsauth","key":"5151BE0BE4A9B667C07C727602C2EF56965412365"}}}';
        Blob Signature = Crypto.generateMac('hmacSHA1', Blob.ValueOf(input), Blob.ValueOf(privateKey));
        System.debug('Final sign => '+ EncodingUtil.convertToHex(Signature)); // gives the correct signature
        return Signature;
    }

 
This was selected as the best answer