// Generated by IcedCoffeeScript 1.7.1-c
(function() {
  var BaseKey, BaseKeyPair, C, Pair, Priv, Pub, SlicerBuffer, kbnacl, konst, util, _ref,
    __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; };

  kbnacl = require('keybase-nacl');

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

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

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

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

  C = konst.openpgp;

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

    Pub.type = C.public_key_algorithms.EDDSA;

    Pub.prototype.type = Pub.type;

    Pub.OID = new Buffer([0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01]);

    Pub.prototype.OID = Pub.OID;

    Pub.MPI_LENGTH_HEADERS = new Buffer([0x1, 0x7, 0x40]);

    Pub.prototype.MPI_LENGTH_HEADERS = Pub.MPI_LENGTH_HEADERS;

    function Pub(_arg) {
      this.key = _arg.key;
    }

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

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

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

    Pub.prototype.serialize = function() {
      var ret;
      ret = Buffer.concat([new Buffer([this.OID.length]), this.OID, this.MPI_LENGTH_HEADERS, this.key]);
      return ret;
    };

    Pub._alloc = function(raw) {
      var expected, key, l, len, mpi_length_headers, oid, pre, pub, sb;
      sb = new SlicerBuffer(raw);
      pre = sb.rem();
      l = sb.read_uint8();
      oid = sb.read_buffer(l);
      expected = Pub.OID;
      if (!util.bufeq_secure(oid, expected)) {
        new Error("Wrong OID in EdDSA key");
      }
      mpi_length_headers = sb.read_buffer(Pub.MPI_LENGTH_HEADERS.length);
      if (!util.bufeq_secure(mpi_length_headers, Pub.MPI_LENGTH_HEADERS)) {
        new Error("Wrong MPI length headers");
      }
      key = sb.read_buffer(kbnacl.sign.publicKeyLength);
      pub = new Pub({
        key: key
      });
      len = pre - sb.rem();
      return [pub, len];
    };

    Pub.alloc = function(raw) {
      var e, err, len, pub, _ref1;
      pub = len = err = null;
      try {
        _ref1 = Pub._alloc(raw), pub = _ref1[0], len = _ref1[1];
      } catch (_error) {
        e = _error;
        err = e;
      }
      return [err, pub, len];
    };

    Pub.prototype.verify = function(_arg, payload, cb) {
      var err, naclw, r, s, sig, _, _ref1;
      r = _arg[0], s = _arg[1];
      naclw = kbnacl.alloc({
        publicKey: this.key
      });
      sig = Buffer.concat([r, s]);
      _ref1 = naclw.verify({
        payload: payload,
        sig: sig,
        detached: true
      }), err = _ref1[0], _ = _ref1[1];
      return cb(err);
    };

    return Pub;

  })(BaseKey);

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

    Priv.ORDER = [];

    Priv.prototype.ORDER = Priv.ORDER;

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

    Priv.alloc = function(raw, pub) {
      return [new Error("unimplemented")];
    };

    Priv.prototype.sign = function(h, cb) {
      throw new Error("unimplemented");
    };

    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.EDDSA;

    Pair.prototype.type = Pair.type;

    Pair.klass_name = "EDDSA";

    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 hasher;
      hasher = _arg.hasher;
      return cb(new Error("unimplemented"));
    };

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

    Pair.eddsa_value_from_buffer = function(buf) {
      var bits, err, mpi_header_len, ret, totlen, vlen;
      err = ret = null;
      vlen = kbnacl.sign.publicKeyLength;
      mpi_header_len = 2;
      totlen = vlen + mpi_header_len;
      if (buf.length < totlen) {
        err = new Error("need " + len + " bytes per EdDSA value");
      } else if ((bits = buf.readUInt16BE(0)) > 0x100 || bits < (0x100 - 40)) {
        err = new Error("Got an unexpected number of Bits for an EdDSA value: " + bits);
      } else {
        ret = buf.slice(2, totlen);
        buf = buf.slice(totlen);
      }
      return [err, ret, buf];
    };

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

    Pair.alloc = function(klass, raw) {
      var e, err, len, pub, _ref1;
      pub = len = err = null;
      try {
        _ref1 = Pub.alloc(raw), pub = _ref1[0], len = _ref1[1];
      } catch (_error) {
        e = _error;
        err = e;
      }
      return [err, pub, len];
    };

    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 cb(new Error("unimplemented"));
    };

    return Pair;

  })(BaseKeyPair);

  exports.EDDSA = exports.Pair = Pair;

}).call(this);
