pkcs8.js 14 KB

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