pkcs8.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  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. default:
  57. throw (new Error('Unknown key type OID ' + oid));
  58. }
  59. }
  60. function readPkcs8RSAPublic(der) {
  61. // bit string sequence
  62. der.readSequence(asn1.Ber.BitString);
  63. der.readByte();
  64. der.readSequence();
  65. // modulus
  66. var n = readMPInt(der, 'modulus');
  67. var e = readMPInt(der, 'exponent');
  68. // now, make the key
  69. var key = {
  70. type: 'rsa',
  71. source: der.originalInput,
  72. parts: [
  73. { name: 'e', data: e },
  74. { name: 'n', data: n }
  75. ]
  76. };
  77. return (new Key(key));
  78. }
  79. function readPkcs8RSAPrivate(der) {
  80. der.readSequence(asn1.Ber.OctetString);
  81. der.readSequence();
  82. var ver = readMPInt(der, 'version');
  83. assert.equal(ver[0], 0x0, 'unknown RSA private key version');
  84. // modulus then public exponent
  85. var n = readMPInt(der, 'modulus');
  86. var e = readMPInt(der, 'public exponent');
  87. var d = readMPInt(der, 'private exponent');
  88. var p = readMPInt(der, 'prime1');
  89. var q = readMPInt(der, 'prime2');
  90. var dmodp = readMPInt(der, 'exponent1');
  91. var dmodq = readMPInt(der, 'exponent2');
  92. var iqmp = readMPInt(der, 'iqmp');
  93. // now, make the key
  94. var key = {
  95. type: 'rsa',
  96. parts: [
  97. { name: 'n', data: n },
  98. { name: 'e', data: e },
  99. { name: 'd', data: d },
  100. { name: 'iqmp', data: iqmp },
  101. { name: 'p', data: p },
  102. { name: 'q', data: q },
  103. { name: 'dmodp', data: dmodp },
  104. { name: 'dmodq', data: dmodq }
  105. ]
  106. };
  107. return (new PrivateKey(key));
  108. }
  109. function readPkcs8DSAPublic(der) {
  110. der.readSequence();
  111. var p = readMPInt(der, 'p');
  112. var q = readMPInt(der, 'q');
  113. var g = readMPInt(der, 'g');
  114. // bit string sequence
  115. der.readSequence(asn1.Ber.BitString);
  116. der.readByte();
  117. var y = readMPInt(der, 'y');
  118. // now, make the key
  119. var key = {
  120. type: 'dsa',
  121. parts: [
  122. { name: 'p', data: p },
  123. { name: 'q', data: q },
  124. { name: 'g', data: g },
  125. { name: 'y', data: y }
  126. ]
  127. };
  128. return (new Key(key));
  129. }
  130. function readPkcs8DSAPrivate(der) {
  131. der.readSequence();
  132. var p = readMPInt(der, 'p');
  133. var q = readMPInt(der, 'q');
  134. var g = readMPInt(der, 'g');
  135. der.readSequence(asn1.Ber.OctetString);
  136. var x = readMPInt(der, 'x');
  137. /* The pkcs#8 format does not include the public key */
  138. var y = utils.calculateDSAPublic(g, p, x);
  139. var key = {
  140. type: 'dsa',
  141. parts: [
  142. { name: 'p', data: p },
  143. { name: 'q', data: q },
  144. { name: 'g', data: g },
  145. { name: 'y', data: y },
  146. { name: 'x', data: x }
  147. ]
  148. };
  149. return (new PrivateKey(key));
  150. }
  151. function readECDSACurve(der) {
  152. var curveName, curveNames;
  153. var j, c, cd;
  154. if (der.peek() === asn1.Ber.OID) {
  155. var oid = der.readOID();
  156. curveNames = Object.keys(algs.curves);
  157. for (j = 0; j < curveNames.length; ++j) {
  158. c = curveNames[j];
  159. cd = algs.curves[c];
  160. if (cd.pkcs8oid === oid) {
  161. curveName = c;
  162. break;
  163. }
  164. }
  165. } else {
  166. // ECParameters sequence
  167. der.readSequence();
  168. var version = der.readString(asn1.Ber.Integer, true);
  169. assert.strictEqual(version[0], 1, 'ECDSA key not version 1');
  170. var curve = {};
  171. // FieldID sequence
  172. der.readSequence();
  173. var fieldTypeOid = der.readOID();
  174. assert.strictEqual(fieldTypeOid, '1.2.840.10045.1.1',
  175. 'ECDSA key is not from a prime-field');
  176. var p = curve.p = utils.mpNormalize(
  177. der.readString(asn1.Ber.Integer, true));
  178. /*
  179. * p always starts with a 1 bit, so count the zeros to get its
  180. * real size.
  181. */
  182. curve.size = p.length * 8 - utils.countZeros(p);
  183. // Curve sequence
  184. der.readSequence();
  185. curve.a = utils.mpNormalize(
  186. der.readString(asn1.Ber.OctetString, true));
  187. curve.b = utils.mpNormalize(
  188. der.readString(asn1.Ber.OctetString, true));
  189. if (der.peek() === asn1.Ber.BitString)
  190. curve.s = der.readString(asn1.Ber.BitString, true);
  191. // Combined Gx and Gy
  192. curve.G = der.readString(asn1.Ber.OctetString, true);
  193. assert.strictEqual(curve.G[0], 0x4,
  194. 'uncompressed G is required');
  195. curve.n = utils.mpNormalize(
  196. der.readString(asn1.Ber.Integer, true));
  197. curve.h = utils.mpNormalize(
  198. der.readString(asn1.Ber.Integer, true));
  199. assert.strictEqual(curve.h[0], 0x1, 'a cofactor=1 curve is ' +
  200. 'required');
  201. curveNames = Object.keys(algs.curves);
  202. var ks = Object.keys(curve);
  203. for (j = 0; j < curveNames.length; ++j) {
  204. c = curveNames[j];
  205. cd = algs.curves[c];
  206. var equal = true;
  207. for (var i = 0; i < ks.length; ++i) {
  208. var k = ks[i];
  209. if (cd[k] === undefined)
  210. continue;
  211. if (typeof (cd[k]) === 'object' &&
  212. cd[k].equals !== undefined) {
  213. if (!cd[k].equals(curve[k])) {
  214. equal = false;
  215. break;
  216. }
  217. } else if (Buffer.isBuffer(cd[k])) {
  218. if (cd[k].toString('binary')
  219. !== curve[k].toString('binary')) {
  220. equal = false;
  221. break;
  222. }
  223. } else {
  224. if (cd[k] !== curve[k]) {
  225. equal = false;
  226. break;
  227. }
  228. }
  229. }
  230. if (equal) {
  231. curveName = c;
  232. break;
  233. }
  234. }
  235. }
  236. return (curveName);
  237. }
  238. function readPkcs8ECDSAPrivate(der) {
  239. var curveName = readECDSACurve(der);
  240. assert.string(curveName, 'a known elliptic curve');
  241. der.readSequence(asn1.Ber.OctetString);
  242. der.readSequence();
  243. var version = readMPInt(der, 'version');
  244. assert.equal(version[0], 1, 'unknown version of ECDSA key');
  245. var d = der.readString(asn1.Ber.OctetString, true);
  246. der.readSequence(0xa1);
  247. var Q = der.readString(asn1.Ber.BitString, true);
  248. Q = utils.ecNormalize(Q);
  249. var key = {
  250. type: 'ecdsa',
  251. parts: [
  252. { name: 'curve', data: new Buffer(curveName) },
  253. { name: 'Q', data: Q },
  254. { name: 'd', data: d }
  255. ]
  256. };
  257. return (new PrivateKey(key));
  258. }
  259. function readPkcs8ECDSAPublic(der) {
  260. var curveName = readECDSACurve(der);
  261. assert.string(curveName, 'a known elliptic curve');
  262. var Q = der.readString(asn1.Ber.BitString, true);
  263. Q = utils.ecNormalize(Q);
  264. var key = {
  265. type: 'ecdsa',
  266. parts: [
  267. { name: 'curve', data: new Buffer(curveName) },
  268. { name: 'Q', data: Q }
  269. ]
  270. };
  271. return (new Key(key));
  272. }
  273. function writePkcs8(der, key) {
  274. der.startSequence();
  275. if (PrivateKey.isPrivateKey(key)) {
  276. var sillyInt = new Buffer(1);
  277. sillyInt[0] = 0x0;
  278. der.writeBuffer(sillyInt, asn1.Ber.Integer);
  279. }
  280. der.startSequence();
  281. switch (key.type) {
  282. case 'rsa':
  283. der.writeOID('1.2.840.113549.1.1.1');
  284. if (PrivateKey.isPrivateKey(key))
  285. writePkcs8RSAPrivate(key, der);
  286. else
  287. writePkcs8RSAPublic(key, der);
  288. break;
  289. case 'dsa':
  290. der.writeOID('1.2.840.10040.4.1');
  291. if (PrivateKey.isPrivateKey(key))
  292. writePkcs8DSAPrivate(key, der);
  293. else
  294. writePkcs8DSAPublic(key, der);
  295. break;
  296. case 'ecdsa':
  297. der.writeOID('1.2.840.10045.2.1');
  298. if (PrivateKey.isPrivateKey(key))
  299. writePkcs8ECDSAPrivate(key, der);
  300. else
  301. writePkcs8ECDSAPublic(key, der);
  302. break;
  303. default:
  304. throw (new Error('Unsupported key type: ' + key.type));
  305. }
  306. der.endSequence();
  307. }
  308. function writePkcs8RSAPrivate(key, der) {
  309. der.writeNull();
  310. der.endSequence();
  311. der.startSequence(asn1.Ber.OctetString);
  312. der.startSequence();
  313. var version = new Buffer(1);
  314. version[0] = 0;
  315. der.writeBuffer(version, asn1.Ber.Integer);
  316. der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
  317. der.writeBuffer(key.part.e.data, asn1.Ber.Integer);
  318. der.writeBuffer(key.part.d.data, asn1.Ber.Integer);
  319. der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
  320. der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
  321. if (!key.part.dmodp || !key.part.dmodq)
  322. utils.addRSAMissing(key);
  323. der.writeBuffer(key.part.dmodp.data, asn1.Ber.Integer);
  324. der.writeBuffer(key.part.dmodq.data, asn1.Ber.Integer);
  325. der.writeBuffer(key.part.iqmp.data, asn1.Ber.Integer);
  326. der.endSequence();
  327. der.endSequence();
  328. }
  329. function writePkcs8RSAPublic(key, der) {
  330. der.writeNull();
  331. der.endSequence();
  332. der.startSequence(asn1.Ber.BitString);
  333. der.writeByte(0x00);
  334. der.startSequence();
  335. der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
  336. der.writeBuffer(key.part.e.data, asn1.Ber.Integer);
  337. der.endSequence();
  338. der.endSequence();
  339. }
  340. function writePkcs8DSAPrivate(key, der) {
  341. der.startSequence();
  342. der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
  343. der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
  344. der.writeBuffer(key.part.g.data, asn1.Ber.Integer);
  345. der.endSequence();
  346. der.endSequence();
  347. der.startSequence(asn1.Ber.OctetString);
  348. der.writeBuffer(key.part.x.data, asn1.Ber.Integer);
  349. der.endSequence();
  350. }
  351. function writePkcs8DSAPublic(key, der) {
  352. der.startSequence();
  353. der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
  354. der.writeBuffer(key.part.q.data, asn1.Ber.Integer);
  355. der.writeBuffer(key.part.g.data, asn1.Ber.Integer);
  356. der.endSequence();
  357. der.endSequence();
  358. der.startSequence(asn1.Ber.BitString);
  359. der.writeByte(0x00);
  360. der.writeBuffer(key.part.y.data, asn1.Ber.Integer);
  361. der.endSequence();
  362. }
  363. function writeECDSACurve(key, der) {
  364. var curve = algs.curves[key.curve];
  365. if (curve.pkcs8oid) {
  366. /* This one has a name in pkcs#8, so just write the oid */
  367. der.writeOID(curve.pkcs8oid);
  368. } else {
  369. // ECParameters sequence
  370. der.startSequence();
  371. var version = new Buffer(1);
  372. version.writeUInt8(1, 0);
  373. der.writeBuffer(version, asn1.Ber.Integer);
  374. // FieldID sequence
  375. der.startSequence();
  376. der.writeOID('1.2.840.10045.1.1'); // prime-field
  377. der.writeBuffer(curve.p, asn1.Ber.Integer);
  378. der.endSequence();
  379. // Curve sequence
  380. der.startSequence();
  381. var a = curve.p;
  382. if (a[0] === 0x0)
  383. a = a.slice(1);
  384. der.writeBuffer(a, asn1.Ber.OctetString);
  385. der.writeBuffer(curve.b, asn1.Ber.OctetString);
  386. der.writeBuffer(curve.s, asn1.Ber.BitString);
  387. der.endSequence();
  388. der.writeBuffer(curve.G, asn1.Ber.OctetString);
  389. der.writeBuffer(curve.n, asn1.Ber.Integer);
  390. var h = curve.h;
  391. if (!h) {
  392. h = new Buffer(1);
  393. h[0] = 1;
  394. }
  395. der.writeBuffer(h, asn1.Ber.Integer);
  396. // ECParameters
  397. der.endSequence();
  398. }
  399. }
  400. function writePkcs8ECDSAPublic(key, der) {
  401. writeECDSACurve(key, der);
  402. der.endSequence();
  403. var Q = utils.ecNormalize(key.part.Q.data, true);
  404. der.writeBuffer(Q, asn1.Ber.BitString);
  405. }
  406. function writePkcs8ECDSAPrivate(key, der) {
  407. writeECDSACurve(key, der);
  408. der.endSequence();
  409. der.startSequence(asn1.Ber.OctetString);
  410. der.startSequence();
  411. var version = new Buffer(1);
  412. version[0] = 1;
  413. der.writeBuffer(version, asn1.Ber.Integer);
  414. der.writeBuffer(key.part.d.data, asn1.Ber.OctetString);
  415. der.startSequence(0xa1);
  416. var Q = utils.ecNormalize(key.part.Q.data, true);
  417. der.writeBuffer(Q, asn1.Ber.BitString);
  418. der.endSequence();
  419. der.endSequence();
  420. der.endSequence();
  421. }