Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Intercom user_hash

Remember that your secret key should never be exposed to the public

  • So Javascript code below should only be used for testing unless modified and used to run on a server

Javascript

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/hmac-sha256.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/enc-base64-min.js"></script>
<script>
  var hash = CryptoJS.HmacSHA256("Message", "secret");
  var hashInHex = CryptoJS.enc.Hex.stringify(hash);
  document.write(hashInHex); // aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597
</script>

Node

const crypto = require('crypto');
const hmac = crypto.createHmac('sha256', 'secret');
hmac.update('Message');
console.log(hmac.digest('hex')); // aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597

PHP

<?php
echo hash_hmac('sha256', 'Message', 'secret'); // thanks @AshleyPinner https://gist.github.com/thewheat/7342c76ade46e7322c3e#gistcomment-1820677
?>

Java

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class Test {
  public static void main(String[] args) {
  try {
      String secret = "secret";
      String message = "Message";

      Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
      SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
      sha256_HMAC.init(secret_key);

      byte[] hash = (sha256_HMAC.doFinal(message.getBytes()));
      StringBuffer result = new StringBuffer();
      for (byte b : hash) {
        result.append(String.format("%02x", b)); // thanks sachins! https://gist.github.com/thewheat/7342c76ade46e7322c3e#gistcomment-1863031 
      }
      System.out.println(result.toString()); // aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597
    }
    catch (Exception e){
      System.out.println("Error");
    }
  }
}

Groovy

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;

def hmac_sha256(String secretKey, String data) {
 try {
    Mac mac = Mac.getInstance("HmacSHA256")
    SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256")
    mac.init(secretKeySpec)
    byte[] digest = mac.doFinal(data.getBytes())
    return digest
   } catch (InvalidKeyException e) {
    throw new RuntimeException("Invalid key exception while converting to HMac SHA256")
  }
}

def hash = hmac_sha256("secret", "Message")
StringBuffer result = new StringBuffer();
for (byte b : hash) {
result.append(String.format("%02x", b)); // thanks sachins! https://gist.github.com/thewheat/7342c76ade46e7322c3e#gistcomment-1863031
}
print(result.toString()); // aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597

C#

using System.Security.Cryptography;

namespace Test
{
	public class MyHmac
	{
		public static void Main(string[] args){
			var hmac = new MyHmac ();
			System.Console.WriteLine(hmac.CreateToken ("Message", "secret")); // AA747C502A898200F9E4FA21BAC68136F886A0E27AEC70BA06DAF2E2A5CB5597
		}
		private string CreateToken(string message, string secret)
		{
			secret = secret ?? "";
			var encoding = new System.Text.ASCIIEncoding();
			byte[] keyByte = encoding.GetBytes(secret);
			byte[] messageBytes = encoding.GetBytes(message);
			using (var hmacsha256 = new HMACSHA256(keyByte))
			{
				byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);

				var sb = new System.Text.StringBuilder();
				for (var i = 0; i <= hashmessage.Length - 1; i++)
				{
					sb.Append(hashmessage[i].ToString("X2"));
				}
				return sb.ToString();
			}
		}
	}
}

Objective C

#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonHMAC.h>

NSData *hmacForKeyAndData(NSString *key, NSString *data)
{
    const char *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
    return [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
}

// http://stackoverflow.com/a/9084784
NSString *hexadecimalString(NSData *data){
    /* Returns hexadecimal string of NSData. Empty string if data is empty.   */

    const unsigned char *dataBuffer = (const unsigned char *)[data bytes];

    if (!dataBuffer)
        return [NSString string];

    NSUInteger          dataLength  = [data length];
    NSMutableString     *hexString  = [NSMutableString stringWithCapacity:(dataLength * 2)];

    for (int i = 0; i < dataLength; ++i)
        [hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]];

    return [NSString stringWithString:hexString];
}
int main (int argc, const char * argv[])
{
    @autoreleasepool {
        NSLog(@"%@", hexadecimalString(hmacForKeyAndData(@"secret", @"Message")));
    }
    return 0;
}

Go

package main

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "fmt"
)

func ComputeHmac256(message string, secret string) string {
    key := []byte(secret)
    h := hmac.New(sha256.New, key)
    h.Write([]byte(message))
    return hex.EncodeToString(h.Sum(nil))
}

func main() {
    fmt.Println(ComputeHmac256("Message", "secret")) // aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597
}

Ruby

require 'openssl'

OpenSSL::HMAC.hexdigest('sha256', "secret", "Message") # aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597

Python (2.x)

import hashlib
import hmac

KEY = "secret"
MESSAGE = "Message"
result = hmac.new(KEY, MESSAGE, hashlib.sha256).hexdigest()
print result # aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597

Python (3.x)

import hashlib
import hmac

