// Generated by IcedCoffeeScript 1.7.1-c
(function() {
  var ASP, BaseEccKey, BaseKey, BaseKeyPair, BigInteger, C, ECDH, K, Pair, Priv, Pub, bn, bufeq_secure, generate, iced, konst, make_esc, nbits, nbv, uint_to_buffer, __iced_k, __iced_k_noop, _ref, _ref1, _ref2,
    __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() {};

  bn = require('../bn');

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

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

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

  konst = require('../const');

  C = konst.openpgp;

  K = konst.kb;

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

  _ref2 = require('./base'), generate = _ref2.generate, BaseEccKey = _ref2.BaseEccKey;

  ECDH = require('./ecdh').ECDH;

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

    function Pub() {
      return Pub.__super__.constructor.apply(this, arguments);
    }

    Pub.type = C.public_key_algorithms.ECDSA;

    Pub.prototype.type = Pub.type;

    Pub.prototype.nbits = function() {
      return this.curve.nbits();
    };

    Pub.prototype.read_params = function(sb) {};

    Pub.prototype.trunc_hash = function(h) {
      return bn.bn_from_left_n_bits(h, this.nbits());
    };

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

    Pub.prototype.verify = function(_arg, h, cb) {
      var err, hi, n, p, r, s, u1, u2, v, w;
      r = _arg[0], s = _arg[1];
      err = null;
      hi = this.trunc_hash(h);
      if ((r.signum() <= 0) || (r.compareTo(this.curve.p) > 0)) {
        err = new Error("bad r");
      } else if ((r.signum() <= 0) || (s.compareTo(this.curve.p) > 0)) {
        err = new Error("bad s");
      } else {
        n = this.curve.n;
        w = s.modInverse(n);
        u1 = hi.multiply(w).mod(n);
        u2 = r.multiply(w).mod(n);
        p = this.curve.G.multiplyTwo(u1, this.R, u2);
        v = p.affineX.mod(n);
        if (!v.equals(r)) {
          err = new Error("verification failed");
        }
      }
      return cb(err);
    };

    return Pub;

  })(BaseEccKey);

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

    Priv.ORDER = ['x'];

    Priv.prototype.ORDER = Priv.ORDER;

    function Priv(_arg) {
      this.x = _arg.x, this.pub = _arg.pub;
    }

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

    Priv.prototype.sign = function(h, cb) {
      var G, Q, err, hi, k, n, r, s, ___iced_passed_deferral, __iced_deferrals, __iced_k, _ref3;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      err = null;
      _ref3 = this.pub.curve, n = _ref3.n, G = _ref3.G;
      hi = this.pub.trunc_hash(h);
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/ecc/ecdsa.iced",
            funcname: "Priv.sign"
          });
          _this.pub.curve.random_scalar(__iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return k = arguments[0];
              };
            })(),
            lineno: 79
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          Q = G.multiply(k);
          r = Q.affineX.mod(n);
          if (r.signum() === 0) {
            throw new Error("invalid r-value");
          }
          s = k.modInverse(n).multiply(hi.add(_this.x.multiply(r))).mod(n);
          return cb([r, s]);
        };
      })(this));
    };

    return Priv;

  })(BaseKey);

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

    Pair.Pub = Pub;

    Pair.prototype.Pub = Pub;

    Pair.Priv = Priv;

    Pair.prototype.Priv = Priv;

    Pair.type = C.public_key_algorithms.ECDSA;

    Pair.prototype.type = Pair.type;

    Pair.klass_name = "ECDSA";

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

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

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

    Pair.prototype.can_encrypt = function() {
      return false;
    };

    Pair.subkey_algo = function(flags) {
      if (flags & (C.key_flags.certify_keys | C.key_flags.sign_data)) {
        return Pair;
      } else {
        return ECDH;
      }
    };

    Pair.prototype.fulfills_flags = function(flags) {
      var good_for;
      good_for = C.key_flags.certify_keys | C.key_flags.sign_data;
      return (flags & good_for) === flags;
    };

    Pair.prototype.verify_unpad_and_check_hash = function(_arg, cb) {
      var data, hash, hasher, sig;
      sig = _arg.sig, data = _arg.data, hasher = _arg.hasher, hash = _arg.hash;
      return this._dsa_verify_update_and_check_hash({
        sig: sig,
        data: data,
        hasher: hasher,
        hash: hash,
        klass: Pair
      }, cb);
    };

    Pair.prototype.pad_and_sign = function(data, _arg, cb) {
      var h, hasher, s, 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);
      h = hasher(data);
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/ecc/ecdsa.iced",
            funcname: "Pair.pad_and_sign"
          });
          _this.priv.sign(h, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return sig = arguments[0];
              };
            })(),
            lineno: 134
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          return cb(null, Buffer.concat((function() {
            var _i, _len, _results;
            _results = [];
            for (_i = 0, _len = sig.length; _i < _len; _i++) {
              s = sig[_i];
              _results.push(s.to_mpi_buffer());
            }
            return _results;
          })()));
        };
      })(this));
    };

    Pair.parse_sig = function(slice) {
      var buf, err, n, ret, _ref3;
      buf = slice.peek_rest_to_buffer();
      _ref3 = Pair.read_sig_from_buf(buf), err = _ref3[0], ret = _ref3[1], n = _ref3[2];
      if (err != null) {
        throw err;
      }
      slice.advance(n);
      return ret;
    };

    Pair.read_sig_from_buf = function(buf) {
      var err, n, o, order, orig_len, ret, x;
      orig_len = buf.length;
      order = ['r', 's'];
      err = null;
      ret = (function() {
        var _i, _len, _ref3, _results;
        _results = [];
        for (_i = 0, _len = order.length; _i < _len; _i++) {
          o = order[_i];
          if (!(err == null)) {
            continue;
          }
          _ref3 = bn.mpi_from_buffer(buf), err = _ref3[0], x = _ref3[1], buf = _ref3[2];
          _results.push(x);
        }
        return _results;
      })();
      n = orig_len - buf.length;
      return [err, ret, n];
    };

    Pair.prototype.good_for_flags = function() {
      return C.key_flags.certify_keys | C.key_flags.sign_data;
    };

    Pair.generate = function(_arg, cb) {
      var asp, nbits;
      nbits = _arg.nbits, asp = _arg.asp;
      return generate({
        nbits: nbits,
        asp: asp,
        Pair: Pair
      }, cb);
    };

    return Pair;

  })(BaseKeyPair);

  exports.ECDSA = exports.Pair = Pair;

}).call(this);
