-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathparse-and-verify-fastify.ts
114 lines (95 loc) · 2.86 KB
/
parse-and-verify-fastify.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import Fastify from 'fastify';
import fastifyRawBody from 'fastify-raw-body';
import {
verifyDigestHeader,
parseRequestSignature,
verifyParsedSignature,
ParsedSignature,
} from '@/index'; // REPLACE with '@misskey-dev/node-http-message-signatures'
import { ed25519, rsa4096 } from 'test/keys'; // for test
/**
* keyId - publicKeyPem Map
*/
const publicKeyMap = new Map([
['https://sender.example.com/users/0001#main-key', rsa4096.publicKey],
['https://sender.example.com/users/0001#ed25519-key', ed25519.publicKey],
]);
const fastify = Fastify({
logger: true,
});
await fastify.register(fastifyRawBody, {
global: false,
encoding: null,
runFirst: true,
});
fastify.post('/inbox', async (request, reply) => {
const verifyDigest = await verifyDigestHeader(request.raw, request.body, true);
if (verifyDigest !== true) {
reply.code(401);
return;
}
// Parse raw request
let parsedSignature: ParsedSignature;
try {
parsedSignature = parseRequestSignature(request.raw);
} catch (e) {
reply.code(401);
return e; // DO NOT return stack trace in production!!!
}
try {
// If in production, you may be needed to pick public keys from a database or something
const result = await verifyParsedSignature(parsedSignature, publicKeyMap, (...args) => console.log(args));
if (result === true) {
reply.code(202);
return '';
}
} catch (e) {
reply.code(401);
return e; // DO NOT return stack trace in production!!!
}
reply.code(401);
return 'signature verification failed';
});
//#region test
const body = 'Hello, world!';
import {
genRFC3230DigestHeader,
signAsDraftToRequest,
PrivateKey,
} from '@/index';
describe('parse and verify usage', () => { //#region sign logic
const includeHeaders = ['(request-target)', 'date', 'host', 'digest'];
async function createRequest(url: string | URL, body: string, key: PrivateKey) {
const u = new URL(url);
const request = {
headers: {
Date: (new Date()).toUTCString(),
Host: u.host,
'Content-Type': 'text/plain',
},
method: 'POST',
url: u.href,
payload: body,
} as const;
// Draft
request.headers['Digest'] = await genRFC3230DigestHeader(body, 'SHA-256');
await signAsDraftToRequest(request, key, includeHeaders);
return request;
}
//#endregion
test('draft fastify', async () => {
const url = 'http://example.com/inbox';
const response = await fastify.inject(
await createRequest(url, body, { keyId: 'https://sender.example.com/users/0001#ed25519-key', privateKeyPem: ed25519.privateKey })
);
expect(response.body).toBe('');
});
test('draft fastify invalid', async () => {
const url = 'http://example.com/inbox';
const response = await fastify.inject(
await createRequest(url, body, { keyId: 'https://sender.example.com/users/0001#ed25519-key', privateKeyPem: rsa4096.privateKey })
);
expect(response.body).toBe('signature verification failed');
});
});
//#endregion