// Generated by IcedCoffeeScript 1.7.1-c
(function() {
  var BigInteger, Curve, H, OIDS, OID_LOOKUP, SRF, SlicerBuffer, base, bn, brainpool_p256, brainpool_p384, brainpool_p512, iced, k, nist_p256, nist_p384, nist_p521, uint_to_buffer, v, __iced_k, __iced_k_noop,
    __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() {};

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

  base = require('keybase-ecurve');

  uint_to_buffer = require('../util').uint_to_buffer;

  SlicerBuffer = require('../openpgp/buffer').SlicerBuffer;

  SRF = require('../rand').SRF;

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

  exports.H = H = function(x) {
    return BigInteger.fromHex(x.split(/\s+/).join(''));
  };

  exports.Curve = Curve = (function(_super) {
    __extends(Curve, _super);

    function Curve(_arg) {
      var Gx, Gy, a, b, h, n, p;
      p = _arg.p, a = _arg.a, b = _arg.b, Gx = _arg.Gx, Gy = _arg.Gy, n = _arg.n, h = _arg.h, this.oid = _arg.oid;
      h || (h = BigInteger.ONE);
      Curve.__super__.constructor.call(this, p, a, b, Gx, Gy, n, h);
    }

    Curve.prototype.mkpoint = function(_arg) {
      var x, y;
      x = _arg.x, y = _arg.y;
      return base.Point.fromAffine(this, x, y);
    };

    Curve.prototype.nbits = function() {
      return this.p.bitLength();
    };

    Curve.prototype.mpi_bit_size = function() {
      return 2 * this.mpi_coord_bit_size() + 3;
    };

    Curve.prototype.mpi_coord_byte_size = function() {
      return Math.ceil(this.nbits() / 8);
    };

    Curve.prototype.mpi_coord_bit_size = function() {
      return this.mpi_coord_byte_size() * 8;
    };

    Curve.prototype._mpi_point_from_slicer_buffer = function(sb) {
      var b, n_bits, n_bytes, point, x, y, _ref;
      n_bits = sb.read_uint16();
      if (n_bits !== (b = this.mpi_bit_size())) {
        throw new Error("Need " + b + " bits for this curve; got " + n_bits);
      }
      if (sb.read_uint8() !== 0x4) {
        throw new Error("Can only handle 0x4 prefix for MPI representations");
      }
      n_bytes = this.mpi_coord_byte_size();
      _ref = [BigInteger.fromBuffer(sb.read_buffer(n_bytes)), BigInteger.fromBuffer(sb.read_buffer(n_bytes))], x = _ref[0], y = _ref[1];
      point = this.mkpoint({
        x: x,
        y: y
      });
      if (!this.isOnCurve(point)) {
        throw new Error("Given ECC point isn't on the given curve; data corruption detected.");
      }
      return [null, point];
    };

    Curve.prototype.mpi_point_from_buffer = function(b) {
      return this.mpi_point_from_slicer_buffer(new SlicerBuffer(b));
    };

    Curve.prototype.mpi_point_from_slicer_buffer = function(sb) {
      var e, err, point, _ref;
      err = point = null;
      try {
        _ref = this._mpi_point_from_slicer_buffer(sb), err = _ref[0], point = _ref[1];
      } catch (_error) {
        e = _error;
        err = e;
      }
      return [err, point];
    };

    Curve.prototype.point_to_mpi_buffer_compact = function(p) {
      return p.affineX.toBuffer(this.p.byteLength());
    };

    Curve.prototype.point_to_mpi_buffer = function(p) {
      var ret, sz;
      sz = this.mpi_coord_byte_size();
      ret = Buffer.concat([uint_to_buffer(16, this.mpi_bit_size()), new Buffer([0x4]), p.affineX.toBuffer(sz), p.affineY.toBuffer(sz)]);
      return ret;
    };

    Curve.prototype.random_scalar = function(cb) {
      var k, ___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/ecc/curves.iced",
            funcname: "Curve.random_scalar"
          });
          SRF().random_zn(_this.n.subtract(bn.nbv(2)), __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return k = arguments[0];
              };
            })(),
            lineno: 97
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          k = k.add(bn.BigInteger.ONE);
          return cb(k);
        };
      })(this));
    };

    return Curve;

  })(base.Curve);

  exports.nist_p256 = nist_p256 = function() {
    var Gx, Gy, a, b, n, p;
    p = H("FFFFFFFF 00000001 00000000 00000000 00000000 FFFFFFFF FFFFFFFF FFFFFFFF");
    a = H("FFFFFFFF 00000001 00000000 00000000 00000000 FFFFFFFF FFFFFFFF FFFFFFFC");
    b = H("5AC635D8 AA3A93E7 B3EBBD55 769886BC 651D06B0 CC53B0F6 3BCE3C3E 27D2604B");
    n = H("FFFFFFFF 00000000 FFFFFFFF FFFFFFFF BCE6FAAD A7179E84 F3B9CAC2 FC632551");
    Gx = H("6B17D1F2 E12C4247 F8BCE6E5 63A440F2 77037D81 2DEB33A0 F4A13945 D898C296");
    Gy = H("4FE342E2 FE1A7F9B 8EE7EB4A 7C0F9E16 2BCE3357 6B315ECE CBB64068 37BF51F5");
    return new Curve({
      p: p,
      a: a,
      b: b,
      Gx: Gx,
      Gy: Gy,
      n: n,
      oid: OIDS.nist_p256
    });
  };

  exports.nist_p384 = nist_p384 = function() {
    var Gx, Gy, a, b, n, p;
    p = H('ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe ffffffff 00000000 00000000 ffffffff');
    a = H('ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe ffffffff 00000000 00000000 fffffffc');
    b = H('b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f 5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef');
    n = H('ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 f4372ddf 581a0db2 48b0a77a ecec196a ccc52973');
    Gx = H('aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7');
    Gy = H('3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 0a60b1ce 1d7e819d 7a431d7c 90ea0e5f');
    return new Curve({
      p: p,
      a: a,
      b: b,
      Gx: Gx,
      Gy: Gy,
      n: n,
      oid: OIDS.nist_p384
    });
  };

  exports.nist_p521 = nist_p521 = function() {
    var Gx, Gy, a, b, n, p;
    p = H('000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff');
    a = H('000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffc');
    b = H('00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b 99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd 3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00');
    n = H('000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409');
    Gx = H('000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66');
    Gy = H('00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 3fad0761 353c7086 a272c240 88be9476 9fd16650');
    return new Curve({
      p: p,
      a: a,
      b: b,
      Gx: Gx,
      Gy: Gy,
      n: n,
      oid: OIDS.nist_p521
    });
  };

  exports.brainpool_p256 = brainpool_p256 = function() {
    var Gx, Gy, a, b, n, p;
    p = H('a9fb57db a1eea9bc 3e660a90 9d838d72 6e3bf623 d5262028 2013481d 1f6e5377');
    a = H('7d5a0975 fc2c3057 eef67530 417affe7 fb8055c1 26dc5c6c e94a4b44 f330b5d9');
    b = H('26dc5c6c e94a4b44 f330b5d9 bbd77cbf 95841629 5cf7e1ce 6bccdc18 ff8c07b6');
    n = H('a9fb57db a1eea9bc 3e660a90 9d838d71 8c397aa3 b561a6f7 901e0e82 974856a7');
    Gx = H('8bd2aeb9 cb7e57cb 2c4b482f fc81b7af b9de27e1 e3bd23c2 3a4453bd 9ace3262');
    Gy = H('547ef835 c3dac4fd 97f8461a 14611dc9 c2774513 2ded8e54 5c1d54c7 2f046997');
    return new Curve({
      p: p,
      a: a,
      b: b,
      Gx: Gx,
      Gy: Gy,
      n: n,
      oid: OIDS.brainpool_p256
    });
  };

  exports.brainpool_p384 = brainpool_p384 = function() {
    var Gx, Gy, a, b, n, p;
    p = H('8cb91e82 a3386d28 0f5d6f7e 50e641df 152f7109 ed5456b4 12b1da19 7fb71123 acd3a729 901d1a71 87470013 3107ec53');
    a = H('7bc382c6 3d8c150c 3c72080a ce05afa0 c2bea28e 4fb22787 139165ef ba91f90f 8aa5814a 503ad4eb 04a8c7dd 22ce2826');
    b = H('04a8c7dd 22ce2826 8b39b554 16f0447c 2fb77de1 07dcd2a6 2e880ea5 3eeb62d5 7cb43902 95dbc994 3ab78696 fa504c11');
    n = H('8cb91e82 a3386d28 0f5d6f7e 50e641df 152f7109 ed5456b3 1f166e6c ac0425a7 cf3ab6af 6b7fc310 3b883202 e9046565');
    Gx = H('1d1c64f0 68cf45ff a2a63a81 b7c13f6b 8847a3e7 7ef14fe3 db7fcafe 0cbd10e8 e826e034 36d646aa ef87b2e2 47d4af1e');
    Gy = H('8abe1d75 20f9c2a4 5cb1eb8e 95cfd552 62b70b29 feec5864 e19c054f f9912928 0e464621 77918111 42820341 263c5315');
    return new Curve({
      p: p,
      a: a,
      b: b,
      Gx: Gx,
      Gy: Gy,
      n: n,
      oid: OIDS.brainpool_p384
    });
  };

  exports.brainpool_p512 = brainpool_p512 = function() {
    var Gx, Gy, a, b, n, p;
    p = H('aadd9db8 dbe9c48b 3fd4e6ae 33c9fc07 cb308db3 b3c9d20e d6639cca 70330871 7d4d9b00 9bc66842 aecda12a e6a380e6 2881ff2f 2d82c685 28aa6056 583a48f3');
    a = H('7830a331 8b603b89 e2327145 ac234cc5 94cbdd8d 3df91610 a83441ca ea9863bc 2ded5d5a a8253aa1 0a2ef1c9 8b9ac8b5 7f1117a7 2bf2c7b9 e7c1ac4d 77fc94ca');
    b = H('3df91610 a83441ca ea9863bc 2ded5d5a a8253aa1 0a2ef1c9 8b9ac8b5 7f1117a7 2bf2c7b9 e7c1ac4d 77fc94ca dc083e67 984050b7 5ebae5dd 2809bd63 8016f723');
    n = H('aadd9db8 dbe9c48b 3fd4e6ae 33c9fc07 cb308db3 b3c9d20e d6639cca 70330870 553e5c41 4ca92619 41866119 7fac1047 1db1d381 085ddadd b5879682 9ca90069');
    Gx = H('81aee4bd d82ed964 5a21322e 9c4c6a93 85ed9f70 b5d916c1 b43b62ee f4d0098e ff3b1f78 e2d0d48d 50d1687b 93b97d5f 7c6d5047 406a5e68 8b352209 bcb9f822');
    Gy = H('7dde385d 566332ec c0eabfa9 cf7822fd f209f700 24a57b1a a000c55b 881f8111 b2dcde49 4a5f485e 5bca4bd8 8a2763ae d1ca2b2f a8f05406 78cd1e0f 3ad80892');
    return new Curve({
      p: p,
      a: a,
      b: b,
      Gx: Gx,
      Gy: Gy,
      n: n,
      oid: OIDS.brainpool_p512
    });
  };

  OIDS = {
    nist_p256: new Buffer([0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]),
    nist_p384: new Buffer([0x2b, 0x81, 0x04, 0x00, 0x22]),
    nist_p521: new Buffer([0x2b, 0x81, 0x04, 0x00, 0x23]),
    brainpool_p256: new Buffer([0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07]),
    brainpool_p384: new Buffer([0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B]),
    brainpool_p512: new Buffer([0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D])
  };

  OID_LOOKUP = {};

  for (k in OIDS) {
    v = OIDS[k];
    OID_LOOKUP[v.toString('hex')] = exports[k];
  }

  exports.alloc_by_oid = function(oid) {
    var curve, err, f;
    if (Buffer.isBuffer(oid)) {
      oid = oid.toString('hex');
    }
    err = curve = null;
    if ((f = OID_LOOKUP[oid.toLowerCase()]) != null) {
      curve = f();
    } else {
      err = new Error("Unknown curve OID: " + oid);
    }
    return [err, curve];
  };

  exports.alloc_by_nbits = function(nbits) {
    var err, f, ret;
    ret = err = null;
    nbits || (nbits = 256);
    f = (function() {
      switch (nbits) {
        case 256:
          return nist_p256;
        case 384:
          return nist_p384;
        case 521:
          return nist_p521;
        default:
          return null;
      }
    })();
    if (f != null) {
      ret = f();
    } else {
      err = new Error("No curve for " + nbits + " bits");
    }
    return [err, ret];
  };

}).call(this);
