// Generated by IcedCoffeeScript 1.7.1-c
(function() {
  var ASP, BaseKey, BaseKeyPair, BigInteger, C, K, MRF, Output, Pair, Priv, Pub, SHA512, SRF, bn, bufeq_secure, eme_pkcs1_decode, eme_pkcs1_encode, emsa_pkcs1_decode, emsa_pkcs1_encode, iced, konst, make_esc, naive_is_prime, nbi, nbits, nbv, random_prime, __iced_k, __iced_k_noop, _ref, _ref1, _ref2, _ref3, _ref4,
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  iced = require('iced-runtime').iced;
  __iced_k = __iced_k_noop = function() {};

  _ref = require('./primegen'), naive_is_prime = _ref.naive_is_prime, random_prime = _ref.random_prime;

  bn = require('./bn');

  nbits = bn.nbits, nbv = bn.nbv, nbs = bn.nbs, nbi = bn.nbi, BigInteger = bn.BigInteger;

  _ref1 = require('./util'), bufeq_secure = _ref1.bufeq_secure, ASP = _ref1.ASP;

  make_esc = require('iced-error').make_esc;

  konst = require('./const');

  C = konst.openpgp;

  K = konst.kb;

  SHA512 = require('./hash').SHA512;

  _ref2 = require('./pad'), eme_pkcs1_encode = _ref2.eme_pkcs1_encode, eme_pkcs1_decode = _ref2.eme_pkcs1_decode, emsa_pkcs1_decode = _ref2.emsa_pkcs1_decode, emsa_pkcs1_encode = _ref2.emsa_pkcs1_encode;

  _ref3 = require('./rand'), SRF = _ref3.SRF, MRF = _ref3.MRF;

  _ref4 = require('./basekeypair'), BaseKey = _ref4.BaseKey, BaseKeyPair = _ref4.BaseKeyPair;

  Priv = (function(_super) {
    __extends(Priv, _super);

    function Priv(_arg) {
      this.p = _arg.p, this.q = _arg.q, this.d = _arg.d, this.dmp1 = _arg.dmp1, this.dmq1 = _arg.dmq1, this.u = _arg.u, this.pub = _arg.pub;
    }

    Priv.prototype.decrypt = function(c, cb) {
      var x, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
            funcname: "Priv.decrypt"
          });
          _this.mod_pow_d_crt(c, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return x = arguments[0];
              };
            })(),
            lineno: 22
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          return cb(null, x);
        };
      })(this));
    };

    Priv.prototype.sign = function(m, cb) {
      return this.mod_pow_d_crt(m, cb);
    };

    Priv.ORDER = ['d', 'p', 'q', 'u'];

    Priv.prototype.ORDER = Priv.ORDER;

    Priv.prototype.n = function() {
      return this.p.multiply(this.q);
    };

    Priv.prototype.phi = function() {
      return this.p.subtract(BigInteger.ONE).multiply(this.q.subtract(BigInteger.ONE));
    };

    Priv.prototype.lambda = function() {
      return this.phi.divide(this.p.subtract(BigInteger.ONE).gcd(this.q.subtract(BigInteger.ONE)));
    };

    Priv.alloc = function(raw, pub) {
      return BaseKey.alloc(Priv, raw, {
        pub: pub
      });
    };

    Priv.prototype.mod_pow_d_crt = function(x, cb) {
      var n, r, r_e, r_inv, x_1, xp, xq, y, y_0, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      if (this.dP == null) {
        this.dP = this.d.mod(this.p.subtract(BigInteger.ONE));
      }
      if (this.dQ == null) {
        this.dQ = this.d.mod(this.q.subtract(BigInteger.ONE));
      }
      if (this.qInv == null) {
        this.qInv = this.q.modInverse(this.p);
      }

      /* Chinese remainder theorem (CRT) states:
      
        Suppose n1, n2, ..., nk are positive integers which are pairwise
        coprime (n1 and n2 have no common factors other than 1). For any
        integers x1, x2, ..., xk there exists an integer x solving the
        system of simultaneous congruences (where ~= means modularly
        congruent so a ~= b mod n means a mod n = b mod n):
      
        x ~= x1 mod n1
        x ~= x2 mod n2
        ...
        x ~= xk mod nk
      
        This system of congruences has a single simultaneous solution x
        between 0 and n - 1. Furthermore, each xk solution and x itself
        is congruent modulo the product n = n1*n2*...*nk.
        So x1 mod n = x2 mod n = xk mod n = x mod n.
      
        The single simultaneous solution x can be solved with the following
        equation:
      
        x = sum(xi*ri*si) mod n where ri = n/ni and si = ri^-1 mod ni.
      
        Where x is less than n, xi = x mod ni.
      
        For RSA we are only concerned with k = 2. The modulus n = pq, where
        p and q are coprime. The RSA decryption algorithm is:
      
        y = x^d mod n
      
        Given the above:
      
        x1 = x^d mod p
        r1 = n/p = q
        s1 = q^-1 mod p
        x2 = x^d mod q
        r2 = n/q = p
        s2 = p^-1 mod q
      
        So y = (x1r1s1 + x2r2s2) mod n
             = ((x^d mod p)q(q^-1 mod p) + (x^d mod q)p(p^-1 mod q)) mod n
      
        According to Fermat's Little Theorem, if the modulus P is prime,
        for any integer A not evenly divisible by P, A^(P-1) ~= 1 mod P.
        Since A is not divisible by P it follows that if:
        N ~= M mod (P - 1), then A^N mod P = A^M mod P. Therefore:
      
        A^N mod P = A^(M mod (P - 1)) mod P. (The latter takes less effort
        to calculate). In order to calculate x^d mod p more quickly the
        exponent d mod (p - 1) is stored in the RSA private key (the same
        is done for x^d mod q). These values are referred to as dP and dQ
        respectively. Therefore we now have:
      
        y = ((x^dP mod p)q(q^-1 mod p) + (x^dQ mod q)p(p^-1 mod q)) mod n
      
        Since we'll be reducing x^dP by modulo p (same for q) we can also
        reduce x by p (and q respectively) before hand. Therefore, let
      
        xp = ((x mod p)^dP mod p), and
        xq = ((x mod q)^dQ mod q), yielding:
      
        y = (xp*q*(q^-1 mod p) + xq*p*(p^-1 mod q)) mod n
      
        This can be further reduced to a simple algorithm that only
        requires 1 inverse (the q inverse is used) to be used and stored.
        The algorithm is called Garner's algorithm. If qInv is the
        inverse of q, we simply calculate:
      
        y = (qInv*(xp - xq) mod p) * q + xq
      
        However, there are two further complications. First, we need to
        ensure that xp > xq to prevent signed BigIntegers from being used
        so we add p until this is true (since we will be mod'ing with
        p anyway). Then, there is a known timing attack on algorithms
        using the CRT. To mitigate this risk, "cryptographic blinding"
        should be used (*Not yet implemented*). This requires simply
        generating a random number r between 0 and n-1 and its inverse
        and multiplying x by r^e before calculating y and then multiplying
        y by r^-1 afterwards.
       */
      n = this.pub.n;
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
            funcname: "Priv.mod_pow_d_crt"
          });
          SRF().random_zn(n, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return r = arguments[0];
              };
            })(),
            lineno: 141
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          r_inv = r.modInverse(n);
          r_e = r.modPow(_this.pub.e, n);
          x_1 = x.multiply(r_e).mod(n);
          xp = x_1.mod(_this.p).modPow(_this.dP, _this.p);
          xq = x_1.mod(_this.q).modPow(_this.dQ, _this.q);
          while (xp.compareTo(xq) < 0) {
            xp = xp.add(_this.p);
          }
          y_0 = xp.subtract(xq).multiply(_this.qInv).mod(_this.p).multiply(_this.q).add(xq);
          y = y_0.multiply(r_inv).mod(n);
          return cb(y);
        };
      })(this));
    };

    return Priv;

  })(BaseKey);

  Pub = (function(_super) {
    __extends(Pub, _super);

    Pub.type = C.public_key_algorithms.RSA;

    Pub.prototype.type = Pub.type;

    Pub.ORDER = ['n', 'e'];

    Pub.prototype.ORDER = Pub.ORDER;

    function Pub(_arg) {
      this.n = _arg.n, this.e = _arg.e;
    }

    Pub.prototype.encrypt = function(p, cb) {
      return this.mod_pow(p, this.e, cb);
    };

    Pub.prototype.verify = function(s, cb) {
      return this.mod_pow(s, this.e, cb);
    };

    Pub.prototype.nbits = function() {
      var _ref5;
      return (_ref5 = this.n) != null ? _ref5.bitLength() : void 0;
    };

    Pub.alloc = function(raw) {
      return BaseKey.alloc(Pub, raw);
    };

    Pub.prototype.mod_pow = function(x, d, cb) {
      return cb(x.modPow(d, this.n));
    };

    Pub.prototype.validity_check = function(cb) {
      var err;
      err = !this.n.gcd(this.e).equals(BigInteger.ONE) ? new Error("gcd(n,e) != 1") : !this.n.mod(nbv(2)).equals(BigInteger.ONE) ? new Error("n % 2 != 1") : this.e.compareTo(BigInteger.ONE) <= 0 ? new Error("e <= 1") : this.e.bitLength() > 32 ? new Error("e=" + this.e + " > 2^32") : null;
      return cb(err);
    };

    return Pub;

  })(BaseKey);

  Pair = (function(_super) {
    __extends(Pair, _super);

    Pair.type = C.public_key_algorithms.RSA;

    Pair.prototype.type = Pair.type;

    Pair.prototype.get_type = function() {
      return this.type;
    };

    Pair.klass_name = 'RSA';

    Pair.Pub = Pub;

    Pair.prototype.Pub = Pub;

    Pair.Priv = Priv;

    Pair.prototype.Priv = Priv;

    function Pair(_arg) {
      var priv, pub;
      priv = _arg.priv, pub = _arg.pub;
      Pair.__super__.constructor.call(this, {
        priv: priv,
        pub: pub
      });
    }

    Pair.parse = function(pub_raw) {
      return BaseKeyPair.parse(Pair, pub_raw);
    };

    Pair.alloc = function(_arg) {
      var priv, pub;
      pub = _arg.pub, priv = _arg.priv;
      return BaseKeyPair.alloc({
        pub: pub,
        priv: priv
      });
    };

    Pair.subkey_algo = function(flags) {
      return Pair;
    };

    Pair.prototype.sanity_check = function(cb) {
      var err, x0, x1, x2, y0, y1, y2, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      err = this.priv.n().compareTo(this.pub.n) === 0 ? null : new Error("pq != n");
      (function(_this) {
        return (function(__iced_k) {
          if (err == null) {
            x0 = MRF().random_zn(_this.pub.n);
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
                funcname: "Pair.sanity_check"
              });
              _this.encrypt(x0, __iced_deferrals.defer({
                assign_fn: (function() {
                  return function() {
                    return x1 = arguments[0];
                  };
                })(),
                lineno: 240
              }));
              __iced_deferrals._fulfill();
            })(function() {
              (function(__iced_k) {
                __iced_deferrals = new iced.Deferrals(__iced_k, {
                  parent: ___iced_passed_deferral,
                  filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
                  funcname: "Pair.sanity_check"
                });
                _this.decrypt(x1, __iced_deferrals.defer({
                  assign_fn: (function() {
                    return function() {
                      err = arguments[0];
                      return x2 = arguments[1];
                    };
                  })(),
                  lineno: 241
                }));
                __iced_deferrals._fulfill();
              })(function() {
                return __iced_k((err == null) && x0.compareTo(x2) !== 0 ? err = new Error("Decrypt/encrypt failed") : void 0);
              });
            });
          } else {
            return __iced_k();
          }
        });
      })(this)((function(_this) {
        return function() {
          (function(__iced_k) {
            if (err == null) {
              y0 = MRF().random_zn(_this.pub.n);
              (function(__iced_k) {
                __iced_deferrals = new iced.Deferrals(__iced_k, {
                  parent: ___iced_passed_deferral,
                  filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
                  funcname: "Pair.sanity_check"
                });
                _this.sign(y0, __iced_deferrals.defer({
                  assign_fn: (function() {
                    return function() {
                      return y1 = arguments[0];
                    };
                  })(),
                  lineno: 246
                }));
                __iced_deferrals._fulfill();
              })(function() {
                (function(__iced_k) {
                  __iced_deferrals = new iced.Deferrals(__iced_k, {
                    parent: ___iced_passed_deferral,
                    filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
                    funcname: "Pair.sanity_check"
                  });
                  _this.verify(y1, __iced_deferrals.defer({
                    assign_fn: (function() {
                      return function() {
                        return y2 = arguments[0];
                      };
                    })(),
                    lineno: 247
                  }));
                  __iced_deferrals._fulfill();
                })(function() {
                  return __iced_k(y0.compareTo(y2) !== 0 ? err = new Error("Sign/verify failed") : void 0);
                });
              });
            } else {
              return __iced_k();
            }
          })(function() {
            return cb(err);
          });
        };
      })(this));
    };

    Pair.parse_sig = function(slice) {
      var err, n, raw, ret, _ref5;
      _ref5 = bn.mpi_from_buffer(slice.peek_rest_to_buffer()), err = _ref5[0], ret = _ref5[1], raw = _ref5[2], n = _ref5[3];
      if (err != null) {
        throw err;
      }
      slice.advance(n);
      return ret;
    };

    Pair.prototype.encrypt = function(p, cb) {
      return this.pub.encrypt(p, cb);
    };

    Pair.prototype.decrypt = function(c, cb) {
      return this.priv.decrypt(c, cb);
    };

    Pair.prototype.max_value = function() {
      return this.pub.n;
    };

    Pair.make = function(_arg) {
      var d, dmp1, dmq1, e, lambda, n, p, p1, phi, priv, pub, q, q1, u;
      p = _arg.p, q = _arg.q, e = _arg.e, phi = _arg.phi, p1 = _arg.p1, q1 = _arg.q1, lambda = _arg.lambda;
      n = p.multiply(q);
      d = e.modInverse(lambda);
      dmp1 = d.mod(p1);
      dmq1 = d.mod(q1);
      u = p.modInverse(q);
      pub = new Pub({
        n: n,
        e: e
      });
      priv = new Priv({
        p: p,
        q: q,
        d: d,
        dmp1: dmp1,
        dmq1: dmq1,
        u: u,
        pub: pub
      });
      return new Pair({
        priv: priv,
        pub: pub
      });
    };

    Pair.prototype.to_openpgp = function() {
      var key;
      key = new (new RSA).keyObject();
      key.n = this.pub.n;
      key.e = this.pub.e.intValue();
      key.ee = this.pub.e;
      key.d = this.priv.d;
      key.p = this.priv.p;
      key.q = this.priv.q;
      key.dmp1 = this.priv.dmp1;
      key.dmq1 = this.priv.dmq1;
      key.u = this.priv.u;
      return key;
    };

    Pair.prototype.sign = function(m, cb) {
      return this.priv.sign(m, cb);
    };

    Pair.prototype.verify = function(s, cb) {
      return this.pub.verify(s, cb);
    };

    Pair.prototype.pad_and_encrypt = function(data, params, cb) {
      var ct, err, m, ret, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      err = ret = null;
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
            funcname: "Pair.pad_and_encrypt"
          });
          eme_pkcs1_encode(data, _this.pub.n.mpi_byte_length(), __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                err = arguments[0];
                return m = arguments[1];
              };
            })(),
            lineno: 306
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          (function(__iced_k) {
            if (err == null) {
              (function(__iced_k) {
                __iced_deferrals = new iced.Deferrals(__iced_k, {
                  parent: ___iced_passed_deferral,
                  filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
                  funcname: "Pair.pad_and_encrypt"
                });
                _this.encrypt(m, __iced_deferrals.defer({
                  assign_fn: (function() {
                    return function() {
                      return ct = arguments[0];
                    };
                  })(),
                  lineno: 308
                }));
                __iced_deferrals._fulfill();
              })(function() {
                return __iced_k(ret = _this.export_output({
                  y_mpi: ct
                }));
              });
            } else {
              return __iced_k();
            }
          })(function() {
            return cb(err, ret);
          });
        };
      })(this));
    };

    Pair.prototype.decrypt_and_unpad = function(ciphertext, params, cb) {
      var b, err, p, ret, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      err = ret = null;
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
            funcname: "Pair.decrypt_and_unpad"
          });
          _this.decrypt(ciphertext.y(), __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                err = arguments[0];
                return p = arguments[1];
              };
            })(),
            lineno: 318
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          var _ref5;
          if (err == null) {
            b = p.to_padded_octets(_this.pub.n);
            _ref5 = eme_pkcs1_decode(b), err = _ref5[0], ret = _ref5[1];
          }
          return cb(err, ret);
        };
      })(this));
    };

    Pair.prototype.pad_and_sign = function(data, _arg, cb) {
      var hashed_data, hasher, m, sig, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      hasher = _arg.hasher;
      hasher || (hasher = SHA512);
      hashed_data = hasher(data);
      m = emsa_pkcs1_encode(hashed_data, this.pub.n.mpi_byte_length(), {
        hasher: hasher
      });
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
            funcname: "Pair.pad_and_sign"
          });
          _this.sign(m, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return sig = arguments[0];
              };
            })(),
            lineno: 330
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          return cb(null, sig.to_mpi_buffer());
        };
      })(this));
    };

    Pair.prototype.verify_unpad_and_check_hash = function(_arg, cb) {
      var b, data, err, hash, hasher, hd1, sig, v, ___iced_passed_deferral, __iced_deferrals, __iced_k, _ref5;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      sig = _arg.sig, data = _arg.data, hasher = _arg.hasher, hash = _arg.hash;
      err = null;
      if (Buffer.isBuffer(sig)) {
        _ref5 = bn.mpi_from_buffer(sig), err = _ref5[0], sig = _ref5[1];
      }
      (function(_this) {
        return (function(__iced_k) {
          if (err == null) {
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
                funcname: "Pair.verify_unpad_and_check_hash"
              });
              _this.verify(sig, __iced_deferrals.defer({
                assign_fn: (function() {
                  return function() {
                    return v = arguments[0];
                  };
                })(),
                lineno: 339
              }));
              __iced_deferrals._fulfill();
            })(function() {
              var _ref6;
              b = v.to_padded_octets(_this.pub.n);
              _ref6 = emsa_pkcs1_decode(b, hasher), err = _ref6[0], hd1 = _ref6[1];
              return __iced_k(err == null ? (hash || (hash = hasher(data)), !bufeq_secure(hd1, hash) ? err = new Error("hash mismatch") : void 0) : void 0);
            });
          } else {
            return __iced_k();
          }
        });
      })(this)((function(_this) {
        return function() {
          return cb(err);
        };
      })(this));
    };

    Pair.generate = function(_arg, cb) {
      var asp, e, e_orig, esc, go, iters, key, lambda, nbits, p, p1, phi, q, q1, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      nbits = _arg.nbits, iters = _arg.iters, e = _arg.e, asp = _arg.asp;
      e || (e = (1 << 16) + 1);
      e_orig = e;
      nbits || (nbits = 4096);
      iters || (iters = 10);
      asp || (asp = new ASP({}));
      e = nbv(e_orig);
      esc = make_esc(cb, "generate_rsa_keypair");
      go = true;
      nbits >>= 1;
      (function(_this) {
        return (function(__iced_k) {
          var _results, _while;
          _results = [];
          _while = function(__iced_k) {
            var _break, _continue, _next;
            _break = function() {
              return __iced_k(_results);
            };
            _continue = function() {
              return iced.trampoline(function() {
                return _while(__iced_k);
              });
            };
            _next = function(__iced_next_arg) {
              _results.push(__iced_next_arg);
              return _continue();
            };
            if (!go) {
              return _break();
            } else {
              (function(__iced_k) {
                __iced_deferrals = new iced.Deferrals(__iced_k, {
                  parent: ___iced_passed_deferral,
                  filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
                  funcname: "Pair.generate"
                });
                random_prime({
                  asp: asp.section('p'),
                  e: e,
                  nbits: nbits,
                  iters: iters
                }, esc(__iced_deferrals.defer({
                  assign_fn: (function() {
                    return function() {
                      return p = arguments[0];
                    };
                  })(),
                  lineno: 363
                })));
                __iced_deferrals._fulfill();
              })(function() {
                (function(__iced_k) {
                  __iced_deferrals = new iced.Deferrals(__iced_k, {
                    parent: ___iced_passed_deferral,
                    filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
                    funcname: "Pair.generate"
                  });
                  asp.progress({
                    what: "found",
                    p: p
                  }, esc(__iced_deferrals.defer({
                    lineno: 364
                  })));
                  __iced_deferrals._fulfill();
                })(function() {
                  (function(__iced_k) {
                    __iced_deferrals = new iced.Deferrals(__iced_k, {
                      parent: ___iced_passed_deferral,
                      filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
                      funcname: "Pair.generate"
                    });
                    random_prime({
                      asp: asp.section('q'),
                      e: e,
                      nbits: nbits,
                      iters: iters
                    }, esc(__iced_deferrals.defer({
                      assign_fn: (function() {
                        return function() {
                          return q = arguments[0];
                        };
                      })(),
                      lineno: 365
                    })));
                    __iced_deferrals._fulfill();
                  })(function() {
                    (function(__iced_k) {
                      __iced_deferrals = new iced.Deferrals(__iced_k, {
                        parent: ___iced_passed_deferral,
                        filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
                        funcname: "Pair.generate"
                      });
                      asp.progress({
                        what: "found",
                        q: q
                      }, esc(__iced_deferrals.defer({
                        lineno: 366
                      })));
                      __iced_deferrals._fulfill();
                    })(function() {
                      var _ref5;
                      if (p.compareTo(q) <= 0) {
                        _ref5 = [q, p], p = _ref5[0], q = _ref5[1];
                      }
                      q1 = q.subtract(BigInteger.ONE);
                      p1 = p.subtract(BigInteger.ONE);
                      phi = p1.multiply(q1);
                      lambda = phi.divide(q1.gcd(p1));
                      return _next(phi.gcd(e).compareTo(BigInteger.ONE) !== 0 ? (typeof progress_hook === "function" ? progress_hook({
                        what: "unlucky_phi"
                      }) : void 0, go = true) : go = false);
                    });
                  });
                });
              });
            }
          };
          _while(__iced_k);
        });
      })(this)((function(_this) {
        return function() {
          key = Pair.make({
            p: p,
            q: q,
            e: e,
            phi: phi,
            p1: p1,
            q1: q1,
            lambda: lambda
          });
          return cb(null, key);
        };
      })(this));
    };

    Pair.parse_output = function(buf) {
      return Output.parse(buf);
    };

    Pair.prototype.export_output = function(args) {
      return new Output(args);
    };

    Pair.prototype.validity_check = function(cb) {
      var err, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
            funcname: "Pair.validity_check"
          });
          _this.pub.validity_check(__iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return err = arguments[0];
              };
            })(),
            lineno: 391
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          return cb(err);
        };
      })(this));
    };

    return Pair;

  })(BaseKeyPair);

  Output = (function() {
    function Output(_arg) {
      this.y_mpi = _arg.y_mpi, this.y_buf = _arg.y_buf;
    }

    Output.parse = function(buf) {
      var err, n, raw, ret, _ref5;
      _ref5 = bn.mpi_from_buffer(buf), err = _ref5[0], ret = _ref5[1], raw = _ref5[2], n = _ref5[3];
      if (err != null) {
        throw err;
      }
      if (raw.length !== 0) {
        throw new Error("junk at the end of input");
      }
      return new Output({
        y_mpi: ret
      });
    };

    Output.prototype.y = function() {
      return this.y_mpi;
    };

    Output.prototype.hide = function(_arg, cb) {
      var err, i, key, max, slosh, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      key = _arg.key, max = _arg.max, slosh = _arg.slosh;
      max || (max = 8192);
      slosh || (slosh = 128);
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/rsa.iced",
            funcname: "Output.hide"
          });
          key.hide({
            i: _this.y(),
            max: max,
            slosh: slosh
          }, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                err = arguments[0];
                return i = arguments[1];
              };
            })(),
            lineno: 417
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          if (typeof err === "undefined" || err === null) {
            _this.y_mpi = i;
            _this.y_buf = null;
          }
          return cb(err);
        };
      })(this));
    };

    Output.prototype.find = function(_arg) {
      var key;
      key = _arg.key;
      return this.y_mpi = key.find(this.y_mpi);
    };

    Output.prototype.output = function() {
      return this.y_buf || this.y_mpi.to_mpi_buffer();
    };

    return Output;

  })();

  exports.RSA = exports.Pair = Pair;

  exports.Output = Output;

}).call(this);
