// Generated by IcedCoffeeScript 1.7.1-c
(function() {
  var BaseKey, BaseKeyPair, K, NaclEddsa, Pair, Priv, Pub, SRF, TYPE, b2u, box, bufeq_fast, genseed, iced, konst, u2b, __iced_k, __iced_k_noop, _ref, _ref1,
    __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() {};

  box = require('tweetnacl').box;

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

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

  K = konst.kb;

  _ref = require('../util'), genseed = _ref.genseed, bufeq_fast = _ref.bufeq_fast;

  BaseKey = require('../basekeypair').BaseKey;

  BaseKeyPair = require('./base').BaseKeyPair;

  _ref1 = require('./eddsa'), b2u = _ref1.b2u, u2b = _ref1.u2b;

  NaclEddsa = require('./eddsa').Pair;

  TYPE = K.public_key_algorithms.NACL_DH;

  b2u = function(b) {
    return new Uint8Array(b);
  };

  u2b = function(u) {
    return new Buffer(u);
  };

  Pub = (function() {
    Pub.HEADER = new Buffer([K.kid.version, TYPE]);

    Pub.TRAILER = new Buffer([K.kid.trailer]);

    Pub.LEN = Pub.HEADER.length + Pub.TRAILER.length + box.publicKeyLength;

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

    Pub.alloc_kb = function(kid) {
      var err, key;
      err = key = null;
      err = kid.length !== Pub.LEN ? new Error("bad key length") : !bufeq_fast(kid.slice(-1), Pub.TRAILER) ? new Error("bad trailing byte") : !bufeq_fast(kid.slice(0, 2), Pub.HEADER) ? new Error("bad header") : (key = new Pub(kid.slice(2, -1)), null);
      return [err, key];
    };

    Pub.prototype.serialize = function() {
      return this.key;
    };

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

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

    Pub.prototype.encrypt = function(_arg, cb) {
      var nonce, plaintext, res, sender, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      plaintext = _arg.plaintext, sender = _arg.sender;
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/nacl/dh.iced",
            funcname: "Pub.encrypt"
          });
          SRF().random_bytes(box.nonceLength, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return nonce = arguments[0];
              };
            })(),
            lineno: 50
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          res = box(b2u(plaintext), b2u(nonce), b2u(_this.key), b2u(sender.priv.key));
          return cb(null, {
            ciphertext: u2b(res),
            nonce: nonce
          });
        };
      })(this));
    };

    return Pub;

  })();

  Priv = (function() {
    function Priv(key) {
      this.key = key;
    }

    Priv.prototype.alloc = function(raw) {
      var err, key;
      err = key = null;
      if (raw.length !== box.secretKeyLength) {
        err = new Error("Bad secret key length");
      } else {
        key = new Priv(raw);
      }
      return [err, key];
    };

    Priv.prototype.decrypt = function(_arg, cb) {
      var ciphertext, err, nonce, res, sender;
      ciphertext = _arg.ciphertext, nonce = _arg.nonce, sender = _arg.sender;
      err = res = null;
      res = box.open(b2u(ciphertext), b2u(nonce), b2u(sender.pub.key), b2u(this.key));
      if (res === false) {
        err = new Error("decryption failed");
        res = null;
      } else {
        res = u2b(res);
      }
      return cb(err, res);
    };

    return Priv;

  })();

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

    Pair.Pub = Pub;

    Pair.prototype.Pub = Pub;

    Pair.Priv = Priv;

    Pair.prototype.Priv = Priv;

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

    Pair.type = K.public_key_algorithms.NACL_DH;

    Pair.prototype.type = Pair.type;

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

    Pair.klass_name = "DH";

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

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

    Pair.prototype.hash = function() {
      return this.serialize();
    };

    Pair.prototype.encrypt_kb = function(_arg, cb) {
      var plaintext, sender;
      plaintext = _arg.plaintext, sender = _arg.sender;
      return this.pub.encrypt({
        plaintext: plaintext,
        sender: sender
      }, cb);
    };

    Pair.prototype.decrypt_kb = function(_arg, cb) {
      var ciphertext, err, nonce, plaintex, plaintext, sender, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      ciphertext = _arg.ciphertext, nonce = _arg.nonce, sender = _arg.sender;
      err = plaintex = null;
      (function(_this) {
        return (function(__iced_k) {
          if (_this.priv != null) {
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/Users/max/src/keybase/kbpgp/src/nacl/dh.iced",
                funcname: "Pair.decrypt_kb"
              });
              _this.priv.decrypt({
                ciphertext: ciphertext,
                nonce: nonce,
                sender: sender
              }, __iced_deferrals.defer({
                assign_fn: (function() {
                  return function() {
                    err = arguments[0];
                    return plaintext = arguments[1];
                  };
                })(),
                lineno: 118
              }));
              __iced_deferrals._fulfill();
            })(__iced_k);
          } else {
            return __iced_k(err = new Error("no secret key available"));
          }
        });
      })(this)((function(_this) {
        return function() {
          return cb(err, plaintext);
        };
      })(this));
    };

    Pair.subkey_algo = function(flags) {
      if (flags & (C.key_flags.encrypt_comm | C.key_flags.encrypt_storage)) {
        return Pair;
      } else {
        return NaclEddsa;
      }
    };

    Pair.prototype.fulfills_flags = function(flags) {
      var good_for;
      good_for = C.key_flags.encrypt_comm | C.key_flags.encrypt_storage;
      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 cb(new Error("verify_unpad_and_check_hash unsupported"));
    };

    Pair.prototype.pad_and_sign = function(data, _arg, cb) {
      var hasher;
      hasher = _arg.hasher;
      return cb(new Error("pad_and_sign unsupported"));
    };

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

    Pair.parse_sig = function(slice) {
      var err;
      err = new Error("@parse_sig unsupported");
      throw err;
    };

    Pair.read_sig_from_buf = function(buf) {
      var err;
      err = new Error("@read_sig_from_buf unsupported");
      return [err];
    };

    Pair.generate = function(_arg, cb) {
      var arg, err, priv, pub, publicKey, ret, secretKey, seed, server_half, split, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      server_half = _arg.server_half, seed = _arg.seed, split = _arg.split;
      arg = {
        seed: seed,
        split: split,
        len: box.secretKeyLength,
        server_half: server_half
      };
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/nacl/dh.iced",
            funcname: "Pair.generate"
          });
          genseed(arg, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                err = arguments[0];
                server_half = arguments[1].server_half;
                return seed = arguments[1].seed;
              };
            })(),
            lineno: 179
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          var _ref2;
          ret = null;
          if (typeof err === "undefined" || err === null) {
            _ref2 = box.keyPair.fromSecretKey(b2u(seed)), secretKey = _ref2.secretKey, publicKey = _ref2.publicKey;
            pub = new Pub(u2b(publicKey));
            priv = new Priv(u2b(secretKey));
            ret = new Pair({
              pub: pub,
              priv: priv
            });
          }
          return cb(err, ret, server_half);
        };
      })(this));
    };

    return Pair;

  })(BaseKeyPair);

  exports.DH = exports.Pair = Pair;

}).call(this);
