twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

pkcs8.js (14539B)


      1 // Copyright 2018 Joyent, Inc.
      2 
      3 module.exports = {
      4 	read: read,
      5 	readPkcs8: readPkcs8,
      6 	write: write,
      7 	writePkcs8: writePkcs8,
      8 	pkcs8ToBuffer: pkcs8ToBuffer,
      9 
     10 	readECDSACurve: readECDSACurve,
     11 	writeECDSACurve: writeECDSACurve
     12 };
     13 
     14 var assert = require('assert-plus');
     15 var asn1 = require('asn1');
     16 var Buffer = require('safer-buffer').Buffer;
     17 var algs = require('../algs');
     18 var utils = require('../utils');
     19 var Key = require('../key');
     20 var PrivateKey = require('../private-key');
     21 var pem = require('./pem');
     22 
     23 function read(buf, options) {
     24 	return (pem.read(buf, options, 'pkcs8'));
     25 }
     26 
     27 function write(key, options) {
     28 	return (pem.write(key, options, 'pkcs8'));
     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 readPkcs8(alg, type, der) {
     39 	/* Private keys in pkcs#8 format have a weird extra int */
     40 	if (der.peek() === asn1.Ber.Integer) {
     41 		assert.strictEqual(type, 'private',
     42 		    'unexpected Integer at start of public key');
     43 		der.readString(asn1.Ber.Integer, true);
     44 	}
     45 
     46 	der.readSequence();
     47 	var next = der.offset + der.length;
     48 
     49 	var oid = der.readOID();
     50 	switch (oid) {
     51 	case '1.2.840.113549.1.1.1':
     52 		der._offset = next;
     53 		if (type === 'public')
     54 			return (readPkcs8RSAPublic(der));
     55 		else
     56 			return (readPkcs8RSAPrivate(der));
     57 	case '1.2.840.10040.4.1':
     58 		if (type === 'public')
     59 			return (readPkcs8DSAPublic(der));
     60 		else
     61 			return (readPkcs8DSAPrivate(der));
     62 	case '1.2.840.10045.2.1':
     63 		if (type === 'public')
     64 			return (readPkcs8ECDSAPublic(der));
     65 		else
     66 			return (readPkcs8ECDSAPrivate(der));
     67 	case '1.3.101.112':
     68 		if (type === 'public') {
     69 			return (readPkcs8EdDSAPublic(der));
     70 		} else {
     71 			return (readPkcs8EdDSAPrivate(der));
     72 		}
     73 	case '1.3.101.110':
     74 		if (type === 'public') {
     75 			return (readPkcs8X25519Public(der));
     76 		} else {
     77 			return (readPkcs8X25519Private(der));
     78 		}
     79 	default:
     80 		throw (new Error('Unknown key type OID ' + oid));
     81 	}
     82 }
     83 
     84 function readPkcs8RSAPublic(der) {
     85 	// bit string sequence
     86 	der.readSequence(asn1.Ber.BitString);
     87 	der.readByte();
     88 	der.readSequence();
     89 
     90 	// modulus
     91 	var n = readMPInt(der, 'modulus');
     92 	var e = readMPInt(der, 'exponent');
     93 
     94 	// now, make the key
     95 	var key = {
     96 		type: 'rsa',
     97 		source: der.originalInput,
     98 		parts: [
     99 			{ name: 'e', data: e },
    100 			{ name: 'n', data: n }
    101 		]
    102 	};
    103 
    104 	return (new Key(key));
    105 }
    106 
    107 function readPkcs8RSAPrivate(der) {
    108 	der.readSequence(asn1.Ber.OctetString);
    109 	der.readSequence();
    110 
    111 	var ver = readMPInt(der, 'version');
    112 	assert.equal(ver[0], 0x0, 'unknown RSA private key version');
    113 
    114 	// modulus then public exponent
    115 	var n = readMPInt(der, 'modulus');
    116 	var e = readMPInt(der, 'public exponent');
    117 	var d = readMPInt(der, 'private exponent');
    118 	var p = readMPInt(der, 'prime1');
    119 	var q = readMPInt(der, 'prime2');
    120 	var dmodp = readMPInt(der, 'exponent1');
    121 	var dmodq = readMPInt(der, 'exponent2');
    122 	var iqmp = readMPInt(der, 'iqmp');
    123 
    124 	// now, make the key
    125 	var key = {
    126 		type: 'rsa',
    127 		parts: [
    128 			{ name: 'n', data: n },
    129 			{ name: 'e', data: e },
    130 			{ name: 'd', data: d },
    131 			{ name: 'iqmp', data: iqmp },
    132 			{ name: 'p', data: p },
    133 			{ name: 'q', data: q },
    134 			{ name: 'dmodp', data: dmodp },
    135 			{ name: 'dmodq', data: dmodq }
    136 		]
    137 	};
    138 
    139 	return (new PrivateKey(key));
    140 }
    141 
    142 function readPkcs8DSAPublic(der) {
    143 	der.readSequence();
    144 
    145 	var p = readMPInt(der, 'p');
    146 	var q = readMPInt(der, 'q');
    147 	var g = readMPInt(der, 'g');
    148 
    149 	// bit string sequence
    150 	der.readSequence(asn1.Ber.BitString);
    151 	der.readByte();
    152 
    153 	var y = readMPInt(der, 'y');
    154 
    155 	// now, make the key
    156 	var key = {
    157 		type: 'dsa',
    158 		parts: [
    159 			{ name: 'p', data: p },
    160 			{ name: 'q', data: q },
    161 			{ name: 'g', data: g },
    162 			{ name: 'y', data: y }
    163 		]
    164 	};
    165 
    166 	return (new Key(key));
    167 }
    168 
    169 function readPkcs8DSAPrivate(der) {
    170 	der.readSequence();
    171 
    172 	var p = readMPInt(der, 'p');
    173 	var q = readMPInt(der, 'q');
    174 	var g = readMPInt(der, 'g');
    175 
    176 	der.readSequence(asn1.Ber.OctetString);
    177 	var x = readMPInt(der, 'x');
    178 
    179 	/* The pkcs#8 format does not include the public key */
    180 	var y = utils.calculateDSAPublic(g, p, x);
    181 
    182 	var key = {
    183 		type: 'dsa',
    184 		parts: [
    185 			{ name: 'p', data: p },
    186 			{ name: 'q', data: q },
    187 			{ name: 'g', data: g },
    188 			{ name: 'y', data: y },
    189 			{ name: 'x', data: x }
    190 		]
    191 	};
    192 
    193 	return (new PrivateKey(key));
    194 }
    195 
    196 function readECDSACurve(der) {
    197 	var curveName, curveNames;
    198 	var j, c, cd;
    199 
    200 	if (der.peek() === asn1.Ber.OID) {
    201 		var oid = der.readOID();
    202 
    203 		curveNames = Object.keys(algs.curves);
    204 		for (j = 0; j < curveNames.length; ++j) {
    205 			c = curveNames[j];
    206 			cd = algs.curves[c];
    207 			if (cd.pkcs8oid === oid) {
    208 				curveName = c;
    209 				break;
    210 			}
    211 		}
    212 
    213 	} else {
    214 		// ECParameters sequence
    215 		der.readSequence();
    216 		var version = der.readString(asn1.Ber.Integer, true);
    217 		assert.strictEqual(version[0], 1, 'ECDSA key not version 1');
    218 
    219 		var curve = {};
    220 
    221 		// FieldID sequence
    222 		der.readSequence();
    223 		var fieldTypeOid = der.readOID();
    224 		assert.strictEqual(fieldTypeOid, '1.2.840.10045.1.1',
    225 		    'ECDSA key is not from a prime-field');
    226 		var p = curve.p = utils.mpNormalize(
    227 		    der.readString(asn1.Ber.Integer, true));
    228 		/*
    229 		 * p always starts with a 1 bit, so count the zeros to get its
    230 		 * real size.
    231 		 */
    232 		curve.size = p.length * 8 - utils.countZeros(p);
    233 
    234 		// Curve sequence
    235 		der.readSequence();
    236 		curve.a = utils.mpNormalize(
    237 		    der.readString(asn1.Ber.OctetString, true));
    238 		curve.b = utils.mpNormalize(
    239 		    der.readString(asn1.Ber.OctetString, true));
    240 		if (der.peek() === asn1.Ber.BitString)
    241 			curve.s = der.readString(asn1.Ber.BitString, true);
    242 
    243 		// Combined Gx and Gy
    244 		curve.G = der.readString(asn1.Ber.OctetString, true);
    245 		assert.strictEqual(curve.G[0], 0x4,
    246 		    'uncompressed G is required');
    247 
    248 		curve.n = utils.mpNormalize(
    249 		    der.readString(asn1.Ber.Integer, true));
    250 		curve.h = utils.mpNormalize(
    251 		    der.readString(asn1.Ber.Integer, true));
    252 		assert.strictEqual(curve.h[0], 0x1, 'a cofactor=1 curve is ' +
    253 		    'required');
    254 
    255 		curveNames = Object.keys(algs.curves);
    256 		var ks = Object.keys(curve);
    257 		for (j = 0; j < curveNames.length; ++j) {
    258 			c = curveNames[j];
    259 			cd = algs.curves[c];
    260 			var equal = true;
    261 			for (var i = 0; i < ks.length; ++i) {
    262 				var k = ks[i];
    263 				if (cd[k] === undefined)
    264 					continue;
    265 				if (typeof (cd[k]) === 'object' &&
    266 				    cd[k].equals !== undefined) {
    267 					if (!cd[k].equals(curve[k])) {
    268 						equal = false;
    269 						break;
    270 					}
    271 				} else if (Buffer.isBuffer(cd[k])) {
    272 					if (cd[k].toString('binary')
    273 					    !== curve[k].toString('binary')) {
    274 						equal = false;
    275 						break;
    276 					}
    277 				} else {
    278 					if (cd[k] !== curve[k]) {
    279 						equal = false;
    280 						break;
    281 					}
    282 				}
    283 			}
    284 			if (equal) {
    285 				curveName = c;
    286 				break;
    287 			}
    288 		}
    289 	}
    290 	return (curveName);
    291 }
    292 
    293 function readPkcs8ECDSAPrivate(der) {
    294 	var curveName = readECDSACurve(der);
    295 	assert.string(curveName, 'a known elliptic curve');
    296 
    297 	der.readSequence(asn1.Ber.OctetString);
    298 	der.readSequence();
    299 
    300 	var version = readMPInt(der, 'version');
    301 	assert.equal(version[0], 1, 'unknown version of ECDSA key');
    302 
    303 	var d = der.readString(asn1.Ber.OctetString, true);
    304 	var Q;
    305 
    306 	if (der.peek() == 0xa0) {
    307 		der.readSequence(0xa0);
    308 		der._offset += der.length;
    309 	}
    310 	if (der.peek() == 0xa1) {
    311 		der.readSequence(0xa1);
    312 		Q = der.readString(asn1.Ber.BitString, true);
    313 		Q = utils.ecNormalize(Q);
    314 	}
    315 
    316 	if (Q === undefined) {
    317 		var pub = utils.publicFromPrivateECDSA(curveName, d);
    318 		Q = pub.part.Q.data;
    319 	}
    320 
    321 	var key = {
    322 		type: 'ecdsa',
    323 		parts: [
    324 			{ name: 'curve', data: Buffer.from(curveName) },
    325 			{ name: 'Q', data: Q },
    326 			{ name: 'd', data: d }
    327 		]
    328 	};
    329 
    330 	return (new PrivateKey(key));
    331 }
    332 
    333 function readPkcs8ECDSAPublic(der) {
    334 	var curveName = readECDSACurve(der);
    335 	assert.string(curveName, 'a known elliptic curve');
    336 
    337 	var Q = der.readString(asn1.Ber.BitString, true);
    338 	Q = utils.ecNormalize(Q);
    339 
    340 	var key = {
    341 		type: 'ecdsa',
    342 		parts: [
    343 			{ name: 'curve', data: Buffer.from(curveName) },
    344 			{ name: 'Q', data: Q }
    345 		]
    346 	};
    347 
    348 	return (new Key(key));
    349 }
    350 
    351 function readPkcs8EdDSAPublic(der) {
    352 	if (der.peek() === 0x00)
    353 		der.readByte();
    354 
    355 	var A = utils.readBitString(der);
    356 
    357 	var key = {
    358 		type: 'ed25519',
    359 		parts: [
    360 			{ name: 'A', data: utils.zeroPadToLength(A, 32) }
    361 		]
    362 	};
    363 
    364 	return (new Key(key));
    365 }
    366 
    367 function readPkcs8X25519Public(der) {
    368 	var A = utils.readBitString(der);
    369 
    370 	var key = {
    371 		type: 'curve25519',
    372 		parts: [
    373 			{ name: 'A', data: utils.zeroPadToLength(A, 32) }
    374 		]
    375 	};
    376 
    377 	return (new Key(key));
    378 }
    379 
    380 function readPkcs8EdDSAPrivate(der) {
    381 	if (der.peek() === 0x00)
    382 		der.readByte();
    383 
    384 	der.readSequence(asn1.Ber.OctetString);
    385 	var k = der.readString(asn1.Ber.OctetString, true);
    386 	k = utils.zeroPadToLength(k, 32);
    387 
    388 	var A;
    389 	if (der.peek() === asn1.Ber.BitString) {
    390 		A = utils.readBitString(der);
    391 		A = utils.zeroPadToLength(A, 32);
    392 	} else {
    393 		A = utils.calculateED25519Public(k);
    394 	}
    395 
    396 	var key = {
    397 		type: 'ed25519',
    398 		parts: [
    399 			{ name: 'A', data: utils.zeroPadToLength(A, 32) },
    400 			{ name: 'k', data: utils.zeroPadToLength(k, 32) }
    401 		]
    402 	};
    403 
    404 	return (new PrivateKey(key));
    405 }
    406 
    407 function readPkcs8X25519Private(der) {
    408 	if (der.peek() === 0x00)
    409 		der.readByte();
    410 
    411 	der.readSequence(asn1.Ber.OctetString);
    412 	var k = der.readString(asn1.Ber.OctetString, true);
    413 	k = utils.zeroPadToLength(k, 32);
    414 
    415 	var A = utils.calculateX25519Public(k);
    416 
    417 	var key = {
    418 		type: 'curve25519',
    419 		parts: [
    420 			{ name: 'A', data: utils.zeroPadToLength(A, 32) },
    421 			{ name: 'k', data: utils.zeroPadToLength(k, 32) }
    422 		]
    423 	};
    424 
    425 	return (new PrivateKey(key));
    426 }
    427 
    428 function pkcs8ToBuffer(key) {
    429 	var der = new asn1.BerWriter();
    430 	writePkcs8(der, key);
    431 	return (der.buffer);
    432 }
    433 
    434 function writePkcs8(der, key) {
    435 	der.startSequence();
    436 
    437 	if (PrivateKey.isPrivateKey(key)) {
    438 		var sillyInt = Buffer.from([0]);
    439 		der.writeBuffer(sillyInt, asn1.Ber.Integer);
    440 	}
    441 
    442 	der.startSequence();
    443 	switch (key.type) {
    444 	case 'rsa':
    445 		der.writeOID('1.2.840.113549.1.1.1');
    446 		if (PrivateKey.isPrivateKey(key))
    447 			writePkcs8RSAPrivate(key, der);
    448 		else
    449 			writePkcs8RSAPublic(key, der);
    450 		break;
    451 	case 'dsa':
    452 		der.writeOID('1.2.840.10040.4.1');
    453 		if (PrivateKey.isPrivateKey(key))
    454 			writePkcs8DSAPrivate(key, der);
    455 		else
    456 			writePkcs8DSAPublic(key, der);
    457 		break;
    458 	case 'ecdsa':
    459 		der.writeOID('1.2.840.10045.2.1');
    460 		if (PrivateKey.isPrivateKey(key))
    461 			writePkcs8ECDSAPrivate(key, der);
    462 		else
    463 			writePkcs8ECDSAPublic(key, der);
    464 		break;
    465 	case 'ed25519':
    466 		der.writeOID('1.3.101.112');
    467 		if (PrivateKey.isPrivateKey(key))
    468 			throw (new Error('Ed25519 private keys in pkcs8 ' +
    469 			    'format are not supported'));
    470 		writePkcs8EdDSAPublic(key, der);
    471 		break;
    472 	default:
    473 		throw (new Error('Unsupported key type: ' + key.type));
    474 	}
    475 
    476 	der.endSequence();
    477 }
    478 
    479 function writePkcs8RSAPrivate(key, der) {
    480 	der.writeNull();
    481 	der.endSequence();
    482 
    483 	der.startSequence(asn1.Ber.OctetString);
    484 	der.startSequence();
    485 
    486 	var version = Buffer.from([0]);
    487 	der.writeBuffer(version, asn1.Ber.Integer);
    488 
    489 	der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
    490 	der.writeBuffer(key.part.e.data, asn1.Ber.Integer);
    491 	der.writeBuffer(key.part.d.data, asn1.Ber.Integer);
    492 	der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
    493 	der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
    494 	if (!key.part.dmodp || !key.part.dmodq)
    495 		utils.addRSAMissing(key);
    496 	der.writeBuffer(key.part.dmodp.data, asn1.Ber.Integer);
    497 	der.writeBuffer(key.part.dmodq.data, asn1.Ber.Integer);
    498 	der.writeBuffer(key.part.iqmp.data, asn1.Ber.Integer);
    499 
    500 	der.endSequence();
    501 	der.endSequence();
    502 }
    503 
    504 function writePkcs8RSAPublic(key, der) {
    505 	der.writeNull();
    506 	der.endSequence();
    507 
    508 	der.startSequence(asn1.Ber.BitString);
    509 	der.writeByte(0x00);
    510 
    511 	der.startSequence();
    512 	der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
    513 	der.writeBuffer(key.part.e.data, asn1.Ber.Integer);
    514 	der.endSequence();
    515 
    516 	der.endSequence();
    517 }
    518 
    519 function writePkcs8DSAPrivate(key, der) {
    520 	der.startSequence();
    521 	der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
    522 	der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
    523 	der.writeBuffer(key.part.g.data, asn1.Ber.Integer);
    524 	der.endSequence();
    525 
    526 	der.endSequence();
    527 
    528 	der.startSequence(asn1.Ber.OctetString);
    529 	der.writeBuffer(key.part.x.data, asn1.Ber.Integer);
    530 	der.endSequence();
    531 }
    532 
    533 function writePkcs8DSAPublic(key, der) {
    534 	der.startSequence();
    535 	der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
    536 	der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
    537 	der.writeBuffer(key.part.g.data, asn1.Ber.Integer);
    538 	der.endSequence();
    539 	der.endSequence();
    540 
    541 	der.startSequence(asn1.Ber.BitString);
    542 	der.writeByte(0x00);
    543 	der.writeBuffer(key.part.y.data, asn1.Ber.Integer);
    544 	der.endSequence();
    545 }
    546 
    547 function writeECDSACurve(key, der) {
    548 	var curve = algs.curves[key.curve];
    549 	if (curve.pkcs8oid) {
    550 		/* This one has a name in pkcs#8, so just write the oid */
    551 		der.writeOID(curve.pkcs8oid);
    552 
    553 	} else {
    554 		// ECParameters sequence
    555 		der.startSequence();
    556 
    557 		var version = Buffer.from([1]);
    558 		der.writeBuffer(version, asn1.Ber.Integer);
    559 
    560 		// FieldID sequence
    561 		der.startSequence();
    562 		der.writeOID('1.2.840.10045.1.1'); // prime-field
    563 		der.writeBuffer(curve.p, asn1.Ber.Integer);
    564 		der.endSequence();
    565 
    566 		// Curve sequence
    567 		der.startSequence();
    568 		var a = curve.p;
    569 		if (a[0] === 0x0)
    570 			a = a.slice(1);
    571 		der.writeBuffer(a, asn1.Ber.OctetString);
    572 		der.writeBuffer(curve.b, asn1.Ber.OctetString);
    573 		der.writeBuffer(curve.s, asn1.Ber.BitString);
    574 		der.endSequence();
    575 
    576 		der.writeBuffer(curve.G, asn1.Ber.OctetString);
    577 		der.writeBuffer(curve.n, asn1.Ber.Integer);
    578 		var h = curve.h;
    579 		if (!h) {
    580 			h = Buffer.from([1]);
    581 		}
    582 		der.writeBuffer(h, asn1.Ber.Integer);
    583 
    584 		// ECParameters
    585 		der.endSequence();
    586 	}
    587 }
    588 
    589 function writePkcs8ECDSAPublic(key, der) {
    590 	writeECDSACurve(key, der);
    591 	der.endSequence();
    592 
    593 	var Q = utils.ecNormalize(key.part.Q.data, true);
    594 	der.writeBuffer(Q, asn1.Ber.BitString);
    595 }
    596 
    597 function writePkcs8ECDSAPrivate(key, der) {
    598 	writeECDSACurve(key, der);
    599 	der.endSequence();
    600 
    601 	der.startSequence(asn1.Ber.OctetString);
    602 	der.startSequence();
    603 
    604 	var version = Buffer.from([1]);
    605 	der.writeBuffer(version, asn1.Ber.Integer);
    606 
    607 	der.writeBuffer(key.part.d.data, asn1.Ber.OctetString);
    608 
    609 	der.startSequence(0xa1);
    610 	var Q = utils.ecNormalize(key.part.Q.data, true);
    611 	der.writeBuffer(Q, asn1.Ber.BitString);
    612 	der.endSequence();
    613 
    614 	der.endSequence();
    615 	der.endSequence();
    616 }
    617 
    618 function writePkcs8EdDSAPublic(key, der) {
    619 	der.endSequence();
    620 
    621 	utils.writeBitString(der, key.part.A.data);
    622 }
    623 
    624 function writePkcs8EdDSAPrivate(key, der) {
    625 	der.endSequence();
    626 
    627 	var k = utils.mpNormalize(key.part.k.data, true);
    628 	der.startSequence(asn1.Ber.OctetString);
    629 	der.writeBuffer(k, asn1.Ber.OctetString);
    630 	der.endSequence();
    631 }