discord-verify
Advanced tools
Comparing version 0.0.2-beta.17 to 0.0.2-beta.18
@@ -1,3 +0,3 @@ | ||
import { R as Request, S as SubtleCryptoImportKeyAlgorithm } from './verify-ebfcae1c.js'; | ||
export { h as hexToBinary, v as validate } from './verify-ebfcae1c.js'; | ||
import { R as Request, S as SubtleCryptoImportKeyAlgorithm } from './verify-206a2779.js'; | ||
export { P as PlatformAlgorithm, h as hexStringToBinary, v as verify } from './verify-206a2779.js'; | ||
@@ -4,0 +4,0 @@ /** |
@@ -1,3 +0,3 @@ | ||
import { R as Request, S as SubtleCryptoImportKeyAlgorithm } from './verify-ebfcae1c.js'; | ||
export { P as PlatformAlgorithm, h as hexToBinary, v as validate } from './verify-ebfcae1c.js'; | ||
import { R as Request, S as SubtleCryptoImportKeyAlgorithm } from './verify-206a2779.js'; | ||
export { P as PlatformAlgorithm, h as hexStringToBinary, v as verify } from './verify-206a2779.js'; | ||
@@ -4,0 +4,0 @@ /** |
{ | ||
"name": "discord-verify", | ||
"version": "0.0.2-beta.17", | ||
"version": "0.0.2-beta.18", | ||
"author": "Ian Mitchell", | ||
@@ -5,0 +5,0 @@ "description": "A library for verifying the authenticity of requests coming from the Discord Interactions API", |
@@ -29,8 +29,8 @@ # discord-verify | ||
### Custom Validation | ||
### Custom Verification | ||
If you want to validate requests from frameworks such as Express or Fastify that have their own request classes, you can import the validate function and pass raw values to it. | ||
If you want to verify requests from frameworks such as Express or Fastify that have their own request classes, you can import the verify function and pass raw values to it. | ||
```ts | ||
import { validate } from "discord-verify"; | ||
import { verify } from "discord-verify/node"; | ||
@@ -51,6 +51,6 @@ async function handleRequest( | ||
const isValid = await validate( | ||
const isValid = await verify( | ||
rawBody, | ||
signature, | ||
timestmap, | ||
timestamp, | ||
this.client.publicKey, | ||
@@ -66,2 +66,40 @@ crypto.subtle | ||
#### Node 17 and Older | ||
If you are using Node 17 or lower, you need to make some changes: | ||
```diff | ||
+ import { webcrypto } from "node:crypto"; | ||
+ import { verify, PlatformAlgorithms } from "discord-verify/node"; | ||
async function handleRequest( | ||
req: FastifyRequest<{ | ||
Body: APIInteraction; | ||
Headers: { | ||
"x-signature-ed25519": string; | ||
"x-signature-timestamp": string; | ||
}; | ||
}>, | ||
res: FastifyReply | ||
) { | ||
const signature = req.headers["x-signature-ed25519"]; | ||
const timestamp = req.headers["x-signature-timestamp"]; | ||
const rawBody = JSON.stringify(req.body); | ||
const isValid = await verify( | ||
rawBody, | ||
signature, | ||
timestamp, | ||
this.client.publicKey, | ||
- crypto.subtle | ||
+ webcrypto.subtle, | ||
+ PlatformAlgorithms.Node16 | ||
); | ||
if (!isValid) { | ||
return res.code(401).send("Invalid signature"); | ||
} | ||
} | ||
``` | ||
### Options | ||
@@ -68,0 +106,0 @@ |
@@ -14,18 +14,39 @@ import type { | ||
const KEYS = { | ||
ZERO: 48, | ||
A: 65, | ||
a: 97, | ||
}; | ||
function hexCharToBinary(char: string) { | ||
const code = char.charCodeAt(0); | ||
if (code >= KEYS.a) { | ||
return code - KEYS.a + 10; | ||
} | ||
if (code >= KEYS.A) { | ||
return code - KEYS.A + 10; | ||
} | ||
return code - KEYS.ZERO; | ||
} | ||
/** | ||
* Helper method that takes in a hex string and converts it to its binary representation. | ||
* @param hex Hex string to convert to binary | ||
* @param key Hex string to convert to binary | ||
* @returns The binary form of a hex string | ||
*/ | ||
export function hexToBinary(hex: string | null) { | ||
if (hex == null) { | ||
return new Uint8Array(0); | ||
export function hexStringToBinary(key: string | null) { | ||
if (key == null) { | ||
return new Uint8Array(0).buffer; | ||
} | ||
const buffer = new Uint8Array(Math.ceil(hex.length / 2)); | ||
for (let i = 0; i < buffer.length; i++) { | ||
buffer[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16); | ||
const view = new Uint8Array(key.length / 2); | ||
for (let i = 0, o = 0; i < key.length; i += 2, ++o) { | ||
view[o] = (hexCharToBinary(key[i]) << 4) | hexCharToBinary(key[i + 1]); | ||
} | ||
return buffer; | ||
return view.buffer; | ||
} | ||
@@ -40,3 +61,3 @@ | ||
"raw", | ||
hexToBinary(publicKey), | ||
hexStringToBinary(publicKey), | ||
algorithm, | ||
@@ -54,2 +75,9 @@ true, | ||
export const PlatformAlgorithm = { | ||
Web: "Ed25519", | ||
Node18: "Ed25519", | ||
Node16: { | ||
name: "NODE-ED25519", | ||
namedCurve: "NODE-ED25519", | ||
public: true, | ||
}, | ||
Cloudflare: { | ||
@@ -61,2 +89,3 @@ name: "NODE-ED25519", | ||
Vercel: { | ||
// TODO: ecdsa? | ||
name: "eddsa", | ||
@@ -79,3 +108,3 @@ namedCurve: "ed25519", | ||
subtleCrypto: SubtleCrypto, | ||
algorithm: SubtleCryptoImportKeyAlgorithm | string = "Ed25519" | ||
algorithm: SubtleCryptoImportKeyAlgorithm | string = PlatformAlgorithm.Node18 | ||
) { | ||
@@ -87,10 +116,3 @@ const clone = request.clone(); | ||
return validate( | ||
body, | ||
signature, | ||
timestamp, | ||
publicKey, | ||
subtleCrypto, | ||
algorithm | ||
); | ||
return verify(body, signature, timestamp, publicKey, subtleCrypto, algorithm); | ||
} | ||
@@ -108,3 +130,3 @@ | ||
*/ | ||
export async function validate( | ||
export async function verify( | ||
rawBody: string | null | undefined, | ||
@@ -115,3 +137,3 @@ signature: string | null | undefined, | ||
subtleCrypto: SubtleCrypto, | ||
algorithm: SubtleCryptoImportKeyAlgorithm | string = "Ed25519" | ||
algorithm: SubtleCryptoImportKeyAlgorithm | string = PlatformAlgorithm.Node18 | ||
) { | ||
@@ -128,3 +150,3 @@ if (timestamp == null || signature == null || rawBody == null) { | ||
key, | ||
hexToBinary(signature), | ||
hexStringToBinary(signature), | ||
encoder.encode(`${timestamp ?? ""}${rawBody}`) | ||
@@ -131,0 +153,0 @@ ); |
// eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error | ||
// @ts-ignore-error Node Crypto types are not well defined yet | ||
import crypto from "node:crypto"; | ||
import { isValidRequest as verifyRequest } from "./lib/verify"; | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error | ||
// @ts-ignore-error Node Process | ||
import process from "node:process"; | ||
import { | ||
isValidRequest as verifyRequest, | ||
PlatformAlgorithm, | ||
} from "./lib/verify"; | ||
import type { | ||
@@ -10,3 +16,3 @@ Request, | ||
} from "./types"; | ||
export { hexToBinary, validate } from "./lib/verify"; | ||
export { hexStringToBinary, PlatformAlgorithm, verify } from "./lib/verify"; | ||
@@ -23,12 +29,13 @@ /** | ||
publicKey: string, | ||
algorithm: SubtleCryptoImportKeyAlgorithm | string = "Ed25519" | ||
algorithm?: SubtleCryptoImportKeyAlgorithm | string | ||
) { | ||
return verifyRequest( | ||
request, | ||
publicKey, | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error | ||
// @ts-ignore-error Node Crypto types are not well defined yet | ||
crypto.subtle as SubtleCrypto, | ||
algorithm | ||
); | ||
const [majorVersion] = process.versions.node.split("."); | ||
const algo = | ||
majorVersion >= 18 ? PlatformAlgorithm.Node18 : PlatformAlgorithm.Node16; | ||
const subtleCrypto = | ||
majorVersion >= 18 | ||
? (crypto.subtle as SubtleCrypto) | ||
: (crypto.webcrypto.subtle as SubtleCrypto); | ||
return verifyRequest(request, publicKey, subtleCrypto, algorithm ?? algo); | ||
} |
@@ -1,2 +0,5 @@ | ||
import { isValidRequest as verifyRequest } from "./lib/verify"; | ||
import { | ||
isValidRequest as verifyRequest, | ||
PlatformAlgorithm, | ||
} from "./lib/verify"; | ||
import type { | ||
@@ -7,3 +10,3 @@ Request, | ||
} from "./types"; | ||
export { hexToBinary, PlatformAlgorithm, validate } from "./lib/verify"; | ||
export { hexStringToBinary, PlatformAlgorithm, verify } from "./lib/verify"; | ||
@@ -24,5 +27,5 @@ declare const crypto: { | ||
publicKey: string, | ||
algorithm: SubtleCryptoImportKeyAlgorithm | string = "Ed25519" | ||
algorithm: SubtleCryptoImportKeyAlgorithm | string = PlatformAlgorithm.Web | ||
) { | ||
return verifyRequest(request, publicKey, crypto.subtle, algorithm); | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
24954
627
120