• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015 Joyent, Inc.
2
3module.exports = {
4	read: read,
5	readPkcs1: readPkcs1,
6	write: write,
7	writePkcs1: writePkcs1
8};
9
10var assert = require('assert-plus');
11var asn1 = require('asn1');
12var Buffer = require('safer-buffer').Buffer;
13var algs = require('../algs');
14var utils = require('../utils');
15
16var Key = require('../key');
17var PrivateKey = require('../private-key');
18var pem = require('./pem');
19
20var pkcs8 = require('./pkcs8');
21var readECDSACurve = pkcs8.readECDSACurve;
22
23function read(buf, options) {
24	return (pem.read(buf, options, 'pkcs1'));
25}
26
27function write(key, options) {
28	return (pem.write(key, options, 'pkcs1'));
29}
30
31/* Helper to read in a single mpint */
32function 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
38function 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
69function 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
86function 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
118function 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
143function 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
168function 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
187function 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
221function 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
248function 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
283function 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
288function 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
304function 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
315function 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
322function 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
337function 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
356function 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
371function writePkcs1EdDSAPublic(der, key) {
372	throw (new Error('Public keys are not supported for EdDSA PKCS#1'));
373}
374