docs: function X509() {
      this.subjectPublicKeyRSA = null;
      this.subjectPublicKeyRSA_hN = null;
      this.subjectPublicKeyRSA_hE = null;
      this.hex = null;
  
      // ===== get basic fields from hex =====================================
  
      /**
       * get hexadecimal string of serialNumber field of certificate.<br/>
       * @name getSerialNumberHex
       * @memberOf X509#
       * @function
       */
      this.getSerialNumberHex = function() {
          return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);
      };
  
      /**
       * get hexadecimal string of issuer field TLV of certificate.<br/>
       * @name getIssuerHex
       * @memberOf X509#
       * @function
       */
      this.getIssuerHex = function() {
          return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);
      };
  
      /**
       * get string of issuer field of certificate.<br/>
       * @name getIssuerString
       * @memberOf X509#
       * @function
       */
      this.getIssuerString = function() {
          return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));
      };
  
      /**
       * get hexadecimal string of subject field of certificate.<br/>
       * @name getSubjectHex
       * @memberOf X509#
       * @function
       */
      this.getSubjectHex = function() {
          return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);
      };
  
      /**
       * get string of subject field of certificate.<br/>
       * @name getSubjectString
       * @memberOf X509#
       * @function
       */
      this.getSubjectString = function() {
          return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));
      };
  
      /**
       * get notBefore field string of certificate.<br/>
       * @name getNotBefore
       * @memberOf X509#
       * @function
       */
      this.getNotBefore = function() {
          var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]);
          s = s.replace(/(..)/g, "%$1");
          s = decodeURIComponent(s);
          return s;
      };
  
      /**
       * get notAfter field string of certificate.<br/>
       * @name getNotAfter
       * @memberOf X509#
       * @function
       */
      this.getNotAfter = function() {
          var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);
          s = s.replace(/(..)/g, "%$1");
          s = decodeURIComponent(s);
          return s;
      };
  
      // ===== read certificate public key ==========================
  
      // ===== read certificate =====================================
      /**
       * read PEM formatted X.509 certificate from string.<br/>
       * @name readCertPEM
       * @memberOf X509#
       * @function
       * @param {String} sCertPEM string for PEM formatted X.509 certificate
       */
      this.readCertPEM = function(sCertPEM) {
          var hCert = X509.pemToHex(sCertPEM);
          var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
          var rsa = new RSAKey();
          rsa.setPublic(a[0], a[1]);
          this.subjectPublicKeyRSA = rsa;
          this.subjectPublicKeyRSA_hN = a[0];
          this.subjectPublicKeyRSA_hE = a[1];
          this.hex = hCert;
      };
  
      this.readCertPEMWithoutRSAInit = function(sCertPEM) {
          var hCert = X509.pemToHex(sCertPEM);
          var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
          this.subjectPublicKeyRSA.setPublic(a[0], a[1]);
          this.subjectPublicKeyRSA_hN = a[0];
          this.subjectPublicKeyRSA_hE = a[1];
          this.hex = hCert;
      };
  }