From 3068f375b51d6763acbe508760e38024094f51dd Mon Sep 17 00:00:00 2001 From: sasikumar-bitgo Date: Mon, 20 Oct 2025 14:30:00 +0530 Subject: [PATCH] feat(sdk-hmac): normalize HTTP methods and update calculateHMAC types TICKET: ANT-1025 --- commitlint.config.js | 1 + modules/sdk-hmac/src/hmac.ts | 8 ++++++-- modules/sdk-hmac/src/types.ts | 2 +- modules/sdk-hmac/test/hmac.ts | 15 +++++++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/commitlint.config.js b/commitlint.config.js index 1784b5e571..f625c1182e 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -65,6 +65,7 @@ module.exports = { 'COIN-', 'FIAT-', 'ME-', + 'ANT-', '#', // Prefix used by GitHub issues ], }, diff --git a/modules/sdk-hmac/src/hmac.ts b/modules/sdk-hmac/src/hmac.ts index 56839f7184..8be11f396d 100644 --- a/modules/sdk-hmac/src/hmac.ts +++ b/modules/sdk-hmac/src/hmac.ts @@ -1,4 +1,4 @@ -import { createHmac } from 'crypto'; +import { type BinaryLike, createHmac, type KeyObject } from 'crypto'; import * as urlLib from 'url'; import * as sjcl from '@bitgo/sjcl'; import { @@ -16,7 +16,7 @@ import { * @param message {String} - the actual message to HMAC * @returns {*} - the result of the HMAC operation */ -export function calculateHMAC(key: string, message: string): string { +export function calculateHMAC(key: string | BinaryLike | KeyObject, message: string | BinaryLike): string { return createHmac('sha256', key).update(message).digest('hex'); } @@ -37,6 +37,10 @@ export function calculateHMACSubject({ method, authVersion, }: CalculateHmacSubjectOptions): string { + /* Normalize legacy 'del' to 'delete' for backward compatibility */ + if (method === 'del') { + method = 'delete'; + } const urlDetails = urlLib.parse(urlPath); const queryPath = urlDetails.query && urlDetails.query.length > 0 ? urlDetails.path : urlDetails.pathname; if (statusCode !== undefined && isFinite(statusCode) && Number.isInteger(statusCode)) { diff --git a/modules/sdk-hmac/src/types.ts b/modules/sdk-hmac/src/types.ts index 3952b03e38..b90304983c 100644 --- a/modules/sdk-hmac/src/types.ts +++ b/modules/sdk-hmac/src/types.ts @@ -1,4 +1,4 @@ -export const supportedRequestMethods = ['get', 'post', 'put', 'del', 'patch', 'options'] as const; +export const supportedRequestMethods = ['get', 'post', 'put', 'del', 'patch', 'options', 'delete'] as const; export type AuthVersion = 2 | 3; diff --git a/modules/sdk-hmac/test/hmac.ts b/modules/sdk-hmac/test/hmac.ts index f5e2578382..75f669cd27 100644 --- a/modules/sdk-hmac/test/hmac.ts +++ b/modules/sdk-hmac/test/hmac.ts @@ -8,6 +8,7 @@ import { verifyResponse, } from '../src/hmac'; import * as sjcl from '@bitgo/sjcl'; +import { createSecretKey } from 'crypto'; // Mock Date.now for consistent timestamp values const MOCK_TIMESTAMP = 1672531200000; // Example timestamp (e.g., Jan 1, 2023, 00:00:00 UTC) @@ -30,6 +31,20 @@ describe('HMAC Utility Functions', () => { const expectedHmac = 'f8c2bb87c17608c9038eab4e92ef2775e42629c939d6fd3390d42f80af6bb712'; expect(calculateHMAC(key, message)).to.equal(expectedHmac); }); + + it('should accept a Buffer key (BinaryLike) and match the string result', () => { + const keyBuffer = Buffer.from('test-key', 'utf8'); + const message = Buffer.from('test-message'); + const expectedHmac = 'f8c2bb87c17608c9038eab4e92ef2775e42629c939d6fd3390d42f80af6bb712'; + expect(calculateHMAC(keyBuffer, message)).to.equal(expectedHmac); + }); + + it('should accept a KeyObject key and match the string result', () => { + const keyObject = createSecretKey(Buffer.from('test-key', 'utf8')); + const message = 'test-message'; + const expectedHmac = 'f8c2bb87c17608c9038eab4e92ef2775e42629c939d6fd3390d42f80af6bb712'; + expect(calculateHMAC(keyObject, message)).to.equal(expectedHmac); + }); }); describe('calculateHMACSubject', () => {