This repository has been archived by the owner on Jul 1, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
server.js
161 lines (143 loc) · 5.38 KB
/
server.js
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
'use strict';
require('dotenv').config({path: '/run/secrets/env'})
const consts = require('./constants')
const express = require('express')
const cors = require('cors')
const forge = require('node-forge')
const PORT = 8000
const HOST = '0.0.0.0'
const ALLOWED_ORIGINS = ['http://localhost:3000', 'https://covidpass.marvinsextro.de']
const APPLE_CA_CERTIFICATE = forge.pki.certificateFromPem(
process.env.APPLE_WWDR_CERT_PEM ||
`-----BEGIN CERTIFICATE-----
MIIEIjCCAwqgAwIBAgIIAd68xDltoBAwDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UE
BhMCVVMxEzARBgNVBAoTCkFwcGxlIEluYy4xJjAkBgNVBAsTHUFwcGxlIENlcnRp
ZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1BcHBsZSBSb290IENBMB4XDTEz
MDIwNzIxNDg0N1oXDTIzMDIwNzIxNDg0N1owgZYxCzAJBgNVBAYTAlVTMRMwEQYD
VQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3JsZHdpZGUgRGV2ZWxv
cGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3aWRlIERldmVsb3Bl
ciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQDKOFSmy1aqyCQ5SOmM7uxfuH8mkbw0U3rOfGOA
YXdkXqUHI7Y5/lAtFVZYcC1+xG7BSoU+L/DehBqhV8mvexj/avoVEkkVCBmsqtsq
Mu2WY2hSFT2Miuy/axiV4AOsAX2XBWfODoWVN2rtCbauZ81RZJ/GXNG8V25nNYB2
NqSHgW44j9grFU57Jdhav06DwY3Sk9UacbVgnJ0zTlX5ElgMhrgWDcHld0WNUEi6
Ky3klIXh6MSdxmilsKP8Z35wugJZS3dCkTm59c3hTO/AO0iMpuUhXf1qarunFjVg
0uat80YpyejDi+l5wGphZxWy8P3laLxiX27Pmd3vG2P+kmWrAgMBAAGjgaYwgaMw
HQYDVR0OBBYEFIgnFwmpthhgi+zruvZHWcVSVKO3MA8GA1UdEwEB/wQFMAMBAf8w
HwYDVR0jBBgwFoAUK9BpR5R2Cf70a40uQKb3R01/CF4wLgYDVR0fBCcwJTAjoCGg
H4YdaHR0cDovL2NybC5hcHBsZS5jb20vcm9vdC5jcmwwDgYDVR0PAQH/BAQDAgGG
MBAGCiqGSIb3Y2QGAgEEAgUAMA0GCSqGSIb3DQEBBQUAA4IBAQBPz+9Zviz1smwv
j+4ThzLoBTWobot9yWkMudkXvHcs1Gfi/ZptOllc34MBvbKuKmFysa/Nw0Uwj6OD
Dc4dR7Txk4qjdJukw5hyhzs+r0ULklS5MruQGFNrCk4QttkdUGwhgAqJTleMa1s8
Pab93vcNIx0LSiaHP7qRkkykGRIZbVf1eliHe2iK5IaMSuviSRSqpd1VAKmuu0sw
ruGgsbwpgOYJd+W+NKIByn/c4grmO7i77LpilfMFY0GCzQ87HUyVpNur+cmV6U/k
TecmmYHpvPm0KdIBembhLoz2IYrF+Hjhga6/05Cdqa3zr/04GpZnMBxRpVzscYqC
tGwPDBUf
-----END CERTIFICATE-----`,
);
const app = express()
app.use(cors({
origin: function(origin, callback) {
if (!origin) return callback(null, true)
if (ALLOWED_ORIGINS.indexOf(origin) === -1){
var msg = 'The CORS policy for this site does not allow access from the specified Origin.'
return callback(new Error(msg), false)
}
return callback(null, true)
}
}))
app.use(express.json())
app.get('/signing_identity', async (req, res) => {
res.type('application/json')
res.status(200).send(
JSON.stringify(
{
pass_identifier: consts.SECRETS.PASS_TYPE_ID,
pass_team_id: consts.SECRETS.TEAM_ID
}
)
)
});
app.post('/sign_manifest', async (req, res) => {
const manifest = req.body['manifest']
const manifestJson = JSON.parse(manifest)
if (((manifestJson["icon.png"] !== consts.HASHES.IMG1X_BLACK) ||
(manifestJson["[email protected]"] !== consts.HASHES.IMG2X_BLACK)) &&
((manifestJson["icon.png"] !== consts.HASHES.IMG1X_WHITE) ||
(manifestJson["[email protected]"] !== consts.HASHES.IMG2X_WHITE))) {
res.status(400).send('Modified icon')
return
}
if (((manifestJson["logo.png"] !== consts.HASHES.IMG1X_BLACK) ||
(manifestJson["[email protected]"] !== consts.HASHES.IMG2X_BLACK)) &&
((manifestJson["logo.png"] !== consts.HASHES.IMG1X_WHITE) ||
(manifestJson["[email protected]"] !== consts.HASHES.IMG2X_WHITE))) {
res.status(400).send('Modified logo')
return
}
let certificate
let key
try {
// From https://github.com/walletpass/pass-js/blob/2b6475749582ca3ea742a91466303cb0eb01a13a/src/template.ts#L249
certificate = forge.pki.certificateFromPem(consts.SECRETS.CERT);
if (!certificate) {
res.status(500).send('Failed to load signing identity')
return
}
const pemMessages = forge.pem.decode(consts.SECRETS.CERT);
const signerKeyMessage = pemMessages.find(message =>
message.type.includes('KEY'),
);
if (signerKeyMessage) {
key = forge.pki.decryptRsaPrivateKey(
forge.pem.encode(signerKeyMessage),
consts.SECRETS.PASSPHRASE
)
if (!key) {
console.log("Failed to decode the key.")
}
}
} catch (e) {
console.log(e)
res.status(500).send('Failed to load signing identity')
return
}
if (!certificate || !key) {
res.status(500).send('Failed to load signing identity')
return
}
// From https://github.com/walletpass/pass-js/blob/2b6475749582ca3ea742a91466303cb0eb01a13a/src/lib/signManifest-forge.ts#L42
const p7 = forge.pkcs7.createSignedData();
p7.content = manifest;
p7.addCertificate(certificate);
p7.addCertificate(APPLE_CA_CERTIFICATE);
p7.addSigner({
key: forge.pki.privateKeyToPem(key),
certificate,
digestAlgorithm: forge.pki.oids.sha1,
authenticatedAttributes: [
{
type: forge.pki.oids.contentType,
value: forge.pki.oids.data,
},
{
type: forge.pki.oids.messageDigest,
// value will be auto-populated at signing time
},
{
type: forge.pki.oids.signingTime,
// value will be auto-populated at signing time
// value: new Date('2050-01-01T00:00:00Z')
},
],
});
/**
* Creating a detached signature because we don't need the signed content.
*/
p7.sign({ detached: true });
let signature = Buffer.from(forge.asn1.toDer(p7.toAsn1()).getBytes(), 'binary');
res.type('application/octet-stream')
res.status(200).send(signature)
});
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);