1 | // Copyright 2015 Joyent, Inc.
|
---|
2 |
|
---|
3 | module.exports = {
|
---|
4 | read: read,
|
---|
5 | readPkcs1: readPkcs1,
|
---|
6 | write: write,
|
---|
7 | writePkcs1: writePkcs1
|
---|
8 | };
|
---|
9 |
|
---|
10 | var assert = require('assert-plus');
|
---|
11 | var asn1 = require('asn1');
|
---|
12 | var Buffer = require('safer-buffer').Buffer;
|
---|
13 | var algs = require('../algs');
|
---|
14 | var utils = require('../utils');
|
---|
15 |
|
---|
16 | var Key = require('../key');
|
---|
17 | var PrivateKey = require('../private-key');
|
---|
18 | var pem = require('./pem');
|
---|
19 |
|
---|
20 | var pkcs8 = require('./pkcs8');
|
---|
21 | var readECDSACurve = pkcs8.readECDSACurve;
|
---|
22 |
|
---|
23 | function read(buf, options) {
|
---|
24 | return (pem.read(buf, options, 'pkcs1'));
|
---|
25 | }
|
---|
26 |
|
---|
27 | function write(key, options) {
|
---|
28 | return (pem.write(key, options, 'pkcs1'));
|
---|
29 | }
|
---|
30 |
|
---|
31 | /* Helper to read in a single mpint */
|
---|
32 | function readMPInt(der, nm) {
|
---|
33 | assert.strictEqual(der.peek(), asn1.Ber.Integer,
|
---|
34 | nm + ' is not an Integer');
|
---|
35 | return (utils.mpNormalize(der.readString(asn1.Ber.Integer, true)));
|
---|
36 | }
|
---|
37 |
|
---|
38 | function readPkcs1(alg, type, der) {
|
---|
39 | switch (alg) {
|
---|
40 | case 'RSA':
|
---|
41 | if (type === 'public')
|
---|
42 | return (readPkcs1RSAPublic(der));
|
---|
43 | else if (type === 'private')
|
---|
44 | return (readPkcs1RSAPrivate(der));
|
---|
45 | throw (new Error('Unknown key type: ' + type));
|
---|
46 | case 'DSA':
|
---|
47 | if (type === 'public')
|
---|
48 | return (readPkcs1DSAPublic(der));
|
---|
49 | else if (type === 'private')
|
---|
50 | return (readPkcs1DSAPrivate(der));
|
---|
51 | throw (new Error('Unknown key type: ' + type));
|
---|
52 | case 'EC':
|
---|
53 | case 'ECDSA':
|
---|
54 | if (type === 'private')
|
---|
55 | return (readPkcs1ECDSAPrivate(der));
|
---|
56 | else if (type === 'public')
|
---|
57 | return (readPkcs1ECDSAPublic(der));
|
---|
58 | throw (new Error('Unknown key type: ' + type));
|
---|
59 | case 'EDDSA':
|
---|
60 | case 'EdDSA':
|
---|
61 | if (type === 'private')
|
---|
62 | return (readPkcs1EdDSAPrivate(der));
|
---|
63 | throw (new Error(type + ' keys not supported with EdDSA'));
|
---|
64 | default:
|
---|
65 | throw (new Error('Unknown key algo: ' + alg));
|
---|
66 | }
|
---|
67 | }
|
---|
68 |
|
---|
69 | function readPkcs1RSAPublic(der) {
|
---|
70 | // modulus and exponent
|
---|
71 | var n = readMPInt(der, 'modulus');
|
---|
72 | var e = readMPInt(der, 'exponent');
|
---|
73 |
|
---|
74 | // now, make the key
|
---|
75 | var key = {
|
---|
76 | type: 'rsa',
|
---|
77 | parts: [
|
---|
78 | { name: 'e', data: e },
|
---|
79 | { name: 'n', data: n }
|
---|
80 | ]
|
---|
81 | };
|
---|
82 |
|
---|
83 | return (new Key(key));
|
---|
84 | }
|
---|
85 |
|
---|
86 | function readPkcs1RSAPrivate(der) {
|
---|
87 | var version = readMPInt(der, 'version');
|
---|
88 | assert.strictEqual(version[0], 0);
|
---|
89 |
|
---|
90 | // modulus then public exponent
|
---|
91 | var n = readMPInt(der, 'modulus');
|
---|
92 | var e = readMPInt(der, 'public exponent');
|
---|
93 | var d = readMPInt(der, 'private exponent');
|
---|
94 | var p = readMPInt(der, 'prime1');
|
---|
95 | var q = readMPInt(der, 'prime2');
|
---|
96 | var dmodp = readMPInt(der, 'exponent1');
|
---|
97 | var dmodq = readMPInt(der, 'exponent2');
|
---|
98 | var iqmp = readMPInt(der, 'iqmp');
|
---|
99 |
|
---|
100 | // now, make the key
|
---|
101 | var key = {
|
---|
102 | type: 'rsa',
|
---|
103 | parts: [
|
---|
104 | { name: 'n', data: n },
|
---|
105 | { name: 'e', data: e },
|
---|
106 | { name: 'd', data: d },
|
---|
107 | { name: 'iqmp', data: iqmp },
|
---|
108 | { name: 'p', data: p },
|
---|
109 | { name: 'q', data: q },
|
---|
110 | { name: 'dmodp', data: dmodp },
|
---|
111 | { name: 'dmodq', data: dmodq }
|
---|
112 | ]
|
---|
113 | };
|
---|
114 |
|
---|
115 | return (new PrivateKey(key));
|
---|
116 | }
|
---|
117 |
|
---|
118 | function readPkcs1DSAPrivate(der) {
|
---|
119 | var version = readMPInt(der, 'version');
|
---|
120 | assert.strictEqual(version.readUInt8(0), 0);
|
---|
121 |
|
---|
122 | var p = readMPInt(der, 'p');
|
---|
123 | var q = readMPInt(der, 'q');
|
---|
124 | var g = readMPInt(der, 'g');
|
---|
125 | var y = readMPInt(der, 'y');
|
---|
126 | var x = readMPInt(der, 'x');
|
---|
127 |
|
---|
128 | // now, make the key
|
---|
129 | var key = {
|
---|
130 | type: 'dsa',
|
---|
131 | parts: [
|
---|
132 | { name: 'p', data: p },
|
---|
133 | { name: 'q', data: q },
|
---|
134 | { name: 'g', data: g },
|
---|
135 | { name: 'y', data: y },
|
---|
136 | { name: 'x', data: x }
|
---|
137 | ]
|
---|
138 | };
|
---|
139 |
|
---|
140 | return (new PrivateKey(key));
|
---|
141 | }
|
---|
142 |
|
---|
143 | function readPkcs1EdDSAPrivate(der) {
|
---|
144 | var version = readMPInt(der, 'version');
|
---|
145 | assert.strictEqual(version.readUInt8(0), 1);
|
---|
146 |
|
---|
147 | // private key
|
---|
148 | var k = der.readString(asn1.Ber.OctetString, true);
|
---|
149 |
|
---|
150 | der.readSequence(0xa0);
|
---|
151 | var oid = der.readOID();
|
---|
152 | assert.strictEqual(oid, '1.3.101.112', 'the ed25519 curve identifier');
|
---|
153 |
|
---|
154 | der.readSequence(0xa1);
|
---|
155 | var A = utils.readBitString(der);
|
---|
156 |
|
---|
157 | var key = {
|
---|
158 | type: 'ed25519',
|
---|
159 | parts: [
|
---|
160 | { name: 'A', data: utils.zeroPadToLength(A, 32) },
|
---|
161 | { name: 'k', data: k }
|
---|
162 | ]
|
---|
163 | };
|
---|
164 |
|
---|
165 | return (new PrivateKey(key));
|
---|
166 | }
|
---|
167 |
|
---|
168 | function readPkcs1DSAPublic(der) {
|
---|
169 | var y = readMPInt(der, 'y');
|
---|
170 | var p = readMPInt(der, 'p');
|
---|
171 | var q = readMPInt(der, 'q');
|
---|
172 | var g = readMPInt(der, 'g');
|
---|
173 |
|
---|
174 | var key = {
|
---|
175 | type: 'dsa',
|
---|
176 | parts: [
|
---|
177 | { name: 'y', data: y },
|
---|
178 | { name: 'p', data: p },
|
---|
179 | { name: 'q', data: q },
|
---|
180 | { name: 'g', data: g }
|
---|
181 | ]
|
---|
182 | };
|
---|
183 |
|
---|
184 | return (new Key(key));
|
---|
185 | }
|
---|
186 |
|
---|
187 | function readPkcs1ECDSAPublic(der) {
|
---|
188 | der.readSequence();
|
---|
189 |
|
---|
190 | var oid = der.readOID();
|
---|
191 | assert.strictEqual(oid, '1.2.840.10045.2.1', 'must be ecPublicKey');
|
---|
192 |
|
---|
193 | var curveOid = der.readOID();
|
---|
194 |
|
---|
195 | var curve;
|
---|
196 | var curves = Object.keys(algs.curves);
|
---|
197 | for (var j = 0; j < curves.length; ++j) {
|
---|
198 | var c = curves[j];
|
---|
199 | var cd = algs.curves[c];
|
---|
200 | if (cd.pkcs8oid === curveOid) {
|
---|
201 | curve = c;
|
---|
202 | break;
|
---|
203 | }
|
---|
204 | }
|
---|
205 | assert.string(curve, 'a known ECDSA named curve');
|
---|
206 |
|
---|
207 | var Q = der.readString(asn1.Ber.BitString, true);
|
---|
208 | Q = utils.ecNormalize(Q);
|
---|
209 |
|
---|
210 | var key = {
|
---|
211 | type: 'ecdsa',
|
---|
212 | parts: [
|
---|
213 | { name: 'curve', data: Buffer.from(curve) },
|
---|
214 | { name: 'Q', data: Q }
|
---|
215 | ]
|
---|
216 | };
|
---|
217 |
|
---|
218 | return (new Key(key));
|
---|
219 | }
|
---|
220 |
|
---|
221 | function readPkcs1ECDSAPrivate(der) {
|
---|
222 | var version = readMPInt(der, 'version');
|
---|
223 | assert.strictEqual(version.readUInt8(0), 1);
|
---|
224 |
|
---|
225 | // private key
|
---|
226 | var d = der.readString(asn1.Ber.OctetString, true);
|
---|
227 |
|
---|
228 | der.readSequence(0xa0);
|
---|
229 | var curve = readECDSACurve(der);
|
---|
230 | assert.string(curve, 'a known elliptic curve');
|
---|
231 |
|
---|
232 | der.readSequence(0xa1);
|
---|
233 | var Q = der.readString(asn1.Ber.BitString, true);
|
---|
234 | Q = utils.ecNormalize(Q);
|
---|
235 |
|
---|
236 | var key = {
|
---|
237 | type: 'ecdsa',
|
---|
238 | parts: [
|
---|
239 | { name: 'curve', data: Buffer.from(curve) },
|
---|
240 | { name: 'Q', data: Q },
|
---|
241 | { name: 'd', data: d }
|
---|
242 | ]
|
---|
243 | };
|
---|
244 |
|
---|
245 | return (new PrivateKey(key));
|
---|
246 | }
|
---|
247 |
|
---|
248 | function writePkcs1(der, key) {
|
---|
249 | der.startSequence();
|
---|
250 |
|
---|
251 | switch (key.type) {
|
---|
252 | case 'rsa':
|
---|
253 | if (PrivateKey.isPrivateKey(key))
|
---|
254 | writePkcs1RSAPrivate(der, key);
|
---|
255 | else
|
---|
256 | writePkcs1RSAPublic(der, key);
|
---|
257 | break;
|
---|
258 | case 'dsa':
|
---|
259 | if (PrivateKey.isPrivateKey(key))
|
---|
260 | writePkcs1DSAPrivate(der, key);
|
---|
261 | else
|
---|
262 | writePkcs1DSAPublic(der, key);
|
---|
263 | break;
|
---|
264 | case 'ecdsa':
|
---|
265 | if (PrivateKey.isPrivateKey(key))
|
---|
266 | writePkcs1ECDSAPrivate(der, key);
|
---|
267 | else
|
---|
268 | writePkcs1ECDSAPublic(der, key);
|
---|
269 | break;
|
---|
270 | case 'ed25519':
|
---|
271 | if (PrivateKey.isPrivateKey(key))
|
---|
272 | writePkcs1EdDSAPrivate(der, key);
|
---|
273 | else
|
---|
274 | writePkcs1EdDSAPublic(der, key);
|
---|
275 | break;
|
---|
276 | default:
|
---|
277 | throw (new Error('Unknown key algo: ' + key.type));
|
---|
278 | }
|
---|
279 |
|
---|
280 | der.endSequence();
|
---|
281 | }
|
---|
282 |
|
---|
283 | function writePkcs1RSAPublic(der, key) {
|
---|
284 | der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
|
---|
285 | der.writeBuffer(key.part.e.data, asn1.Ber.Integer);
|
---|
286 | }
|
---|
287 |
|
---|
288 | function writePkcs1RSAPrivate(der, key) {
|
---|
289 | var ver = Buffer.from([0]);
|
---|
290 | der.writeBuffer(ver, asn1.Ber.Integer);
|
---|
291 |
|
---|
292 | der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
|
---|
293 | der.writeBuffer(key.part.e.data, asn1.Ber.Integer);
|
---|
294 | der.writeBuffer(key.part.d.data, asn1.Ber.Integer);
|
---|
295 | der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
|
---|
296 | der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
|
---|
297 | if (!key.part.dmodp || !key.part.dmodq)
|
---|
298 | utils.addRSAMissing(key);
|
---|
299 | der.writeBuffer(key.part.dmodp.data, asn1.Ber.Integer);
|
---|
300 | der.writeBuffer(key.part.dmodq.data, asn1.Ber.Integer);
|
---|
301 | der.writeBuffer(key.part.iqmp.data, asn1.Ber.Integer);
|
---|
302 | }
|
---|
303 |
|
---|
304 | function writePkcs1DSAPrivate(der, key) {
|
---|
305 | var ver = Buffer.from([0]);
|
---|
306 | der.writeBuffer(ver, asn1.Ber.Integer);
|
---|
307 |
|
---|
308 | der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
|
---|
309 | der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
|
---|
310 | der.writeBuffer(key.part.g.data, asn1.Ber.Integer);
|
---|
311 | der.writeBuffer(key.part.y.data, asn1.Ber.Integer);
|
---|
312 | der.writeBuffer(key.part.x.data, asn1.Ber.Integer);
|
---|
313 | }
|
---|
314 |
|
---|
315 | function writePkcs1DSAPublic(der, key) {
|
---|
316 | der.writeBuffer(key.part.y.data, asn1.Ber.Integer);
|
---|
317 | der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
|
---|
318 | der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
|
---|
319 | der.writeBuffer(key.part.g.data, asn1.Ber.Integer);
|
---|
320 | }
|
---|
321 |
|
---|
322 | function writePkcs1ECDSAPublic(der, key) {
|
---|
323 | der.startSequence();
|
---|
324 |
|
---|
325 | der.writeOID('1.2.840.10045.2.1'); /* ecPublicKey */
|
---|
326 | var curve = key.part.curve.data.toString();
|
---|
327 | var curveOid = algs.curves[curve].pkcs8oid;
|
---|
328 | assert.string(curveOid, 'a known ECDSA named curve');
|
---|
329 | der.writeOID(curveOid);
|
---|
330 |
|
---|
331 | der.endSequence();
|
---|
332 |
|
---|
333 | var Q = utils.ecNormalize(key.part.Q.data, true);
|
---|
334 | der.writeBuffer(Q, asn1.Ber.BitString);
|
---|
335 | }
|
---|
336 |
|
---|
337 | function writePkcs1ECDSAPrivate(der, key) {
|
---|
338 | var ver = Buffer.from([1]);
|
---|
339 | der.writeBuffer(ver, asn1.Ber.Integer);
|
---|
340 |
|
---|
341 | der.writeBuffer(key.part.d.data, asn1.Ber.OctetString);
|
---|
342 |
|
---|
343 | der.startSequence(0xa0);
|
---|
344 | var curve = key.part.curve.data.toString();
|
---|
345 | var curveOid = algs.curves[curve].pkcs8oid;
|
---|
346 | assert.string(curveOid, 'a known ECDSA named curve');
|
---|
347 | der.writeOID(curveOid);
|
---|
348 | der.endSequence();
|
---|
349 |
|
---|
350 | der.startSequence(0xa1);
|
---|
351 | var Q = utils.ecNormalize(key.part.Q.data, true);
|
---|
352 | der.writeBuffer(Q, asn1.Ber.BitString);
|
---|
353 | der.endSequence();
|
---|
354 | }
|
---|
355 |
|
---|
356 | function writePkcs1EdDSAPrivate(der, key) {
|
---|
357 | var ver = Buffer.from([1]);
|
---|
358 | der.writeBuffer(ver, asn1.Ber.Integer);
|
---|
359 |
|
---|
360 | der.writeBuffer(key.part.k.data, asn1.Ber.OctetString);
|
---|
361 |
|
---|
362 | der.startSequence(0xa0);
|
---|
363 | der.writeOID('1.3.101.112');
|
---|
364 | der.endSequence();
|
---|
365 |
|
---|
366 | der.startSequence(0xa1);
|
---|
367 | utils.writeBitString(der, key.part.A.data);
|
---|
368 | der.endSequence();
|
---|
369 | }
|
---|
370 |
|
---|
371 | function writePkcs1EdDSAPublic(der, key) {
|
---|
372 | throw (new Error('Public keys are not supported for EdDSA PKCS#1'));
|
---|
373 | }
|
---|