- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-03-2024 11:45 PM
Hello Community,
We are currently supporting API key authorization login for our client portal by generating an HMAC-SHA256 signature in ServiceNow using the CryptoJS library (used library: crypto-js/3.1.2/hmac-sha256.js ). However, as ServiceNow will no longer support CryptoJS, we need a new approach to create this HMAC signature without relying on external libraries.
Our goal is to securely generate an HMAC-SHA256 signature using the available ServiceNow platform capabilities or an alternative method that aligns with ServiceNow’s security standards. The signature is essential for API authentication in our integration, and our requirements are as follows:
- API Key and Secret: The solution should utilize API keys and secrets securely stored within ServiceNow.
- Signature Generation: HMAC-SHA256 hashing needs to be applied to these credentials to generate the required signature.
- Platform Compatibility: Ideally, the solution should be compatible with out-of-the-box ServiceNow features without needing any external libraries.
If anyone has encountered a similar situation or has insights into achieving HMAC-SHA256 hashing within ServiceNow’s native environment, your guidance would be highly appreciated. Any code examples, alternative libraries that are ServiceNow-compatible, or best practices would be incredibly helpful.
Thank you in advance for your support and recommendations!
Best regards,
Shuvo
Solved! Go to Solution.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-12-2024 01:36 PM - edited 11-12-2024 02:04 PM
Hey Shuvo,
I managed to achieve the same output that CryptoJS.HmacSHA256(signatureStr, key) provides, but without any use of KMF or the external CryptoJS library.
Here's how I did it--
- Generate HMAC-SHA256 signature using OOB CertificateEncrpytion API:
hmacSHA256: function(signatureStr, key) {
var mac = new CertificateEncryption;
return mac.generateMac(key, 'HmacSHA256', signatureStr) || '';
},
- This will return the HMAC-SHA256 signature in base64 encoded string format
- From there, at least for the use case of my target API endpoint, the 3rd-party platform is expecting this HMAC-SHA256 signature not to be in base64 encoded string format, but rather the equivalent hex value (this hex value is what CryptoJS.HmacSHA256() returns).
- So to convert base64 encoded string to its hex equivalent, the below javascript can be used:
var raw = atob(base64Str), //input base64 encoded string
hex = '';
for (var i = 0; i < raw.length; i++) {
var hexChar = raw.charCodeAt(i).toString(16);
hex += (hexChar.length === 2 ? hexChar : '0' + hexChar);
}
return hex;
- The issue, though, is that this global 'atob()' JavaScript function is not supported in servicenow, and the native 'equivalent' for decoding base64 encoded strings "gs.base64Decode()" does not give 1:1 output results. So, to get around this, I implemented a vanilla JS workaround equivalent for atob() as below NOTE: the community isn't letting me save this reply with the correct line of code at the top...not quite sure how to share it right now):
decodeBase64ToBinary: function(base64Str) {
var chars = '';//servicenow community won't let me save this real line of code in the reply for some reason
var result = '';
base64Str = base64Str.replace(/=+$/, ''); // Remove any trailing '='
for (var i = 0, buffer, bs, bc = 0; buffer = base64Str.charAt(i++);) {
buffer = chars.indexOf(buffer);
if (buffer === -1) continue;
bs = bc % 4 ? (bs << 6) | buffer : buffer;
if (bc++ % 4) {
result += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)));
}
}
return result;
},
- Now that I have my proper/expected decoded binary string as what atob() provides, I can convert it to hex using the same JS function provided above to get the final expected output equivalent to CryptoJS().HmacSHA256():
base64ToHex: function(base64Str) {
var raw = this.decodeBase64ToBinary(base64Str),
hex = '';
for (var i = 0; i < raw.length; i++) {
var hexChar = raw.charCodeAt(i).toString(16);
hex += (hexChar.length === 2 ? hexChar : '0' + hexChar);
}
return hex;
},
- So to put it all together, it could look something like this in a script include (with the functions defined that I provided above):
finalHmacFunction: function(signatureStr, key) {
var result = '';
var signature = this.hmacSHA256(signatureStr, key);
result = this.base64ToHex(signature);
return result;
},
Hope this helps!
Regards,
Chris Perry

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-08-2024 11:20 AM - edited 11-11-2024 12:58 PM
Hi there,
I am currently working through the same situation. I am waiting for my vendor instances to upgrade to Xanadu as I type this, and once those are complete I will be implementing the below alternative solution that was provided by ServiceNow:
<image removed due to confidentiality>
Regards,
Chris Perry
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-10-2024 05:53 AM
Hi @chrisperry ,
Thanks for sharing this approach! I have been analyzing the possibility of using the KMF module, as suggested. However, I encountered some prerequisites that need to be active on the instance, such as the "Column Level Encryption Enterprise" plugin (com.glide.now.platform.encryption) to store customer supplied key. Unfortunately, this plugin isn't available in the system applications list. I created a Hi ticket to request its activation, but the ServiceNow engineer informed me that this plugin cannot be activated on a client instance.
If you come across any other solutions or additional insights, I'd greatly appreciate it if you could share them!
Thanks again for your help.
Best regards,
Shuvo

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-12-2024 01:36 PM - edited 11-12-2024 02:04 PM
Hey Shuvo,
I managed to achieve the same output that CryptoJS.HmacSHA256(signatureStr, key) provides, but without any use of KMF or the external CryptoJS library.
Here's how I did it--
- Generate HMAC-SHA256 signature using OOB CertificateEncrpytion API:
hmacSHA256: function(signatureStr, key) {
var mac = new CertificateEncryption;
return mac.generateMac(key, 'HmacSHA256', signatureStr) || '';
},
- This will return the HMAC-SHA256 signature in base64 encoded string format
- From there, at least for the use case of my target API endpoint, the 3rd-party platform is expecting this HMAC-SHA256 signature not to be in base64 encoded string format, but rather the equivalent hex value (this hex value is what CryptoJS.HmacSHA256() returns).
- So to convert base64 encoded string to its hex equivalent, the below javascript can be used:
var raw = atob(base64Str), //input base64 encoded string
hex = '';
for (var i = 0; i < raw.length; i++) {
var hexChar = raw.charCodeAt(i).toString(16);
hex += (hexChar.length === 2 ? hexChar : '0' + hexChar);
}
return hex;
- The issue, though, is that this global 'atob()' JavaScript function is not supported in servicenow, and the native 'equivalent' for decoding base64 encoded strings "gs.base64Decode()" does not give 1:1 output results. So, to get around this, I implemented a vanilla JS workaround equivalent for atob() as below NOTE: the community isn't letting me save this reply with the correct line of code at the top...not quite sure how to share it right now):
decodeBase64ToBinary: function(base64Str) {
var chars = '';//servicenow community won't let me save this real line of code in the reply for some reason
var result = '';
base64Str = base64Str.replace(/=+$/, ''); // Remove any trailing '='
for (var i = 0, buffer, bs, bc = 0; buffer = base64Str.charAt(i++);) {
buffer = chars.indexOf(buffer);
if (buffer === -1) continue;
bs = bc % 4 ? (bs << 6) | buffer : buffer;
if (bc++ % 4) {
result += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)));
}
}
return result;
},
- Now that I have my proper/expected decoded binary string as what atob() provides, I can convert it to hex using the same JS function provided above to get the final expected output equivalent to CryptoJS().HmacSHA256():
base64ToHex: function(base64Str) {
var raw = this.decodeBase64ToBinary(base64Str),
hex = '';
for (var i = 0; i < raw.length; i++) {
var hexChar = raw.charCodeAt(i).toString(16);
hex += (hexChar.length === 2 ? hexChar : '0' + hexChar);
}
return hex;
},
- So to put it all together, it could look something like this in a script include (with the functions defined that I provided above):
finalHmacFunction: function(signatureStr, key) {
var result = '';
var signature = this.hmacSHA256(signatureStr, key);
result = this.base64ToHex(signature);
return result;
},
Hope this helps!
Regards,
Chris Perry
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-21-2024 03:34 AM - edited 11-21-2024 03:35 AM
Hi Christoper,
Really appreciate for above solution!
chars variable can be found here https://en.wikipedia.org/wiki/Base64 in Privacy-enhanced mail section after "as indices into the string"