diff --git a/packages/api/package.json b/packages/api/package.json index 955b3ad..a6d71e3 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -34,12 +34,8 @@ "clean": true, "platform": "browser" }, - "dependencies": { - "crypto-js": "^4.2.0" - }, - "devDependencies": { - "@types/crypto-js": "^4.2.0" - }, + "dependencies": {}, + "devDependencies": {}, "peerDependencies": {}, "keywords": [ "ton", diff --git a/packages/api/src/utils/verify-signature.ts b/packages/api/src/utils/verify-signature.ts index 2ddac0b..a99518b 100644 --- a/packages/api/src/utils/verify-signature.ts +++ b/packages/api/src/utils/verify-signature.ts @@ -1,5 +1,3 @@ -import * as CryptoJS from 'crypto-js'; - /** * Verifies the HMAC-SHA256 signature of a payload * @param payload - Raw JSON string or object to verify @@ -12,11 +10,11 @@ import * as CryptoJS from 'crypto-js'; * import { verifySignature } from "@ton-pay/api"; * * // With raw string - * app.post("/webhook", (req, res) => { + * app.post("/webhook", async (req, res) => { * const signature = req.headers["x-tonpay-signature"] as string; * const payload = JSON.stringify(req.body); * - * if (!verifySignature(payload, signature, YOUR_API_SECRET)) { + * if (!await verifySignature(payload, signature, YOUR_API_SECRET)) { * return res.status(401).json({ error: "Invalid signature" }); * } * @@ -24,10 +22,10 @@ import * as CryptoJS from 'crypto-js'; * }); * * // With object (will be stringified automatically) - * app.post("/webhook", (req, res) => { + * app.post("/webhook", async (req, res) => { * const signature = req.headers["x-tonpay-signature"] as string; * - * if (!verifySignature(req.body, signature, YOUR_API_SECRET)) { + * if (!await verifySignature(req.body, signature, YOUR_API_SECRET)) { * return res.status(401).json({ error: "Invalid signature" }); * } * @@ -35,16 +33,31 @@ import * as CryptoJS from 'crypto-js'; * }); * ``` */ -export function verifySignature( +export async function verifySignature( payload: string | object, signature: string, apiSecret: string, -): boolean { +): Promise { + const encoder = new TextEncoder(); const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload); - const hmac = CryptoJS.HmacSHA256(payloadString, apiSecret); - const expectedSignature = `sha256=${hmac.toString(CryptoJS.enc.Hex)}`; + const key = await crypto.subtle.importKey( + 'raw', + encoder.encode(apiSecret), + { name: 'HMAC', hash: 'SHA-256' }, + false, + ['sign'], + ); + + const sig = await crypto.subtle.sign( + 'HMAC', + key, + encoder.encode(payloadString), + ); + const hex = Array.from(new Uint8Array(sig)) + .map((b) => b.toString(16).padStart(2, '0')) + .join(''); - return signature === expectedSignature; + return signature === `sha256=${hex}`; } diff --git a/packages/api/tsup.config.ts b/packages/api/tsup.config.ts index 0e5845c..0ba9296 100644 --- a/packages/api/tsup.config.ts +++ b/packages/api/tsup.config.ts @@ -8,6 +8,5 @@ export default defineConfig({ sourcemap: true, clean: true, platform: 'browser', - noExternal: ['crypto-js'], tsconfig: './tsconfig.json', });