KEY = "secret"
KEY_BYTES=KEY.encode('ascii')
MESSAGE = "Message"
MESSAGE_BYTES=MESSAGE.encode('ascii')
result = hmac.new(KEY_BYTES, MESSAGE_BYTES, hashlib.sha256).hexdigest()

print (result) # aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597

Perl

use Digest::SHA qw(hmac_sha256_hex);
$digest = hmac_sha256_hex("Message", "secret");
print $digest; # aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597

Swift

// Add
// #import <CommonCrypto/CommonHMAC.h>
// to the bridging Objective-C bridging header.

import Foundation

enum CryptoAlgorithm {
    case MD5, SHA1, SHA224, SHA256, SHA384, SHA512

    var HMACAlgorithm: CCHmacAlgorithm {
        var result: Int = 0
        switch self {
        case .MD5:      result = kCCHmacAlgMD5
        case .SHA1:     result = kCCHmacAlgSHA1
        case .SHA224:   result = kCCHmacAlgSHA224
        case .SHA256:   result = kCCHmacAlgSHA256
        case .SHA384:   result = kCCHmacAlgSHA384
        case .SHA512:   result = kCCHmacAlgSHA512
        }
        return CCHmacAlgorithm(result)
    }

    var digestLength: Int {
        var result: Int32 = 0
        switch self {
        case .MD5:      result = CC_MD5_DIGEST_LENGTH
        case .SHA1:     result = CC_SHA1_DIGEST_LENGTH
        case .SHA224:   result = CC_SHA224_DIGEST_LENGTH
        case .SHA256:   result = CC_SHA256_DIGEST_LENGTH
        case .SHA384:   result = CC_SHA384_DIGEST_LENGTH
        case .SHA512:   result = CC_SHA512_DIGEST_LENGTH
        }
        return Int(result)
    }
}

extension String {

    func hmac(algorithm: CryptoAlgorithm, key: String) -> String {
        let str = self.cStringUsingEncoding(NSUTF8StringEncoding)
        let strLen = Int(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
        let digestLen = algorithm.digestLength
        let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen)
        let keyStr = key.cStringUsingEncoding(NSUTF8StringEncoding)
        let keyLen = Int(key.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))

        CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)

        let digest = stringFromResult(result, length: digestLen)

        result.dealloc(digestLen)

        return digest
    }

    private func stringFromResult(result: UnsafeMutablePointer<CUnsignedChar>, length: Int) -> String {
        var hash = NSMutableString()
        for i in 0..<length {
            hash.appendFormat("%02x", result[i])
        }
        return String(hash)
    }

}


print("Message".hmac(CryptoAlgorithm.SHA256, key: "secret")) //aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597
@edkellena

This comment has been minimized.

Copy link

commented May 5, 2016

Bash

echo -n "your_user_data" | openssl dgst -sha256 -hmac "your API secret"

@mike-north

This comment has been minimized.

Copy link

commented May 30, 2016

New CDN tags for javascript assets. Google ones don't work anymore

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/hmac-sha256.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/enc-base64-min.js"></script>
@mike-north

This comment has been minimized.

Copy link

commented May 30, 2016

Elixir

hmac_digest = :sha256
|> :crypto.hmac(intercom_secure_key, user.intercom_id)
|> Base.encode16
|> String.downcase
@gawin

This comment has been minimized.

Copy link

commented Jun 6, 2016

Lua

local crypto = require("crypto")
local hmac = require("crypto.hmac")

local result = hmac.digest("sha256", "Intercom.user_id", "Intercom.secret_key")

Note that you need to have LuaCrypto and OpenSSL installed. Install via LuaRocks:
luarocks install luacrypto

@botekchristophe

This comment has been minimized.

Copy link

commented Jun 21, 2016

Scala

import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec

def encryptSHA256(message: String, secret: String): String = {
    val sha256_HMAC = Mac.getInstance("HmacSHA256")
    val secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256")
    sha256_HMAC.init(secret_key)
    sha256_HMAC.doFinal(message.getBytes())
      .map("%02X" format _)
      .mkString
  }
@AshleyPinner

This comment has been minimized.

Copy link

commented Jul 7, 2016

FYI, the PHP example can be done more simply as:

<?php
echo hash_hmac('sha256', 'Message', 'secret');
?>

If you don't specify the final argument, it defaults to false and outputs as lowercase hexits, as per the docs

@hawkz

This comment has been minimized.

Copy link

commented Aug 12, 2016

Django

Create a template tag:

import hashlib as h 
import hmac as h2

@register.filter(name='hmac')
def hmac(userid, key): 
    """Return the encrypted key"""
    return h2.new(str(key), str(userid), digestmod=h.sha256).hexdigest()

In your template do something like:

{% load your_template_tag_here %}

