Skip to content

Commit fe937f2

Browse files
authored
feat: add create hmac signature (#500)
**This PR adds new function to the utility package.** Function `createHmacSignature()` will be used in Apify SDK as well as in Apify Core repositories
1 parent 4f707d4 commit fe937f2

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

packages/utilities/src/hmac.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import crypto from 'crypto';
2+
3+
const CHARSET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
4+
5+
/**
6+
* Encodes BigInt to base62.
7+
*/
8+
function encodeBase62(num: bigint) {
9+
if (num === 0n) {
10+
return CHARSET[0];
11+
}
12+
13+
let res = '';
14+
while (num > 0n) {
15+
res = CHARSET[Number(num % 62n)] + res;
16+
num /= 62n;
17+
}
18+
return res;
19+
}
20+
21+
/**
22+
* Generates an HMAC signature and encodes it using Base62.
23+
* Base62 encoding reduces the signature length.
24+
*
25+
* @param secretKey {string} Secret key used for signing signatures
26+
* @param message {string} Message to be signed
27+
* @returns string
28+
*/
29+
export function createHmacSignature(secretKey: string, message: string): string {
30+
const signature = crypto.createHmac('sha256', secretKey)
31+
.update(message)
32+
.digest('hex')
33+
.substring(0, 30);
34+
35+
return encodeBase62(BigInt(`0x${signature}`));
36+
}

packages/utilities/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export * from './webhook_payload_template';
88
export * from './crypto';
99
export * from './url_params_utils';
1010
export * from './code_hash_manager';
11+
export * from './hmac';

test/hmac.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { createHmacSignature } from '@apify/utilities';
2+
3+
describe('createHmacSignature()', () => {
4+
it('should create a valid HMAC signature', () => {
5+
const secretKey = 'hmac-secret-key';
6+
const message = 'hmac-message-to-be-authenticated';
7+
expect(createHmacSignature(secretKey, message)).toBe('pcVagAsudj8dFqdlg7mG');
8+
});
9+
10+
it('should create same HMAC signature, when secretKey and message are same', () => {
11+
const secretKey = 'hmac-same-secret-key';
12+
const message = 'hmac-same-message-to-be-authenticated';
13+
for (let i = 0; i < 5; i++) {
14+
expect(createHmacSignature(secretKey, message)).toBe('FYMcmTIm3idXqleF1Sw5');
15+
}
16+
});
17+
});

0 commit comments

Comments
 (0)