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 }