<script> 
{% if not user.is_authenticated %} 
    window.intercomSettings = { 
      app_id: "XXXXXXXX" 
    }; 
{% else %} 
    window.intercomSettings = { 
      app_id: "XXXXXXXX", 
      name: "{{ request.user.get_full_name }}", // Full name 
      user_id: "{{ request.user.id }}", // User ID 
      created_at: {{ request.user.date_joined|date:"U" }}, // Signup date as a Unix timestamp 
      user_hash: "{{ request.user.id|hmac:'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' }}" 
    }; 
{% endif %} 
</script> 
@sachins

This comment has been minimized.

Copy link

commented Aug 31, 2016

The Java example works for Android, but make sure to lowercase the result. So result.append(String.format("%02X", b)); should be result.append(String.format("%02x", b));

@atskimura

This comment has been minimized.

Copy link

commented Oct 21, 2016

Apex

String userId = 'userid';
String intercomSecret = 'intercom_secret';
Blob userHashBlob = crypto.generateMac('HmacSHA256', Blob.valueOf(userId), Blob.valueOf(intercomSecret));
String userHash = EncodingUtil.convertToHex(userHashBlob);
@scottsouthard

This comment has been minimized.

Copy link

commented Feb 26, 2017

Liquid

{% assign my_secret_string = "user_id" | hmac_sha256: "secret_key" %}
My encoded string is: {{ my_secret_string }}
@hasmMarques

This comment has been minimized.

Copy link

commented Sep 28, 2017

Hi,
Here string CreateToken(string message, string secret)
what means the 'secret' input parameter? it's the apikey?
Cheers,
Hasm

@whitecaps

This comment has been minimized.

Copy link

commented Nov 6, 2017

@hasmMarques The secret argument in this case refers to the "Identity Verification Secret" found in your "App Settings" > "Identity verification" page.

@thevalyreangroup

This comment has been minimized.

Copy link

commented Jan 12, 2018

Update for Swift 4 and also returns the string in lower case for API satisfaction.

import Foundation

enum CryptoAlgorithm {
    case MD5, SHA1, SHA224, SHA256, SHA384, SHA512
    
    var HMACAlgorithm: CCHmacAlgorithm {
        var result: Int = 0
        switch self {
        case .MD5:      result = kCCHmacAlgMD5
        case .SHA1:     result = kCCHmacAlgSHA1
        case .SHA224:   result = kCCHmacAlgSHA224
        case .SHA256:   result = kCCHmacAlgSHA256
        case .SHA384:   result = kCCHmacAlgSHA384
        case .SHA512:   result = kCCHmacAlgSHA512
        }
        return CCHmacAlgorithm(result)
    }
    
    var digestLength: Int {
        var result: Int32 = 0
        switch self {
        case .MD5:      result = CC_MD5_DIGEST_LENGTH
        case .SHA1:     result = CC_SHA1_DIGEST_LENGTH
        case .SHA224:   result = CC_SHA224_DIGEST_LENGTH
        case .SHA256:   result = CC_SHA256_DIGEST_LENGTH
        case .SHA384:   result = CC_SHA384_DIGEST_LENGTH
        case .SHA512:   result = CC_SHA512_DIGEST_LENGTH
        }
        return Int(result)
    }
}

extension String {
    
    func hmac(algorithm: CryptoAlgorithm, key: String) -> String {
        let str = self.cString(using: String.Encoding.utf8)
        let strLen = Int(self.lengthOfBytes(using: String.Encoding.utf8))
        let digestLen = algorithm.digestLength
        let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
        let keyStr = key.cString(using: String.Encoding.utf8)
        let keyLen = Int(key.lengthOfBytes(using: String.Encoding.utf8))
        
        CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)
        
        let digest = stringFromResult(result: result, length: digestLen)
        
        result.deallocate(capacity: digestLen)
        
        return digest
    }
    
    private func stringFromResult(result: UnsafeMutablePointer<CUnsignedChar>, length: Int) -> String {
        let hash = NSMutableString()
        for i in 0..<length {
            hash.appendFormat("%02x", result[i])
        }
        return String(hash).lowercased()
    }
}
@wmonk

This comment has been minimized.

Copy link

commented Mar 11, 2019

Rust

Translated from our existing python code. The key here was stringifying the uuid before signing it. As Uuid::as_bytes gives a different output to the string version.

use ring::{hmac, digest};
use hex;
use uuid;

let id = uuid::Uuid::new_v4();
let signing_key = hmac::SigningKey::new(
    &digest::SHA256,
    &INTERCOM_KEY.as_bytes()
);
let signed_user_id = hmac::sign(
    &signing_key,
    id.to_string().as_bytes()
);
let intercom_hash = hex::encode(
    signed_user_id.as_ref()
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.