pkcs8.js 14 KB

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