// Generated by IcedCoffeeScript 1.7.1-c
(function() {
  var AES, C, DSA, ECDH, ECDSA, EDDSA, ElGamal, ElGamalSE, KeyMaterial, Packet, Parser, RSA, S, S2K, SHA1, SHA256, SecretKeyMaterial, Signature, bufeq_secure, bufferify, calc_checksum, decrypt, encode, encrypt, iced, katch, make_time_packet, native_rng, packetsigs, symmetric, triplesec, uint_to_buffer, unix_time, util, __iced_k, __iced_k_noop, _ref, _ref1, _ref2, _ref3,
    __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() {};

  C = require('../../const').openpgp;

  triplesec = require('triplesec');

  _ref = triplesec.hash, SHA1 = _ref.SHA1, SHA256 = _ref.SHA256;

  RSA = require('../../rsa').Pair;

  DSA = require('../../dsa').Pair;

  ElGamal = require('../../elgamal').Pair;

  ElGamalSE = require('../../elgamalse').Pair;

  ECDSA = require('../../ecc/ecdsa').Pair;

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

  EDDSA = require('../../ecc/eddsa').Pair;

  AES = triplesec.ciphers.AES;

  native_rng = triplesec.prng.native_rng;

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

  _ref1 = require('../../util'), bufferify = _ref1.bufferify, unix_time = _ref1.unix_time, bufeq_secure = _ref1.bufeq_secure, katch = _ref1.katch, make_time_packet = _ref1.make_time_packet, uint_to_buffer = _ref1.uint_to_buffer;

  _ref2 = require('../cfb'), decrypt = _ref2.decrypt, encrypt = _ref2.encrypt;

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

  S = require('./signature');

  Signature = S.Signature;

  encode = require('../armor').encode;

  _ref3 = require('../s2k'), S2K = _ref3.S2K, SecretKeyMaterial = _ref3.SecretKeyMaterial;

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

  util = require('util');

  packetsigs = require('./packetsigs');

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

    function KeyMaterial(_arg) {
      this.key = _arg.key, this.timestamp = _arg.timestamp, this.passphrase = _arg.passphrase, this.skm = _arg.skm, this.opts = _arg.opts, this.flags = _arg.flags;
      this.opts || (this.opts = {});
      this.flags || (this.flags = 0);
      this._is_duplicate_primary = false;
      KeyMaterial.__super__.constructor.call(this);
    }

    KeyMaterial.prototype._write_private_enc = function(bufs, priv, pp) {
      var c, ct, iv, ivlen, k, ks, plaintext, salt, sha1hash;
      bufs.push(new Buffer([C.s2k_convention.sha1, C.symmetric_key_algorithms.AES256, C.s2k.salt_iter, C.hash_algorithms.SHA256]));
      sha1hash = (new SHA1).bufhash(priv);
      salt = native_rng(8);
      bufs.push(salt);
      c = 96;
      bufs.push(new Buffer([c]));
      ks = AES.keySize;
      k = (new S2K).write(pp, salt, c, ks);
      ivlen = AES.blockSize;
      iv = native_rng(ivlen);
      bufs.push(iv);
      plaintext = Buffer.concat([priv, sha1hash]);
      ct = encrypt({
        block_cipher_class: AES,
        key: k,
        plaintext: plaintext,
        iv: iv
      });
      return bufs.push(ct);
    };

    KeyMaterial.prototype._write_private_clear = function(bufs, priv) {
      return bufs.push(new Buffer([C.s2k_convention.none]), priv, uint_to_buffer(16, calc_checksum(priv)));
    };

    KeyMaterial.prototype._write_public = function(bufs) {
      var pub;
      pub = this.key.serialize();
      return bufs.push(new Buffer([C.versions.keymaterial.V4]), uint_to_buffer(32, this.timestamp), new Buffer([this.key.type]), pub);
    };

    KeyMaterial.prototype._write_dummy = function(bufs) {
      return bufs.push(new Buffer([C.s2k_convention.sha1, C.symmetric_key_algorithms.AES256, C.s2k.gnu, 0x2]), new Buffer("GNU", "utf8"), new Buffer([0x1]));
    };

    KeyMaterial.prototype.add_flags = function(v) {
      return this.flags |= v;
    };

    KeyMaterial.prototype.private_body = function(opts) {
      var bufs, p, pp, priv, ret;
      bufs = [];
      this._write_public(bufs);
      priv = (p = this.key.priv) != null ? p.serialize() : null;
      pp = opts.passphrase || this.passphrase;
      if (priv == null) {
        this._write_dummy(bufs);
      } else if (pp != null) {
        this._write_private_enc(bufs, priv, pp);
      } else {
        this._write_private_clear(bufs, priv);
      }
      ret = Buffer.concat(bufs);
      return ret;
    };

    KeyMaterial.prototype.private_framed = function(opts) {
      var T, body, tag;
      body = this.private_body(opts);
      T = C.packet_tags;
      tag = opts.subkey ? T.secret_subkey : T.secret_key;
      return this.frame_packet(tag, body);
    };

    KeyMaterial.prototype.public_body = function() {
      var bufs;
      bufs = [];
      this._write_public(bufs);
      return Buffer.concat(bufs);
    };

    KeyMaterial.prototype.get_fingerprint = function() {
      var data;
      data = this.public_body();
      return (new SHA1).bufhash(Buffer.concat([new Buffer([C.signatures.key]), uint_to_buffer(16, data.length), data]));
    };

    KeyMaterial.prototype.get_key_id = function() {
      return this.get_fingerprint().slice(12, 20);
    };

    KeyMaterial.prototype.get_short_key_id = function() {
      return this.get_key_id().slice(-4).toString('hex').toUpperCase();
    };

    KeyMaterial.prototype.get_klass = function() {
      return this.key.constructor;
    };

    KeyMaterial.prototype.export_framed = function(opts) {
      if (opts == null) {
        opts = {};
      }
      if (opts["private"]) {
        return this.private_framed(opts);
      } else {
        return this.public_framed(opts);
      }
    };

    KeyMaterial.prototype.public_framed = function(opts) {
      var T, body, tag;
      if (opts == null) {
        opts = {};
      }
      body = this.public_body();
      T = C.packet_tags;
      tag = opts.subkey ? T.public_subkey : T.public_key;
      return this.frame_packet(tag, body);
    };

    KeyMaterial.prototype.to_signature_payload = function() {
      var pk;
      pk = this.public_body();
      return Buffer.concat([new Buffer([C.signatures.key]), uint_to_buffer(16, pk.length), pk]);
    };

    KeyMaterial.prototype.self_sign_key = function(_arg, cb) {
      var err, lifespan, primary, raw_payload, sig, sigs, userid, userids, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      userids = _arg.userids, lifespan = _arg.lifespan, raw_payload = _arg.raw_payload;
      err = null;
      sigs = [];
      primary = true;
      (function(_this) {
        return (function(__iced_k) {
          var _i, _len, _ref4, _results, _while;
          _ref4 = userids;
          _len = _ref4.length;
          _i = 0;
          _results = [];
          _while = function(__iced_k) {
            var _break, _continue, _next;
            _break = function() {
              return __iced_k(_results);
            };
            _continue = function() {
              return iced.trampoline(function() {
                ++_i;
                return _while(__iced_k);
              });
            };
            _next = function(__iced_next_arg) {
              _results.push(__iced_next_arg);
              return _continue();
            };
            if (!(_i < _len)) {
              return _break();
            } else {
              userid = _ref4[_i];
              if (err == null) {
                sig = null;
                (function(__iced_k) {
                  if (_this.key.can_sign() || raw_payload) {
                    (function(__iced_k) {
                      __iced_deferrals = new iced.Deferrals(__iced_k, {
                        parent: ___iced_passed_deferral,
                        filename: "/Users/max/src/keybase/kbpgp/src/openpgp/packet/keymaterial.iced",
                        funcname: "KeyMaterial.self_sign_key"
                      });
                      _this._self_sign_key({
                        userid: userid,
                        lifespan: lifespan,
                        raw_payload: raw_payload,
                        primary: primary
                      }, __iced_deferrals.defer({
                        assign_fn: (function() {
                          return function() {
                            err = arguments[0];
                            return sig = arguments[1];
                          };
                        })(),
                        lineno: 194
                      }));
                      __iced_deferrals._fulfill();
                    })(__iced_k);
                  } else {
                    return __iced_k((sig = userid.get_framed_signature_output()) == null ? err = new Error("Cannot sign key --- don't have a private key, and can't replay") : void 0);
                  }
                })(function() {
                  primary = false;
                  return _next(sigs.push(sig));
                });
              } else {
                return _continue();
              }
            }
          };
          _while(__iced_k);
        });
      })(this)((function(_this) {
        return function() {
          return cb(err, sig);
        };
      })(this));
    };

    KeyMaterial.prototype._self_sign_key = function(_arg, cb) {
      var err, hsp, lifespan, payload, primary, ps, raw_payload, sig, type, userid, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      userid = _arg.userid, lifespan = _arg.lifespan, raw_payload = _arg.raw_payload, primary = _arg.primary;
      payload = Buffer.concat([this.to_signature_payload(), userid.to_signature_payload()]);
      type = C.sig_types.positive;
      hsp = [new S.CreationTime(lifespan.generated), new S.KeyFlags([this.flags]), new S.PreferredSymmetricAlgorithms([C.symmetric_key_algorithms.AES256, C.symmetric_key_algorithms.AES128]), new S.PreferredHashAlgorithms([C.hash_algorithms.SHA512, C.hash_algorithms.SHA256]), new S.Features([C.features.modification_detection]), new S.KeyServerPreferences([C.key_server_preferences.no_modify]), new S.PreferredCompressionAlgorithms([C.compression.zlib, C.compression.zip])];
      if (primary) {
        hsp.push(new S.PrimaryUserId(1));
      }
      if (lifespan.expire_in) {
        hsp.push(new S.KeyExpirationTime(lifespan.expire_in));
      }
      sig = new Signature({
        type: type,
        key: this.key,
        hashed_subpackets: hsp,
        unhashed_subpackets: [new S.Issuer(this.get_key_id())]
      });
      (function(_this) {
        return (function(__iced_k) {
          if (raw_payload) {
            return __iced_k(sig = payload);
          } else {
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/Users/max/src/keybase/kbpgp/src/openpgp/packet/keymaterial.iced",
                funcname: "KeyMaterial._self_sign_key"
              });
              sig.write(payload, __iced_deferrals.defer({
                assign_fn: (function() {
                  return function() {
                    return err = arguments[0];
                  };
                })(),
                lineno: 237
              }));
              __iced_deferrals._fulfill();
            })(function() {
              ps = new packetsigs.SelfSig({
                userid: userid,
                type: type,
                sig: sig,
                options: _this.flags
              });
              userid.push_sig(ps);
              return __iced_k(_this.push_sig(ps));
            });
          }
        });
      })(this)((function(_this) {
        return function() {
          return cb(err, sig);
        };
      })(this));
    };

    KeyMaterial.prototype.sign_subkey = function(_arg, cb) {
      var err, lifespan, sig, subkey, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      subkey = _arg.subkey, lifespan = _arg.lifespan;
      err = sig = null;
      (function(_this) {
        return (function(__iced_k) {
          var _ref4, _ref5;
          if (_this.key.can_sign()) {
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/Users/max/src/keybase/kbpgp/src/openpgp/packet/keymaterial.iced",
                funcname: "KeyMaterial.sign_subkey"
              });
              _this._sign_subkey({
                subkey: subkey,
                lifespan: lifespan
              }, __iced_deferrals.defer({
                assign_fn: (function() {
                  return function() {
                    return err = arguments[0];
                  };
                })(),
                lineno: 250
              }));
              __iced_deferrals._fulfill();
            })(__iced_k);
          } else {
            return __iced_k(!((_ref4 = subkey.get_subkey_binding()) != null ? (_ref5 = _ref4.sig) != null ? _ref5.get_framed_output() : void 0 : void 0) ? err = new Error("Cannot sign with subkey --- don't have private key and can't replay") : void 0);
          }
        });
      })(this)((function(_this) {
        return function() {
          return cb(err);
        };
      })(this));
    };

    KeyMaterial.prototype._sign_subkey = function(_arg, cb) {
      var SKB, err, lifespan, primary_binding, ps, sig, subkey, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      subkey = _arg.subkey, lifespan = _arg.lifespan;
      sig = err = primary_binding = null;
      (function(_this) {
        return (function(__iced_k) {
          if (subkey.can_sign()) {
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/Users/max/src/keybase/kbpgp/src/openpgp/packet/keymaterial.iced",
                funcname: "KeyMaterial._sign_subkey"
              });
              subkey._sign_primary_with_subkey({
                primary: _this,
                lifespan: lifespan
              }, __iced_deferrals.defer({
                assign_fn: (function() {
                  return function() {
                    err = arguments[0];
                    return primary_binding = arguments[1];
                  };
                })(),
                lineno: 262
              }));
              __iced_deferrals._fulfill();
            })(__iced_k);
          } else {
            return __iced_k();
          }
        });
      })(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/openpgp/packet/keymaterial.iced",
                  funcname: "KeyMaterial._sign_subkey"
                });
                _this._sign_subkey_with_primary({
                  subkey: subkey,
                  lifespan: lifespan,
                  primary_binding: primary_binding
                }, __iced_deferrals.defer({
                  assign_fn: (function() {
                    return function() {
                      err = arguments[0];
                      return sig = arguments[1];
                    };
                  })(),
                  lineno: 264
                }));
                __iced_deferrals._fulfill();
              })(__iced_k);
            } else {
              return __iced_k();
            }
          })(function() {
            if (err == null) {
              SKB = packetsigs.SubkeyBinding;
              ps = new SKB({
                primary: _this,
                sig: sig,
                direction: SKB.DOWN
              });
              subkey.push_sig(ps);
            }
            return cb(err);
          });
        };
      })(this));
    };

    KeyMaterial.prototype._sign_primary_with_subkey = function(_arg, cb) {
      var err, lifespan, payload, primary, sig, sig_unframed, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      primary = _arg.primary, lifespan = _arg.lifespan;
      payload = Buffer.concat([primary.to_signature_payload(), this.to_signature_payload()]);
      sig = new Signature({
        type: C.sig_types.primary_binding,
        key: this.key,
        hashed_subpackets: [new S.CreationTime(lifespan.generated)],
        unhashed_subpackets: [new S.Issuer(this.get_key_id())]
      });
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/openpgp/packet/keymaterial.iced",
            funcname: "KeyMaterial._sign_primary_with_subkey"
          });
          sig.write_unframed(payload, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                err = arguments[0];
                return sig_unframed = arguments[1];
              };
            })(),
            lineno: 288
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          return cb(err, sig_unframed);
        };
      })(this));
    };

    KeyMaterial.prototype._sign_subkey_with_primary = function(_arg, cb) {
      var err, lifespan, payload, primary_binding, sig, subkey, unhashed_subpackets, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      subkey = _arg.subkey, lifespan = _arg.lifespan, primary_binding = _arg.primary_binding;
      payload = Buffer.concat([this.to_signature_payload(), subkey.to_signature_payload()]);
      unhashed_subpackets = [new S.Issuer(this.get_key_id())];
      if (primary_binding != null) {
        unhashed_subpackets.push(new S.EmbeddedSignature({
          rawsig: primary_binding
        }));
      }
      sig = new Signature({
        type: C.sig_types.subkey_binding,
        key: this.key,
        hashed_subpackets: [new S.CreationTime(lifespan.generated), new S.KeyExpirationTime(lifespan.expire_in), new S.KeyFlags([subkey.flags])],
        unhashed_subpackets: unhashed_subpackets
      });
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/keybase/kbpgp/src/openpgp/packet/keymaterial.iced",
            funcname: "KeyMaterial._sign_subkey_with_primary"
          });
          sig.write(payload, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return err = arguments[0];
              };
            })(),
            lineno: 312
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          return cb(err, sig);
        };
      })(this));
    };

    KeyMaterial.prototype.merge_private = function(k2) {
      return this.skm = k2.skm;
    };

    KeyMaterial.parse_public_key = function(slice, opts) {
      return (new Parser(slice)).parse_public_key(opts);
    };

    KeyMaterial.parse_private_key = function(slice, opts) {
      return (new Parser(slice)).parse_private_key(opts);
    };

    KeyMaterial.prototype.is_key_material = function() {
      return true;
    };

    KeyMaterial.prototype.is_primary = function() {
      var _ref4;
      return !((_ref4 = this.opts) != null ? _ref4.subkey : void 0);
    };

    KeyMaterial.prototype.is_duplicate_primary = function() {
      return this._is_duplicate_primary;
    };

    KeyMaterial.prototype.set_duplicate_primary = function() {
      return this._is_duplicate_primary = true;
    };

    KeyMaterial.prototype.ekid = function() {
      return this.key.ekid();
    };

    KeyMaterial.prototype.can_sign = function() {
      return this.key.can_sign();
    };

    KeyMaterial.prototype.is_locked = function() {
      return (!this.key.has_private()) && (this.skm != null) && this.skm.is_locked();
    };

    KeyMaterial.prototype.has_private = function() {
      return this.has_unlocked_private() || this.has_locked_private();
    };

    KeyMaterial.prototype.has_locked_private = function() {
      return this.skm && this.skm.has_private();
    };

    KeyMaterial.prototype.has_unlocked_private = function() {
      return this.key.has_private();
    };

    KeyMaterial.prototype.has_secret_key_material = function() {
      return this.skm != null;
    };

    KeyMaterial.prototype.validity_check = function(cb) {
      var err, msg, ___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/openpgp/packet/keymaterial.iced",
            funcname: "KeyMaterial.validity_check"
          });
          _this.key.validity_check(__iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return err = arguments[0];
              };
            })(),
            lineno: 346
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          if (typeof err !== "undefined" && err !== null) {
            msg = "In key " + (_this.get_fingerprint().toString('hex')) + ": " + err.message;
            err = new Error(err);
          }
          return cb(err);
        };
      })(this));
    };

    KeyMaterial.prototype.is_signed_subkey_of = function(primary) {
      return (!this.primary_flag) && this.get_psc().is_signed_subkey_of(primary);
    };

    KeyMaterial.prototype.get_subkey_binding = function() {
      if (this.opts.subkey) {
        return this.get_psc().get_subkey_binding();
      } else {
        return null;
      }
    };

    KeyMaterial.prototype.get_subkey_binding_signature_output = function() {
      var _ref4, _ref5;
      return (_ref4 = this.get_subkey_binding()) != null ? (_ref5 = _ref4.sig) != null ? _ref5.get_framed_output() : void 0 : void 0;
    };

    KeyMaterial.prototype.equal = function(k2) {
      return bufeq_secure(this.ekid(), k2.ekid());
    };

    KeyMaterial.prototype.unlock = function(_arg, cb) {
      var c1, c2, end, err, h1, h2, key, passphrase, pt;
      passphrase = _arg.passphrase;
      if (passphrase != null) {
        passphrase = bufferify(passphrase);
      }
      err = null;
      if (this.skm == null) {
        err = new Error("Cannot unlock secret key -- no material!");
        return cb(err);
      }
      pt = this.skm.s2k_convention === C.s2k_convention.none ? this.skm.payload : this.skm.s2k.type === C.s2k.gnu_dummy ? null : passphrase == null ? (err = new Error("Key was locked, but no passphrase given"), null) : (key = this.skm.s2k.produce_key(passphrase, this.skm.cipher.key_size), decrypt({
        ciphertext: this.skm.payload,
        block_cipher_class: this.skm.cipher.klass,
        iv: this.skm.iv,
        key: key
      }));
      if (pt) {
        switch (this.skm.s2k_convention) {
          case C.s2k_convention.sha1:
            end = pt.length - SHA1.output_size;
            h1 = pt.slice(end);
            pt = pt.slice(0, end);
            h2 = (new SHA1).bufhash(pt);
            if (!bufeq_secure(h1, h2)) {
              err = new Error("bad private key passphrase (hash mismatch)");
            }
            break;
          case C.s2k_convention.checksum:
          case C.s2k_convention.none:
            end = pt.length - 2;
            c1 = pt.readUInt16BE(end);
            pt = pt.slice(0, end);
            c2 = calc_checksum(pt);
            if (c1 !== c2) {
              err = new Error("bad private key passphrase (checksum mismatch)");
            }
        }
        if (err == null) {
          err = this.key.read_priv(pt);
        }
      }
      return cb(err);
    };

    KeyMaterial.prototype.get_all_key_flags = function() {
      return this._psc.get_all_key_flags();
    };

    KeyMaterial.prototype.add_flags = function(v) {
      return this.flags |= v;
    };

    KeyMaterial.prototype.fulfills_flags = function(flags) {
      var akf, ret;
      if (this.is_revoked()) {
        return false;
      }
      akf = this.get_all_key_flags();
      ret = ((akf & flags) === flags) || this.key.fulfills_flags(flags) || (this.is_primary() && (akf === 0) && ((this.key.good_for_flags() & flags) === flags));
      return ret;
    };

    KeyMaterial.prototype.get_signed_userids = function() {
      return this.get_psc().get_signed_userids();
    };

    KeyMaterial.prototype.get_signed_user_attributes = function() {
      return this.get_psc().get_signed_user_attributes();
    };

    KeyMaterial.prototype.is_self_signed = function() {
      return this.get_psc().is_self_signed();
    };

    KeyMaterial.prototype.push_sig = function(packetsig) {
      this.add_flags(packetsig.sig.get_key_flags());
      return KeyMaterial.__super__.push_sig.call(this, packetsig);
    };

    KeyMaterial.prototype.mark_revoked = function(sig) {
      return this.revocation = sig;
    };

    KeyMaterial.prototype.is_revoked = function() {
      return this.revocation != null;
    };

    KeyMaterial.prototype.check_not_expired = function(_arg) {
      var e, err, now, _ref4;
      now = _arg.now;
      err = null;
      if ((e = (_ref4 = this.get_expire_time()) != null ? _ref4.expire_at : void 0) && e < now) {
        err = new Error("PGP key " + (this.get_fingerprint().toString('hex')) + " expired at " + e + " but we checked for time " + now);
      }
      return err;
    };

    KeyMaterial.prototype.get_expire_time = function() {
      var psc;
      if ((psc = this.get_psc()) == null) {
        return null;
      } else if (this.is_primary()) {
        return this._get_expire_time_on_primary();
      } else {
        return this._get_expire_time_on_subkey();
      }
    };

    KeyMaterial.prototype._get_expire_time_on_primary = function() {
      var expire_in, key_generated, list, packetsig, ret, sig, sig_generated, table, uid, uid_expire_in, uid_winner, winner, _i, _len;
      table = this.get_psc().lookup.self_sigs_by_uid;
      winner = null;
      key_generated = this.timestamp;
      for (uid in table) {
        list = table[uid];
        uid_winner = null;
        for (_i = 0, _len = list.length; _i < _len; _i++) {
          packetsig = list[_i];
          if (!((sig = packetsig.sig) != null)) {
            continue;
          }
          expire_in = sig.get_key_expires();
          sig_generated = sig.when_generated();
          if ((uid_winner == null) || uid_winner.sig_generated < sig_generated) {
            uid_winner = {
              expire_in: expire_in,
              sig_generated: sig_generated
            };
          }
        }
        if (uid_winner != null) {
          uid_expire_in = uid_winner.expire_in || 0;
          if ((winner == null) || (uid_expire_in === 0) || ((0 < winner && winner < uid_expire_in))) {
            winner = uid_expire_in;
          }
        }
      }
      ret = {
        generated: this.timestamp,
        expire_at: null,
        expire_in: null
      };
      if (winner) {
        ret.expire_at = this.timestamp + winner;
        ret.expire_in = winner;
      }
      return ret;
    };

    KeyMaterial.prototype._get_expire_time_on_subkey = function() {
      var expire_at, expire_in, generated, list, packetsig, sig, winner, _i, _len;
      list = this.get_psc().lookup.subkey_binding;
      if (!(list != null ? list.length : void 0)) {
        return null;
      }
      winner = null;
      for (_i = 0, _len = list.length; _i < _len; _i++) {
        packetsig = list[_i];
        if (!((packetsig.sig != null) && packetsig.is_down())) {
          continue;
        }
        sig = packetsig.sig;
        expire_in = sig.get_key_expires();
        generated = this.timestamp;
        if (expire_in && generated) {
          expire_at = generated + expire_in;
          if ((winner == null) || ((winner.expire_at != null) && (winner.expire_at < expire_at))) {
            winner = {
              expire_at: expire_at,
              generated: generated,
              expire_in: expire_in
            };
          }
        } else if (((expire_in != null) && expire_in === 0) || (expire_in == null)) {
          winner = {
            generated: generated,
            expire_in: null,
            expire_at: null
          };
        }
      }
      if (winner == null) {
        winner = {
          generated: 0,
          expire_at: null,
          expire_in: null
        };
      }
      return winner;
    };

    return KeyMaterial;

  })(Packet);

  Parser = (function() {
    function Parser(slice) {
      this.slice = slice;
      this.key = null;
    }

    Parser.prototype.parse_public_key_v3 = function() {
      this.timestamp = this.slice.read_uint32();
      this.expiration = this.slice.read_uint16();
      return this.parse_public_key_mpis();
    };

    Parser.prototype.parse_public_key_v4 = function() {
      this.timestamp = this.slice.read_uint32();
      return this.parse_public_key_mpis();
    };

    Parser.prototype.parse_public_key_mpis = function() {
      var A, err, key, klass, len, _ref4;
      this.algorithm = this.slice.read_uint8();
      A = C.public_key_algorithms;
      klass = (function() {
        switch (this.algorithm) {
          case A.RSA:
          case A.RSA_ENCRYPT_ONLY:
          case A.RSA_SIGN_ONLY:
            return RSA;
          case A.DSA:
            return DSA;
          case A.ELGAMAL:
            return ElGamal;
          case A.ELGAMAL_SIGN_AND_ENCRYPT:
            return ElGamalSE;
          case A.ECDSA:
            return ECDSA;
          case A.ECDH:
            return ECDH;
          case A.EDDSA:
            return EDDSA;
          default:
            throw new Error("Unknown key type: " + this.algorithm);
        }
      }).call(this);
      _ref4 = klass.parse(this.slice.peek_rest_to_buffer()), err = _ref4[0], key = _ref4[1], len = _ref4[2];
      if (err != null) {
        throw err;
      }
      this.slice.advance(len);
      return key;
    };

    Parser.prototype._parse_public_key = function() {
      var version;
      switch ((version = this.slice.read_uint8())) {
        case C.versions.keymaterial.V3:
          return this.parse_public_key_v3();
        case C.versions.keymaterial.V4:
          return this.parse_public_key_v4();
        default:
          throw new Error("Unknown public key version: " + version);
      }
    };

    Parser.prototype.parse_public_key = function(opts) {
      var key;
      key = this._parse_public_key();
      return new KeyMaterial({
        key: key,
        timestamp: this.timestamp,
        opts: opts
      });
    };

    Parser.prototype.parse_private_key = function(opts) {
      var encrypted_private_key, iv_len, key, skm, sym_enc_alg, _ref4;
      skm = new SecretKeyMaterial();
      key = this._parse_public_key();
      encrypted_private_key = true;
      sym_enc_alg = null;
      if ((skm.s2k_convention = this.slice.read_uint8()) === C.s2k_convention.none) {
        encrypted_private_key = false;
      } else {
        if ((_ref4 = skm.s2k_convention) === C.s2k_convention.sha1 || _ref4 === C.s2k_convention.checksum) {
          sym_enc_alg = this.slice.read_uint8();
          skm.s2k = (new S2K).read(this.slice);
        } else {
          sym_enc_alg = skm.s2k_convention;
        }
      }
      if ((skm.s2k_convention !== C.s2k_convention.none) && (skm.s2k.type === C.s2k.gnu_dummy)) {
        skm.payload = null;
      } else {
        if (sym_enc_alg) {
          skm.cipher = symmetric.get_cipher(sym_enc_alg);
          iv_len = skm.cipher.klass.blockSize;
          skm.iv = this.slice.read_buffer(iv_len);
        }
        skm.payload = this.slice.consume_rest_to_buffer();
      }
      return new KeyMaterial({
        key: key,
        skm: skm,
        timestamp: this.timestamp,
        opts: opts
      });
    };

    return Parser;

  })();

  exports.KeyMaterial = KeyMaterial;

}).call(this);
