text: // Depends on jsbn.js and rng.js
  // Version 1.1: support utf-8 encoding in pkcs1pad2
  // convert a (hex) string to a bignum object
  import { BigInteger, nbi, parseBigInt } from "./jsbn";
  import { SecureRandom } from "./rng";
  import { Hex } from "./../asn1js/hex";
  // function linebrk(s,n) {
  //   var ret = "";
  //   var i = 0;
  //   while(i + n < s.length) {
  //     ret += s.substring(i,i+n) + "\n";
  //     i += n;
  //   }
  //   return ret + s.substring(i,s.length);
  // }
  // function byte2Hex(b) {
  //   if(b < 0x10)
  //     return "0" + b.toString(16);
  //   else
  //     return b.toString(16);
  // }
  function pkcs1pad1(s, n) {
      if (n < s.length + 22) {
          console.error("Message too long for RSA");
          return null;
      }
      var len = n - s.length - 6;
      var filler = "";
      for (var f = 0; f < len; f += 2) {
          filler += "ff";
      }
      var m = "0001" + filler + "00" + s;
      return parseBigInt(m, 16);
  }
  // PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
  function pkcs1pad2(s, n) {
      if (n < s.length + 11) { // TODO: fix for utf-8
          console.error("Message too long for RSA");
          return null;
      }
      var ba = [];
      var i = s.length - 1;
      while (i >= 0 && n > 0) {
          var c = s.charCodeAt(i--);
          if (c < 128) { // encode using utf-8
              ba[--n] = c;
          }
          else if ((c > 127) && (c < 2048)) {
              ba[--n] = (c & 63) | 128;
              ba[--n] = (c >> 6) | 192;
          }
          else {
              ba[--n] = (c & 63) | 128;
              ba[--n] = ((c >> 6) & 63) | 128;
              ba[--n] = (c >> 12) | 224;
          }
      }
      ba[--n] = 0;
      var rng = new SecureRandom();
      var x = [];
      while (n > 2) { // random non-zero pad
          x[0] = 0;
          while (x[0] == 0) {
              rng.nextBytes(x);
          }
          ba[--n] = x[0];
      }
      ba[--n] = 2;
      ba[--n] = 0;
      return new BigInteger(ba);
  }
  // "empty" RSA key constructor
  var RSAKey = /** @class */ (function () {
      function RSAKey() {
          this.n = null;
          this.e = 0;
          this.d = null;
          this.p = null;
          this.q = null;
          this.dmp1 = null;
          this.dmq1 = null;
          this.coeff = null;
      }
      //#region PROTECTED
      // protected
      // RSAKey.prototype.doPublic = RSADoPublic;
      // Perform raw public operation on "x": return x^e (mod n)
      RSAKey.prototype.doPublic = function (x) {
          return x.modPowInt(this.e, this.n);
      };
      // RSAKey.prototype.doPrivate = RSADoPrivate;
      // Perform raw private operation on "x": return x^d (mod n)
      RSAKey.prototype.doPrivate = function (x) {
          if (this.p == null || this.q == null) {
              return x.modPow(this.d, this.n);
          }
          // TODO: re-calculate any missing CRT params
          var xp = x.mod(this.p).modPow(this.dmp1, this.p);
          var xq = x.mod(this.q).modPow(this.dmq1, this.q);
          while (xp.compareTo(xq) < 0) {
              xp = xp.add(this.p);
          }
          return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);
      };
      //#endregion PROTECTED
      //#region PUBLIC
      // RSAKey.prototype.setPublic = RSASetPublic;
      // Set the public key fields N and e from hex strings
      RSAKey.prototype.setPublic = function (N, E) {
          if (N != null && E != null && N.length > 0 && E.length > 0) {
              this.n = parseBigInt(N, 16);
              this.e = parseInt(E, 16);
          }
          else {
              console.error("Invalid RSA public key");
          }
      };
      // RSAKey.prototype.encrypt = RSAEncrypt;
      // Return the PKCS#1 RSA encryption of "text" as an even-length hex string
      RSAKey.prototype.encrypt = function (text) {
          var maxLength = (this.n.bitLength() + 7) >> 3;
          var m = pkcs1pad2(text, maxLength);
          if (m == null) {
              return null;
          }
          var c = this.doPublic(m);
          if (c == null) {
              return null;
          }
          var h = c.toString(16);
          var length = h.length;
          // fix zero before result
          for (var i = 0; i < maxLength * 2 - length; i++) {
              h = "0" + h;
          }
          return h;
      };
      // RSAKey.prototype.setPrivate = RSASetPrivate;
      // Set the private key fields N, e, and d from hex strings
      RSAKey.prototype.setPrivate = function (N, E, D) {
          if (N != null && E != null && N.length > 0 && E.length > 0) {
              this.n = parseBigInt(N, 16);
              this.e = parseInt(E, 16);
              this.d = parseBigInt(D, 16);
          }
          else {
              console.error("Invalid RSA private key");
          }
      };
      // RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
      // Set the private key fields N, e, d and CRT params from hex strings
      RSAKey.prototype.setPrivateEx = function (N, E, D, P, Q, DP, DQ, C) {
          if (N != null && E != null && N.length > 0 && E.length > 0) {
              this.n = parseBigInt(N, 16);
              this.e = parseInt(E, 16);
              this.d = parseBigInt(D, 16);
              this.p = parseBigInt(P, 16);
              this.q = parseBigInt(Q, 16);
              this.dmp1 = parseBigInt(DP, 16);
              this.dmq1 = parseBigInt(DQ, 16);
              this.coeff = parseBigInt(C, 16);
          }
          else {
              console.error("Invalid RSA private key");
          }
      };
      // RSAKey.prototype.generate = RSAGenerate;
      // Generate a new random private key B bits long, using public expt E
      RSAKey.prototype.generate = function (B, E) {
          var rng = new SecureRandom();
          var qs = B >> 1;
          this.e = parseInt(E, 16);
          var ee = new BigInteger(E, 16);
          for (;;) {
              for (;;) {
                  this.p = new BigInteger(B - qs, 1, rng);
                  if (this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) {
                      break;
                  }
              }
              for (;;) {
                  this.q = new BigInteger(qs, 1, rng);
                  if (this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) {
                      break;
                  }
              }
              if (this.p.compareTo(this.q) <= 0) {
                  var t = this.p;
                  this.p = this.q;
                  this.q = t;
              }
              var p1 = this.p.subtract(BigInteger.ONE);
              var q1 = this.q.subtract(BigInteger.ONE);
              var phi = p1.multiply(q1);
              if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
                  this.n = this.p.multiply(this.q);
                  this.d = ee.modInverse(phi);
                  this.dmp1 = this.d.mod(p1);
                  this.dmq1 = this.d.mod(q1);
                  this.coeff = this.q.modInverse(this.p);
                  break;
              }
          }
      };
      // RSAKey.prototype.decrypt = RSADecrypt;
      // Return the PKCS#1 RSA decryption of "ctext".
      // "ctext" is an even-length hex string and the output is a plain string.
      RSAKey.prototype.decrypt = function (ctext) {
          var c = parseBigInt(ctext, 16);
          var m = this.doPrivate(c);
          if (m == null) {
              return null;
          }
          var mh = pkcs1unpad2(m, (this.n.bitLength() + 7) >> 3);
          // encoding为utf-8
          var bt = Hex.decode(mh);
          return bt;
          //return pkcs1unpad2(m, (this.n.bitLength() + 7) >> 3);
      };
      // Generate a new random private key B bits long, using public expt E
      RSAKey.prototype.generateAsync = function (B, E, callback) {
          var rng = new SecureRandom();
          var qs = B >> 1;
          this.e = parseInt(E, 16);
          var ee = new BigInteger(E, 16);
          var rsa = this;
          // These functions have non-descript names because they were originally for(;;) loops.
          // I don't know about cryptography to give them better names than loop1-4.
          var loop1 = function () {
              var loop4 = function () {
                  if (rsa.p.compareTo(rsa.q) <= 0) {
                      var t = rsa.p;
                      rsa.p = rsa.q;
                      rsa.q = t;
                  }
                  var p1 = rsa.p.subtract(BigInteger.ONE);
                  var q1 = rsa.q.subtract(BigInteger.ONE);
                  var phi = p1.multiply(q1);
                  if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
                      rsa.n = rsa.p.multiply(rsa.q);
                      rsa.d = ee.modInverse(phi);
                      rsa.dmp1 = rsa.d.mod(p1);
                      rsa.dmq1 = rsa.d.mod(q1);
                      rsa.coeff = rsa.q.modInverse(rsa.p);
                      setTimeout(function () { callback(); }, 0); // escape
                  }
                  else {
                      setTimeout(loop1, 0);
                  }
              };
              var loop3 = function () {
                  rsa.q = nbi();
                  rsa.q.fromNumberAsync(qs, 1, rng, function () {
                      rsa.q.subtract(BigInteger.ONE).gcda(ee, function (r) {
                          if (r.compareTo(BigInteger.ONE) == 0 && rsa.q.isProbablePrime(10)) {
                              setTimeout(loop4, 0);
                          }
                          else {
                              setTimeout(loop3, 0);
                          }
                      });
                  });
              };
              var loop2 = function () {
                  rsa.p = nbi();
                  rsa.p.fromNumberAsync(B - qs, 1, rng, function () {
                      rsa.p.subtract(BigInteger.ONE).gcda(ee, function (r) {
                          if (r.compareTo(BigInteger.ONE) == 0 && rsa.p.isProbablePrime(10)) {
                              setTimeout(loop3, 0);
                          }
                          else {
                              setTimeout(loop2, 0);
                          }
                      });
                  });
              };
              setTimeout(loop2, 0);
          };
          setTimeout(loop1, 0);
      };
      RSAKey.prototype.sign = function (text, digestMethod, digestName) {
          var header = getDigestHeader(digestName);
          var digest = header + digestMethod(text).toString();
          var m = pkcs1pad1(digest, this.n.bitLength() / 4);
          if (m == null) {
              return null;
          }
          var c = this.doPrivate(m);
          if (c == null) {
              return null;
          }
          var h = c.toString(16);
          if ((h.length & 1) == 0) {
              return h;
          }
          else {
              return "0" + h;
          }
      };
      RSAKey.prototype.verify = function (text, signature, digestMethod) {
          var c = parseBigInt(signature, 16);
          var m = this.doPublic(c);
          if (m == null) {
              return null;
          }
          var unpadded = m.toString(16).replace(/^1f+00/, "");
          var digest = removeDigestHeader(unpadded);
          return digest == digestMethod(text).toString();
      };
      return RSAKey;
  }());
  export { RSAKey };
  // Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
  function pkcs1unpad2(d, n) {
      var b = d.toByteArray();
      var i = 0;
      while (i < b.length && b[i] == 0) {
          ++i;
      }
      if (b.length - i != n - 1 || b[i] != 2) {
          return null;
      }
      ++i;
      while (b[i] != 0) {
          if (++i >= b.length) {
              return null;
          }
      }
      var ret = "";
      while (++i < b.length) {
          var c = b[i] & 255;
          ret += c.toString(16);
          /*
          if (c < 128) { // utf-8 decode
              ret += String.fromCharCode(c);
          } else if ((c > 191) && (c < 224)) {
              ret += String.fromCharCode(((c & 31) << 6) | (b[i + 1] & 63));
              ++i;
          } else {
              ret += String.fromCharCode(((c & 15) << 12) | ((b[i + 1] & 63) << 6) | (b[i + 2] & 63));
              i += 2;
          }*/
      }
      return ret;
  }
  // https://tools.ietf.org/html/rfc3447#page-43
  var DIGEST_HEADERS = {
      md2: "3020300c06082a864886f70d020205000410",
      md5: "3020300c06082a864886f70d020505000410",
      sha1: "3021300906052b0e03021a05000414",
      sha224: "302d300d06096086480165030402040500041c",
      sha256: "3031300d060960864801650304020105000420",
      sha384: "3041300d060960864801650304020205000430",
      sha512: "3051300d060960864801650304020305000440",
      ripemd160: "3021300906052b2403020105000414"
  };
  function getDigestHeader(name) {
      return DIGEST_HEADERS[name] || "";
  }
  function removeDigestHeader(str) {
      for (var name_1 in DIGEST_HEADERS) {
          if (DIGEST_HEADERS.hasOwnProperty(name_1)) {
              var header = DIGEST_HEADERS[name_1];
              var len = header.length;
              if (str.substr(0, len) == header) {
                  return str.substr(len);
              }
          }
      }
      return str;
  }
  // Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
  // function RSAEncryptB64(text) {
  //  var h = this.encrypt(text);
  //  if(h) return hex2b64(h); else return null;
  // }
  // public
  // RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
  