Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ program
.command('verify')
.argument('<receipt-file-or-id>', 'Receipt file path, -, receipt id, or share URL')
.option('--key-url <url>', 'Public key endpoint URL')
.option('--key-file <path>', 'Path to public key PEM or base64 DER')
.option('--key-file <path>', 'Path to public key PEM, base64 DER, or raw Ed25519 base64')
.option('--key-id <id>', 'Expected key id')
.option('--json', 'Emit machine-readable JSON output')
.option('-q, --quiet', 'Suppress stdout and return exit code only')
Expand Down
4 changes: 4 additions & 0 deletions src/keyResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createPublicKey } from 'node:crypto';
import { readFile } from 'node:fs/promises';

export const DEFAULT_KEY_URL = 'https://app.permissionprotocol.com/api/v1/keys/current';
const ED25519_SPKI_PREFIX = Buffer.from('302a300506032b6570032100', 'hex');

export type ResolveKeyOptions = {
keyFile?: string;
Expand Down Expand Up @@ -31,6 +32,9 @@ function asPublicKey(raw: string): ReturnType<typeof createPublicKey> {
return createPublicKey(trimmed);
}
const der = Buffer.from(trimmed, 'base64');
if (der.length === 32) {
return createPublicKey({ key: Buffer.concat([ED25519_SPKI_PREFIX, der]), format: 'der', type: 'spki' });
}
return createPublicKey({ key: der, format: 'der', type: 'spki' });
}

Expand Down
1 change: 1 addition & 0 deletions tests/fixtures/public-key.raw-base64
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
utC/MffkkEO2hXR37Ilq4ut4UpZwdrwmtbGw/eEymo0=
10 changes: 10 additions & 0 deletions tests/verify.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ async function loadJson(name: string): Promise<unknown> {
}

const keyFile = resolve(process.cwd(), 'tests/fixtures/public-key.pem');
const rawKeyFile = resolve(process.cwd(), 'tests/fixtures/public-key.raw-base64');

describe('verifyReceipt', () => {
it('verifies a valid receipt', async () => {
Expand All @@ -20,6 +21,15 @@ describe('verifyReceipt', () => {
}
});

it('verifies a valid receipt with a raw Ed25519 base64 public key', async () => {
const receipt = await loadJson('valid.json');
const result = await verifyReceipt(receipt, { keyFile: rawKeyFile, noNetwork: true });
expect(result.verified).toBe(true);
if (result.verified) {
expect(result.receiptId).toBe('rcpt_valid_001');
}
});

it('returns expired for expired receipt', async () => {
const receipt = await loadJson('expired.json');
const result = await verifyReceipt(receipt, { keyFile, noNetwork: true });
Expand Down