-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
137 lines (114 loc) · 3.34 KB
/
index.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
const express = require('express');
const bodyParser = require('body-parser');
const WebCrypto = require('node-webcrypto-p11');
const { MongoClient, ObjectId } = require('mongodb');
const atob = require('atob');
const config = {
library: '/usr/lib/softhsm/libsofthsm2.so',
name: 'SoftHSMv2',
slot: 0,
readWrite: true,
pin: '1234',
};
const crypto = new WebCrypto(config);
const app = express();
app.use(bodyParser.json({ limit: '50mb' }));
const uri = 'mongodb://mongodb:27017';
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
let db;
client.connect((err) => {
if (err) throw err;
db = client.db('signingDB');
console.log('Connected to MongoDB');
});
async function generateAndStoreKeyPair(run, userInfo) {
const keyPair = await crypto.subtle.generateKey(
{
name: 'RSASSA-PKCS1-v1_5',
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: { name: 'SHA-256' },
},
true,
['sign', 'verify']
);
const privateKeyJwk = await crypto.subtle.exportKey(
'jwk',
keyPair.privateKey
);
const publicKeyJwk = await crypto.subtle.exportKey('jwk', keyPair.publicKey);
const fingerprint = await crypto.subtle.digest(
'SHA-256',
new TextEncoder().encode(JSON.stringify(publicKeyJwk))
);
const certificate = {
run,
userInfo,
publicKey: publicKeyJwk,
fingerprint: Buffer.from(fingerprint).toString('hex'),
issuedAt: new Date(),
};
const result = await db.collection('certificates').insertOne(certificate);
await db.collection('keys').insertOne({
_id: result.insertedId,
privateKey: privateKeyJwk,
});
return result.insertedId;
}
async function getPrivateKeyByRun(run) {
const certificate = await db.collection('certificates').findOne({ run });
if (!certificate) throw new Error('Certificate not found');
const key = await db.collection('keys').findOne({ _id: certificate._id });
if (!key) throw new Error('Key not found');
return key.privateKey;
}
app.post('/register', async (req, res) => {
const { run, userInfo } = req.body;
if (!run || !userInfo) {
return res.status(400).json({ error: 'RUN and user info are required' });
}
try {
const certificateId = await generateAndStoreKeyPair(run, userInfo);
res.json({ certificateId });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.post('/sign', async (req, res) => {
const { documentBase64, run } = req.body;
if (!documentBase64 || !run) {
return res.status(400).json({ error: 'Document and RUN are required' });
}
try {
const documentBuffer = Buffer.from(documentBase64, 'base64');
const privateKeyJwk = await getPrivateKeyByRun(run);
const privateKey = await crypto.subtle.importKey(
'jwk',
privateKeyJwk,
{
name: 'RSASSA-PKCS1-v1_5',
hash: { name: 'SHA-256' },
},
false,
['sign']
);
const signature = await crypto.subtle.sign(
{
name: 'RSASSA-PKCS1-v1_5',
},
privateKey,
documentBuffer
);
const signatureHex = Buffer.from(signature).toString('hex');
res.json({ documentBase64, signature: signatureHex });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});