Skip to content

Commit 401799d

Browse files
committed
Add core/crypto package for WebhooksHelper.ts
1 parent fc20c0d commit 401799d

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
export async function createHmacOverride(payload: string, key: string): Promise<string> {
2+
try {
3+
const crypto = require('crypto');
4+
const hmac = crypto.createHmac('sha256', key);
5+
hmac.update(payload, 'utf8');
6+
return hmac.digest('base64');
7+
}
8+
catch (err) {
9+
// Not in Node environmnet; use subtle crypto.
10+
}
11+
const subtleCrypto = getSubtleCrypto();
12+
if (!subtleCrypto) {
13+
throw new Error('No crypto implementation available');
14+
}
15+
const encoder = new TextEncoder();
16+
const cryptoKey = await subtleCrypto.importKey(
17+
'raw',
18+
encoder.encode(key),
19+
{
20+
name: 'HMAC',
21+
hash: { name: 'SHA-256' }
22+
},
23+
false,
24+
['sign']
25+
);
26+
const signatureBuffer = await subtleCrypto.sign(
27+
'HMAC',
28+
cryptoKey,
29+
encoder.encode(payload)
30+
);
31+
return arrayBufferToBase64(signatureBuffer);
32+
}
33+
34+
function getSubtleCrypto(): SubtleCrypto | undefined {
35+
if (typeof window !== 'undefined' && window?.crypto?.subtle) {
36+
return window.crypto.subtle;
37+
}
38+
return undefined;
39+
}
40+
41+
function arrayBufferToBase64(buffer: ArrayBuffer): string {
42+
if (typeof btoa === 'function') {
43+
// Browser environment
44+
const bytes = new Uint8Array(buffer);
45+
let binary = '';
46+
for (let i = 0; i < bytes.byteLength; i++) {
47+
binary += String.fromCharCode(bytes[i]);
48+
}
49+
return btoa(binary);
50+
} else {
51+
// Node environment
52+
return Buffer.from(buffer).toString('base64');
53+
}
54+
}

src/core/crypto/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { createHmacOverride } from "./createHmacOverride";

0 commit comments

Comments
 (0)