x509.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. // **Github:** https://github.com/fidm/x509
  4. //
  5. // **License:** MIT
  6. const util_1 = require("util");
  7. const crypto_1 = require("crypto");
  8. const asn1_1 = require("@fidm/asn1");
  9. const common_1 = require("./common");
  10. const pki_1 = require("./pki");
  11. // short name OID mappings
  12. const shortNames = Object.create(null);
  13. shortNames.CN = common_1.getOID('commonName');
  14. shortNames.commonName = 'CN';
  15. shortNames.C = common_1.getOID('countryName');
  16. shortNames.countryName = 'C';
  17. shortNames.L = common_1.getOID('localityName');
  18. shortNames.localityName = 'L';
  19. shortNames.ST = common_1.getOID('stateOrProvinceName');
  20. shortNames.stateOrProvinceName = 'ST';
  21. shortNames.O = common_1.getOID('organizationName');
  22. shortNames.organizationName = 'O';
  23. shortNames.OU = common_1.getOID('organizationalUnitName');
  24. shortNames.organizationalUnitName = 'OU';
  25. shortNames.E = common_1.getOID('emailAddress');
  26. shortNames.emailAddress = 'E';
  27. function getShortName(name) {
  28. return shortNames[name] == null ? '' : shortNames[name];
  29. }
  30. // validator for an X.509v3 certificate
  31. const x509CertificateValidator = {
  32. name: 'Certificate',
  33. class: asn1_1.Class.UNIVERSAL,
  34. tag: asn1_1.Tag.SEQUENCE,
  35. value: [{
  36. name: 'Certificate.TBSCertificate',
  37. class: asn1_1.Class.UNIVERSAL,
  38. tag: asn1_1.Tag.SEQUENCE,
  39. capture: 'tbsCertificate',
  40. value: [{
  41. name: 'Certificate.TBSCertificate.version',
  42. class: asn1_1.Class.CONTEXT_SPECIFIC,
  43. tag: asn1_1.Tag.NONE,
  44. optional: true,
  45. value: [{
  46. name: 'Certificate.TBSCertificate.version.integer',
  47. class: asn1_1.Class.UNIVERSAL,
  48. tag: asn1_1.Tag.INTEGER,
  49. capture: 'certVersion',
  50. }],
  51. }, {
  52. name: 'Certificate.TBSCertificate.serialNumber',
  53. class: asn1_1.Class.UNIVERSAL,
  54. tag: asn1_1.Tag.INTEGER,
  55. capture: 'certSerialNumber',
  56. }, {
  57. name: 'Certificate.TBSCertificate.signature',
  58. class: asn1_1.Class.UNIVERSAL,
  59. tag: asn1_1.Tag.SEQUENCE,
  60. value: [{
  61. name: 'Certificate.TBSCertificate.signature.algorithm',
  62. class: asn1_1.Class.UNIVERSAL,
  63. tag: asn1_1.Tag.OID,
  64. capture: 'certinfoSignatureOID',
  65. }, {
  66. name: 'Certificate.TBSCertificate.signature.parameters',
  67. class: asn1_1.Class.UNIVERSAL,
  68. tag: asn1_1.Tag.OCTETSTRING,
  69. optional: true,
  70. capture: 'certinfoSignatureParams',
  71. }],
  72. }, {
  73. name: 'Certificate.TBSCertificate.issuer',
  74. class: asn1_1.Class.UNIVERSAL,
  75. tag: asn1_1.Tag.SEQUENCE,
  76. capture: 'certIssuer',
  77. }, {
  78. name: 'Certificate.TBSCertificate.validity',
  79. class: asn1_1.Class.UNIVERSAL,
  80. tag: asn1_1.Tag.SEQUENCE,
  81. value: [{
  82. name: 'Certificate.TBSCertificate.validity.notBefore',
  83. class: asn1_1.Class.UNIVERSAL,
  84. tag: [asn1_1.Tag.UTCTIME, asn1_1.Tag.GENERALIZEDTIME],
  85. capture: 'certValidityNotBefore',
  86. }, {
  87. name: 'Certificate.TBSCertificate.validity.notAfter',
  88. class: asn1_1.Class.UNIVERSAL,
  89. tag: [asn1_1.Tag.UTCTIME, asn1_1.Tag.GENERALIZEDTIME],
  90. capture: 'certValidityNotAfter',
  91. }],
  92. }, {
  93. // Name (subject) (RDNSequence)
  94. name: 'Certificate.TBSCertificate.subject',
  95. class: asn1_1.Class.UNIVERSAL,
  96. tag: asn1_1.Tag.SEQUENCE,
  97. capture: 'certSubject',
  98. },
  99. // SubjectPublicKeyInfo
  100. pki_1.publicKeyValidator,
  101. {
  102. // issuerUniqueID (optional)
  103. name: 'Certificate.TBSCertificate.issuerUniqueID',
  104. class: asn1_1.Class.CONTEXT_SPECIFIC,
  105. tag: asn1_1.Tag.BOOLEAN,
  106. optional: true,
  107. value: [{
  108. name: 'Certificate.TBSCertificate.issuerUniqueID.id',
  109. class: asn1_1.Class.UNIVERSAL,
  110. tag: asn1_1.Tag.BITSTRING,
  111. capture: 'certIssuerUniqueId',
  112. }],
  113. }, {
  114. // subjectUniqueID (optional)
  115. name: 'Certificate.TBSCertificate.subjectUniqueID',
  116. class: asn1_1.Class.CONTEXT_SPECIFIC,
  117. tag: asn1_1.Tag.INTEGER,
  118. optional: true,
  119. value: [{
  120. name: 'Certificate.TBSCertificate.subjectUniqueID.id',
  121. class: asn1_1.Class.UNIVERSAL,
  122. tag: asn1_1.Tag.BITSTRING,
  123. capture: 'certSubjectUniqueId',
  124. }],
  125. }, {
  126. // Extensions (optional)
  127. name: 'Certificate.TBSCertificate.extensions',
  128. class: asn1_1.Class.CONTEXT_SPECIFIC,
  129. tag: asn1_1.Tag.BITSTRING,
  130. capture: 'certExtensions',
  131. optional: true,
  132. }],
  133. }, {
  134. // AlgorithmIdentifier (signature algorithm)
  135. name: 'Certificate.signatureAlgorithm',
  136. class: asn1_1.Class.UNIVERSAL,
  137. tag: asn1_1.Tag.SEQUENCE,
  138. value: [{
  139. // algorithm
  140. name: 'Certificate.signatureAlgorithm.algorithm',
  141. class: asn1_1.Class.UNIVERSAL,
  142. tag: asn1_1.Tag.OID,
  143. capture: 'certSignatureOID',
  144. }, {
  145. name: 'Certificate.TBSCertificate.signature.parameters',
  146. class: asn1_1.Class.UNIVERSAL,
  147. tag: asn1_1.Tag.OCTETSTRING,
  148. optional: true,
  149. capture: 'certSignatureParams',
  150. }],
  151. }, {
  152. name: 'Certificate.signatureValue',
  153. class: asn1_1.Class.UNIVERSAL,
  154. tag: asn1_1.Tag.BITSTRING,
  155. capture: 'certSignature',
  156. }],
  157. };
  158. /**
  159. * DistinguishedName for X.509v3 certificate.
  160. */
  161. class DistinguishedName {
  162. constructor() {
  163. this.attributes = [];
  164. this.uniqueId = null;
  165. }
  166. get commonName() {
  167. return this.getFieldValue('commonName');
  168. }
  169. get organizationName() {
  170. return this.getFieldValue('organizationName');
  171. }
  172. get organizationalUnitName() {
  173. return this.getFieldValue('organizationalUnitName');
  174. }
  175. get countryName() {
  176. return this.getFieldValue('countryName');
  177. }
  178. get localityName() {
  179. return this.getFieldValue('localityName');
  180. }
  181. get serialName() {
  182. return this.getFieldValue('serialName');
  183. }
  184. getHash() {
  185. const hasher = crypto_1.createHash('sha1');
  186. for (const attr of this.attributes) {
  187. hasher.update(attr.oid);
  188. hasher.update(attr.value);
  189. }
  190. return hasher.digest();
  191. }
  192. getField(key) {
  193. for (const attr of this.attributes) {
  194. if (key === attr.oid || key === attr.name || key === attr.shortName) {
  195. return attr;
  196. }
  197. }
  198. return null;
  199. }
  200. addField(attr) {
  201. fillMissingFields([attr]);
  202. this.attributes.push(attr);
  203. }
  204. setAttrs(attrs) {
  205. // set new attributes, clear hash
  206. fillMissingFields(attrs);
  207. this.attributes = attrs;
  208. }
  209. toJSON() {
  210. const obj = {};
  211. for (const attr of this.attributes) {
  212. const key = attr.shortName;
  213. if (typeof key === 'string' && key !== '') {
  214. obj[key] = attr.value;
  215. }
  216. }
  217. obj.uniqueId = this.uniqueId;
  218. obj.attributes = this.attributes;
  219. return obj;
  220. }
  221. getFieldValue(key) {
  222. const val = this.getField(key);
  223. if (val != null) {
  224. return val.value;
  225. }
  226. return '';
  227. }
  228. }
  229. exports.DistinguishedName = DistinguishedName;
  230. /**
  231. * X.509v3 Certificate.
  232. */
  233. class Certificate {
  234. /**
  235. * Parse one or more X.509 certificates from PEM formatted buffer.
  236. * If there is no certificate, it will throw error.
  237. * @param data PEM formatted buffer
  238. */
  239. static fromPEMs(data) {
  240. const certs = [];
  241. const pems = asn1_1.PEM.parse(data);
  242. for (const pem of pems) {
  243. if (pem.type !== 'CERTIFICATE' &&
  244. pem.type !== 'X509 CERTIFICATE' &&
  245. pem.type !== 'TRUSTED CERTIFICATE') {
  246. throw new Error('Could not convert certificate from PEM: invalid type');
  247. }
  248. if (pem.procType.includes('ENCRYPTED')) {
  249. throw new Error('Could not convert certificate from PEM: PEM is encrypted.');
  250. }
  251. const obj = asn1_1.ASN1.fromDER(pem.body);
  252. certs.push(new Certificate(obj));
  253. }
  254. if (certs.length === 0) {
  255. throw new Error('No Certificate');
  256. }
  257. return certs;
  258. }
  259. /**
  260. * Parse an X.509 certificate from PEM formatted buffer.
  261. * @param data PEM formatted buffer
  262. */
  263. static fromPEM(data) {
  264. return Certificate.fromPEMs(data)[0];
  265. }
  266. /**
  267. * Creates an X.509 certificate from an ASN.1 object
  268. * @param obj an ASN.1 object
  269. */
  270. constructor(obj) {
  271. // validate certificate and capture data
  272. const captures = Object.create(null);
  273. const err = obj.validate(x509CertificateValidator, captures);
  274. if (err != null) {
  275. throw new Error('Cannot read X.509 certificate: ' + err.message);
  276. }
  277. this.raw = obj.DER;
  278. this.version = captures.certVersion == null ? 0 : (asn1_1.ASN1.parseIntegerNum(captures.certVersion.bytes) + 1);
  279. this.serialNumber = asn1_1.ASN1.parseIntegerStr(captures.certSerialNumber.bytes);
  280. this.signatureOID = asn1_1.ASN1.parseOID(captures.certSignatureOID.bytes);
  281. this.signatureAlgorithm = common_1.getOIDName(this.signatureOID);
  282. this.infoSignatureOID = asn1_1.ASN1.parseOID(captures.certinfoSignatureOID.bytes);
  283. this.signature = asn1_1.ASN1.parseBitString(captures.certSignature.bytes).buf;
  284. this.validFrom = asn1_1.ASN1.parseTime(captures.certValidityNotBefore.tag, captures.certValidityNotBefore.bytes);
  285. this.validTo = asn1_1.ASN1.parseTime(captures.certValidityNotAfter.tag, captures.certValidityNotAfter.bytes);
  286. this.issuer = new DistinguishedName();
  287. this.issuer.setAttrs(RDNAttributesAsArray(captures.certIssuer));
  288. if (captures.certIssuerUniqueId != null) {
  289. this.issuer.uniqueId = asn1_1.ASN1.parseBitString(captures.certIssuerUniqueId.bytes);
  290. }
  291. this.subject = new DistinguishedName();
  292. this.subject.setAttrs(RDNAttributesAsArray(captures.certSubject));
  293. if (captures.certSubjectUniqueId != null) {
  294. this.subject.uniqueId = asn1_1.ASN1.parseBitString(captures.certSubjectUniqueId.bytes);
  295. }
  296. this.extensions = [];
  297. this.subjectKeyIdentifier = '';
  298. this.authorityKeyIdentifier = '';
  299. this.ocspServer = '';
  300. this.issuingCertificateURL = '';
  301. this.isCA = false;
  302. this.maxPathLen = -1;
  303. this.basicConstraintsValid = false;
  304. this.keyUsage = 0;
  305. this.dnsNames = [];
  306. this.emailAddresses = [];
  307. this.ipAddresses = [];
  308. this.uris = [];
  309. if (captures.certExtensions != null) {
  310. this.extensions = certificateExtensionsFromAsn1(captures.certExtensions);
  311. for (const ext of this.extensions) {
  312. if (typeof ext.subjectKeyIdentifier === 'string') {
  313. this.subjectKeyIdentifier = ext.subjectKeyIdentifier;
  314. }
  315. if (typeof ext.authorityKeyIdentifier === 'string') {
  316. this.authorityKeyIdentifier = ext.authorityKeyIdentifier;
  317. }
  318. if (typeof ext.authorityInfoAccessOcsp === 'string') {
  319. this.ocspServer = ext.authorityInfoAccessOcsp;
  320. }
  321. if (typeof ext.authorityInfoAccessIssuers === 'string') {
  322. this.issuingCertificateURL = ext.authorityInfoAccessIssuers;
  323. }
  324. if (typeof ext.basicConstraintsValid === 'boolean') {
  325. this.isCA = ext.isCA;
  326. this.maxPathLen = ext.maxPathLen;
  327. this.basicConstraintsValid = ext.basicConstraintsValid;
  328. }
  329. if (typeof ext.keyUsage === 'number') {
  330. this.keyUsage = ext.keyUsage;
  331. }
  332. if (Array.isArray(ext.altNames)) {
  333. for (const item of ext.altNames) {
  334. if (item.dnsName != null) {
  335. this.dnsNames.push(item.dnsName);
  336. }
  337. if (item.email != null) {
  338. this.emailAddresses.push(item.email);
  339. }
  340. if (item.ip != null) {
  341. this.ipAddresses.push(item.ip);
  342. }
  343. if (item.uri != null) {
  344. this.uris.push(item.uri);
  345. }
  346. }
  347. }
  348. }
  349. }
  350. this.publicKey = new pki_1.PublicKey(captures.publicKeyInfo);
  351. this.publicKeyRaw = this.publicKey.toDER();
  352. this.tbsCertificate = captures.tbsCertificate;
  353. }
  354. /**
  355. * Gets an extension by its name or oid.
  356. * If extension exists and a key provided, it will return extension[key].
  357. * ```js
  358. * certificate.getExtension('keyUsage')
  359. * certificate.getExtension('2.5.29.15')
  360. * // => { oid: '2.5.29.15',
  361. * // critical: true,
  362. * // value: <Buffer 03 02 05 a0>,
  363. * // name: 'keyUsage',
  364. * // digitalSignature: true,
  365. * // nonRepudiation: false,
  366. * // keyEncipherment: true,
  367. * // dataEncipherment: false,
  368. * // keyAgreement: false,
  369. * // keyCertSign: false,
  370. * // cRLSign: false,
  371. * // encipherOnly: false,
  372. * // decipherOnly: false }
  373. * certificate.getExtension('keyUsage', 'keyCertSign') // => false
  374. * ```
  375. * @param name extension name or OID
  376. * @param key key in extension
  377. */
  378. getExtension(name, key = '') {
  379. for (const ext of this.extensions) {
  380. if (name === ext.oid || name === ext.name) {
  381. return key === '' ? ext : ext[key];
  382. }
  383. }
  384. return null;
  385. }
  386. /**
  387. * Returns null if a subject certificate is valid, or error if invalid.
  388. * Note that it does not check validity time, DNS name, ip or others.
  389. * @param child subject's Certificate
  390. */
  391. checkSignature(child) {
  392. // RFC 5280, 4.2.1.9:
  393. // "If the basic constraints extension is not present in a version 3
  394. // certificate, or the extension is present but the cA boolean is not
  395. // asserted, then the certified public key MUST NOT be used to verify
  396. // certificate signatures."
  397. // (not handler entrust broken SPKI, See http://www.entrust.net/knowledge-base/technote.cfm?tn=7869)
  398. if (this.version === 3 && !this.basicConstraintsValid || (this.basicConstraintsValid && !this.isCA)) {
  399. return new Error('The parent constraint violation error');
  400. }
  401. if (this.getExtension('keyUsage', 'keyCertSign') !== true) {
  402. return new Error('The parent constraint violation error');
  403. }
  404. if (!child.isIssuer(this)) {
  405. return new Error('The parent certificate did not issue the given child certificate');
  406. }
  407. const agl = getHashAgl(child.signatureOID);
  408. if (agl === '') {
  409. return new Error('Unknown child signature OID.');
  410. }
  411. const res = this.publicKey.verify(child.tbsCertificate.DER, child.signature, agl);
  412. if (res === false) {
  413. return new Error('Child signature not matched');
  414. }
  415. return null;
  416. }
  417. /**
  418. * Returns true if this certificate's issuer matches the passed
  419. * certificate's subject. Note that no signature check is performed.
  420. * @param parent issuer's Certificate
  421. */
  422. isIssuer(parent) {
  423. return this.issuer.getHash().equals(parent.subject.getHash());
  424. }
  425. /**
  426. * Verifies the subjectKeyIdentifier extension value for this certificate
  427. * against its public key.
  428. */
  429. verifySubjectKeyIdentifier() {
  430. const ski = this.publicKey.getFingerprint('sha1', 'PublicKey');
  431. return ski.toString('hex') === this.subjectKeyIdentifier;
  432. }
  433. /**
  434. * Return a friendly JSON object for debuging.
  435. */
  436. toJSON() {
  437. const obj = {};
  438. for (const key of Object.keys(this)) {
  439. obj[key] = toJSONify(this[key]);
  440. }
  441. delete obj.tbsCertificate;
  442. return obj;
  443. }
  444. [util_1.inspect.custom](_depth, options) {
  445. if (options.depth <= 2) {
  446. options.depth = 10;
  447. }
  448. return `<${this.constructor.name} ${util_1.inspect(this.toJSON(), options)}>`;
  449. }
  450. }
  451. exports.Certificate = Certificate;
  452. function certificateExtensionsFromAsn1(exts) {
  453. const res = [];
  454. for (const val of exts.mustCompound()) {
  455. for (const ext of val.mustCompound()) {
  456. res.push(certificateExtensionFromAsn1(ext));
  457. }
  458. }
  459. return res;
  460. }
  461. function certificateExtensionFromAsn1(ext) {
  462. // an extension has:
  463. // [0] extnID OBJECT IDENTIFIER
  464. // [1] critical BOOLEAN DEFAULT FALSE
  465. // [2] extnValue OCTET STRING
  466. const e = {};
  467. e.oid = asn1_1.ASN1.parseOID(ext.value[0].bytes);
  468. e.critical = false;
  469. if (ext.value[1].tag === asn1_1.Tag.BOOLEAN) {
  470. e.critical = asn1_1.ASN1.parseBool(ext.value[1].bytes);
  471. e.value = ext.value[2].bytes;
  472. }
  473. else {
  474. e.value = ext.value[1].bytes;
  475. }
  476. // if the oid is known, get its name
  477. e.name = common_1.getOIDName(e.oid);
  478. switch (e.name) {
  479. // handle key usage
  480. case 'keyUsage':
  481. decodeExtKeyUsage(e);
  482. break;
  483. case 'basicConstraints':
  484. decodeExtBasicConstraints(e);
  485. break;
  486. case 'extKeyUsage':
  487. decodeExtExtKeyUsage(e);
  488. break;
  489. case 'nsCertType':
  490. decodeExtNsCertType(e);
  491. break;
  492. case 'subjectAltName':
  493. decodeExtAltName(e);
  494. break;
  495. case 'issuerAltName':
  496. decodeExtAltName(e);
  497. break;
  498. case 'subjectKeyIdentifier':
  499. decodeExtSubjectKeyIdentifier(e);
  500. break;
  501. case 'authorityKeyIdentifier':
  502. decodeExtAuthorityKeyIdentifier(e);
  503. break;
  504. case 'authorityInfoAccess':
  505. decodeExtAuthorityInfoAccess(e);
  506. break;
  507. }
  508. return e;
  509. }
  510. function decodeExtKeyUsage(e) {
  511. // ev is a BITSTRING
  512. const ev = asn1_1.ASN1.parseBitString(asn1_1.ASN1.fromDER(e.value).bytes);
  513. let b2 = 0x00;
  514. let b3 = 0x00;
  515. e.keyUsage = 0;
  516. for (let i = 0; i < 9; i++) {
  517. if (ev.at(i) !== 0) {
  518. e.keyUsage |= 1 << i;
  519. }
  520. }
  521. if (ev.buf.length > 0) {
  522. b2 = ev.buf[0];
  523. b3 = ev.buf.length > 1 ? ev.buf[1] : 0;
  524. }
  525. // set flags
  526. e.digitalSignature = (b2 & 0x80) === 0x80;
  527. e.nonRepudiation = (b2 & 0x40) === 0x40;
  528. e.keyEncipherment = (b2 & 0x20) === 0x20;
  529. e.dataEncipherment = (b2 & 0x10) === 0x10;
  530. e.keyAgreement = (b2 & 0x08) === 0x08;
  531. e.keyCertSign = (b2 & 0x04) === 0x04;
  532. e.cRLSign = (b2 & 0x02) === 0x02;
  533. e.encipherOnly = (b2 & 0x01) === 0x01;
  534. e.decipherOnly = (b3 & 0x80) === 0x80;
  535. }
  536. function decodeExtBasicConstraints(e) {
  537. // handle basic constraints
  538. // get value as SEQUENCE
  539. const ev = asn1_1.ASN1.fromDER(e.value);
  540. const vals = ev.mustCompound();
  541. // get cA BOOLEAN flag (defaults to false)
  542. if (vals.length > 0 && vals[0].tag === asn1_1.Tag.BOOLEAN) {
  543. e.isCA = asn1_1.ASN1.parseBool(vals[0].bytes);
  544. }
  545. else {
  546. e.isCA = false;
  547. }
  548. // get path length constraint
  549. let value = null;
  550. if (vals.length > 0 && vals[0].tag === asn1_1.Tag.INTEGER) {
  551. value = vals[0].bytes;
  552. }
  553. else if (vals.length > 1) {
  554. value = vals[1].bytes;
  555. }
  556. if (value !== null) {
  557. e.maxPathLen = asn1_1.ASN1.parseInteger(value);
  558. }
  559. else {
  560. e.maxPathLen = -1;
  561. }
  562. e.basicConstraintsValid = true;
  563. }
  564. function decodeExtExtKeyUsage(e) {
  565. // handle extKeyUsage
  566. // value is a SEQUENCE of OIDs
  567. const ev = asn1_1.ASN1.fromDER(e.value);
  568. const vals = ev.mustCompound();
  569. for (const val of vals) {
  570. e[common_1.getOIDName(asn1_1.ASN1.parseOID(val.bytes))] = true;
  571. }
  572. }
  573. function decodeExtNsCertType(e) {
  574. // ev is a BITSTRING
  575. const ev = asn1_1.ASN1.parseBitString(asn1_1.ASN1.fromDER(e.value).bytes);
  576. let b2 = 0x00;
  577. if (ev.buf.length > 0) {
  578. b2 = ev.buf[0];
  579. }
  580. // set flags
  581. e.client = (b2 & 0x80) === 0x80;
  582. e.server = (b2 & 0x40) === 0x40;
  583. e.email = (b2 & 0x20) === 0x20;
  584. e.objsign = (b2 & 0x10) === 0x10;
  585. e.reserved = (b2 & 0x08) === 0x08;
  586. e.sslCA = (b2 & 0x04) === 0x04;
  587. e.emailCA = (b2 & 0x02) === 0x02;
  588. e.objCA = (b2 & 0x01) === 0x01;
  589. }
  590. function decodeExtAltName(e) {
  591. // handle subjectAltName/issuerAltName
  592. e.altNames = [];
  593. // ev is a SYNTAX SEQUENCE
  594. const ev = asn1_1.ASN1.fromDER(e.value);
  595. const vals = ev.mustCompound();
  596. for (const gn of vals) {
  597. // get GeneralName
  598. const item = {
  599. tag: gn.tag,
  600. value: gn.bytes,
  601. };
  602. e.altNames.push(item);
  603. switch (gn.tag) {
  604. // rfc822Name, emailAddresses
  605. case 1:
  606. item.email = gn.bytes.toString();
  607. break;
  608. // dNSName
  609. case 2:
  610. item.dnsName = gn.bytes.toString();
  611. break;
  612. // uniformResourceIdentifier (URI)
  613. case 6:
  614. item.uri = gn.bytes.toString();
  615. break;
  616. // IPAddress
  617. case 7:
  618. // convert to IPv4/IPv6 string representation
  619. item.ip = common_1.bytesToIP(gn.bytes);
  620. break;
  621. // registeredID
  622. case 8:
  623. item.oid = asn1_1.ASN1.parseOID(gn.bytes);
  624. break;
  625. default:
  626. // unsupported
  627. }
  628. }
  629. }
  630. const subjectKeyIdentifierValidator = {
  631. name: 'subjectKeyIdentifier',
  632. class: asn1_1.Class.UNIVERSAL,
  633. tag: asn1_1.Tag.OCTETSTRING,
  634. capture: 'subjectKeyIdentifier',
  635. };
  636. function decodeExtSubjectKeyIdentifier(e) {
  637. const captures = asn1_1.ASN1.parseDERWithTemplate(e.value, subjectKeyIdentifierValidator);
  638. e.subjectKeyIdentifier = captures.subjectKeyIdentifier.bytes.toString('hex');
  639. }
  640. const authorityKeyIdentifierValidator = {
  641. name: 'authorityKeyIdentifier',
  642. class: asn1_1.Class.UNIVERSAL,
  643. tag: asn1_1.Tag.SEQUENCE,
  644. value: [{
  645. name: 'authorityKeyIdentifier.value',
  646. class: asn1_1.Class.CONTEXT_SPECIFIC,
  647. tag: asn1_1.Tag.NONE,
  648. capture: 'authorityKeyIdentifier',
  649. }],
  650. };
  651. function decodeExtAuthorityKeyIdentifier(e) {
  652. const captures = asn1_1.ASN1.parseDERWithTemplate(e.value, authorityKeyIdentifierValidator);
  653. e.authorityKeyIdentifier = captures.authorityKeyIdentifier.bytes.toString('hex');
  654. }
  655. const authorityInfoAccessValidator = {
  656. name: 'authorityInfoAccess',
  657. class: asn1_1.Class.UNIVERSAL,
  658. tag: asn1_1.Tag.SEQUENCE,
  659. value: [{
  660. name: 'authorityInfoAccess.authorityInfoAccessOcsp',
  661. class: asn1_1.Class.UNIVERSAL,
  662. tag: asn1_1.Tag.SEQUENCE,
  663. optional: true,
  664. value: [{
  665. name: 'authorityInfoAccess.authorityInfoAccessOcsp.oid',
  666. class: asn1_1.Class.UNIVERSAL,
  667. tag: asn1_1.Tag.OID,
  668. }, {
  669. name: 'authorityInfoAccess.authorityInfoAccessOcsp.value',
  670. class: asn1_1.Class.CONTEXT_SPECIFIC,
  671. tag: asn1_1.Tag.OID,
  672. capture: 'authorityInfoAccessOcsp',
  673. }],
  674. }, {
  675. name: 'authorityInfoAccess.authorityInfoAccessIssuers',
  676. class: asn1_1.Class.UNIVERSAL,
  677. tag: asn1_1.Tag.SEQUENCE,
  678. optional: true,
  679. value: [{
  680. name: 'authorityInfoAccess.authorityInfoAccessIssuers.oid',
  681. class: asn1_1.Class.UNIVERSAL,
  682. tag: asn1_1.Tag.OID,
  683. }, {
  684. name: 'authorityInfoAccess.authorityInfoAccessIssuers.value',
  685. class: asn1_1.Class.CONTEXT_SPECIFIC,
  686. tag: asn1_1.Tag.OID,
  687. capture: 'authorityInfoAccessIssuers',
  688. }],
  689. }],
  690. };
  691. function decodeExtAuthorityInfoAccess(e) {
  692. const captures = asn1_1.ASN1.parseDERWithTemplate(e.value, authorityInfoAccessValidator);
  693. if (captures.authorityInfoAccessOcsp != null) {
  694. e.authorityInfoAccessOcsp = captures.authorityInfoAccessOcsp.bytes.toString();
  695. }
  696. if (captures.authorityInfoAccessIssuers != null) {
  697. e.authorityInfoAccessIssuers = captures.authorityInfoAccessIssuers.bytes.toString();
  698. }
  699. }
  700. // Fills in missing fields in attributes.
  701. function fillMissingFields(attrs) {
  702. for (const attr of attrs) {
  703. // populate missing name
  704. if (attr.name == null || attr.name === '') {
  705. if (attr.oid != null) {
  706. attr.name = common_1.getOIDName(attr.oid);
  707. }
  708. if (attr.name === '' && attr.shortName != null) {
  709. attr.name = common_1.getOIDName(shortNames[attr.shortName]);
  710. }
  711. }
  712. // populate missing type (OID)
  713. if (attr.oid == null || attr.oid === '') {
  714. if (attr.name !== '') {
  715. attr.oid = common_1.getOID(attr.name);
  716. }
  717. else {
  718. throw new Error('Attribute oid not specified.');
  719. }
  720. }
  721. // populate missing shortname
  722. if (attr.shortName == null || attr.shortName === '') {
  723. attr.shortName = shortNames[attr.name] == null ? '' : shortNames[attr.name];
  724. }
  725. if (attr.value == null) {
  726. throw new Error('Attribute value not specified.');
  727. }
  728. }
  729. }
  730. // Only support RSA and ECDSA
  731. function getHashAgl(oid) {
  732. switch (common_1.getOIDName(oid)) {
  733. case 'sha1WithRsaEncryption':
  734. return 'sha1';
  735. case 'md5WithRsaEncryption':
  736. return 'md5';
  737. case 'sha256WithRsaEncryption':
  738. return 'sha256';
  739. case 'sha384WithRsaEncryption':
  740. return 'sha384';
  741. case 'sha512WithRsaEncryption':
  742. return 'sha512';
  743. case 'RSASSA-PSS':
  744. return 'sha256';
  745. case 'ecdsaWithSha1':
  746. return 'sha1';
  747. case 'ecdsaWithSha256':
  748. return 'sha256';
  749. case 'ecdsaWithSha384':
  750. return 'sha384';
  751. case 'ecdsaWithSha512':
  752. return 'sha512';
  753. case 'dsaWithSha1':
  754. return 'sha1';
  755. case 'dsaWithSha256':
  756. return 'sha256';
  757. default:
  758. return '';
  759. }
  760. }
  761. // Converts an RDNSequence of ASN.1 DER-encoded RelativeDistinguishedName
  762. // sets into an array with objects that have type and value properties.
  763. function RDNAttributesAsArray(rdn) {
  764. const rval = [];
  765. // each value in 'rdn' in is a SET of RelativeDistinguishedName
  766. // var set, attr, obj
  767. for (const set of rdn.mustCompound()) {
  768. // each value in the SET is an AttributeTypeAndValue sequence
  769. // containing first a type (an OID) and second a value (defined by the OID)
  770. for (const attr of set.mustCompound()) {
  771. const values = attr.mustCompound();
  772. const obj = {};
  773. obj.oid = asn1_1.ASN1.parseOID(values[0].bytes);
  774. obj.value = values[1].value;
  775. obj.valueTag = values[1].tag;
  776. obj.name = common_1.getOIDName(obj.oid);
  777. obj.shortName = getShortName(obj.name);
  778. rval.push(obj);
  779. }
  780. }
  781. return rval;
  782. }
  783. function toJSONify(val) {
  784. if (val != null && !(val instanceof Buffer) && typeof val.toJSON === 'function') {
  785. return val.toJSON();
  786. }
  787. return val;
  788. }
  789. //# sourceMappingURL=x509.js.map