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