// Generated by IcedCoffeeScript 1.7.1-c
(function() {
  var C, CreationTime, EmbeddedSignature, Experimental, ExpirationTime, Exportable, Features, Issuer, KeyExpirationTime, KeyFlags, KeyServerPreferences, NotationData, Packet, Parser, PolicyURI, Preference, PreferredCompressionAlgorithms, PreferredHashAlgorithms, PreferredKeyServer, PreferredSymmetricAlgorithms, PrimaryUserId, ReasonForRevocation, RegularExpression, Revocable, RevocationKey, S, SHA1, SHA512, Signature, SignatureTarget, Signature_v2, Signature_v2_or_v3, Signature_v3, SignersUserID, SlicerBuffer, SubPacket, Time, Trust, alloc_or_throw, assert, asymmetric, encode_length, iced, make_esc, make_time_packet, packetsigs, uint_to_buffer, unix_time, util, __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() {};

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

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

  S = C.sig_subpacket;

  _ref = require('../util'), encode_length = _ref.encode_length, make_time_packet = _ref.make_time_packet;

  _ref1 = require('../../util'), unix_time = _ref1.unix_time, uint_to_buffer = _ref1.uint_to_buffer;

  _ref2 = require('../../hash'), alloc_or_throw = _ref2.alloc_or_throw, SHA512 = _ref2.SHA512, SHA1 = _ref2.SHA1;

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

  util = require('util');

  packetsigs = require('./packetsigs');

  assert = require('assert');

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

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

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

    function Signature_v2_or_v3(_arg) {
      this.key = _arg.key, this.hasher = _arg.hasher, this.key_id = _arg.key_id, this.sig_data = _arg.sig_data, this.public_key_class = _arg.public_key_class, this.signed_hash_value_hash = _arg.signed_hash_value_hash, this.time = _arg.time, this.sig = _arg.sig, this.type = _arg.type, this.version = _arg.version;
      if (this.hasher == null) {
        this.hasher = SHA512;
      }
      this._framed_output = null;
    }

    Signature_v2_or_v3.prototype.is_signature = function() {
      return true;
    };

    Signature_v2_or_v3.prototype.get_key_id = function() {
      return this.key_id;
    };

    Signature_v2_or_v3.prototype.get_key_flags = function() {
      return 0;
    };

    Signature_v2_or_v3.prototype.get_key_expires = function() {
      return 0;
    };

    Signature_v2_or_v3.prototype.get_issuer_key_id = function() {
      return this.key_id;
    };

    Signature_v2_or_v3.prototype.when_generated = function() {
      return this.time;
    };

    Signature_v2_or_v3.prototype.time_of_primary_uid_sig = function() {
      return null;
    };

    Signature_v2_or_v3.prototype.gen_prefix = function() {
      return Buffer.concat([new Buffer([C.versions.signature.V3, this.type], uint_to_buffer(32, this.time), this.key_id, new Buffer([this.key.type, this.hasher.type]))]);
    };

    Signature_v2_or_v3.prototype.prepare_payload = function(data_packets) {
      var bufs, dp;
      bufs = (function() {
        var _i, _len, _results;
        _results = [];
        for (_i = 0, _len = data_packets.length; _i < _len; _i++) {
          dp = data_packets[_i];
          _results.push(dp.to_signature_payload());
        }
        return _results;
      })();
      bufs.push(new Buffer([this.type]), uint_to_buffer(32, this.time));
      return Buffer.concat(bufs);
    };

    Signature_v2_or_v3.prototype.verify = function(data_packets, cb) {
      var SKB, T, b, d, err, hash, payload, s, v, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      T = C.sig_types;
      SKB = packetsigs.SubkeyBinding;
      if (this.type === T.subkey_binding) {
        data_packets = [this.primary].concat(data_packets);
      }
      payload = this.prepare_payload(data_packets);
      hash = this.hasher(payload);
      s = new SlicerBuffer(hash);
      v = s.read_uint16();
      (function(_this) {
        return (function(__iced_k) {
          if (v !== (b = _this.signed_hash_value_hash)) {
            return __iced_k(err = new Error("quick hash check failed: " + v + " != " + b));
          } else {
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/Users/max/src/keybase/kbpgp/src/openpgp/packet/signature.iced",
                funcname: "Signature_v2_or_v3.verify"
              });
              _this.key.verify_unpad_and_check_hash({
                hash: hash,
                hasher: _this.hasher,
                sig: _this.sig
              }, __iced_deferrals.defer({
                assign_fn: (function() {
                  return function() {
                    return err = arguments[0];
                  };
                })(),
                lineno: 85
              }));
              __iced_deferrals._fulfill();
            })(function() {
              var _i, _j, _len, _len1, _ref3, _ref4;
              if (err != null) {

              } else if ((_ref3 = _this.type) === T.binary_doc || _ref3 === T.canonical_text) {
                for (_i = 0, _len = data_packets.length; _i < _len; _i++) {
                  d = data_packets[_i];
                  d.push_sig(new packetsigs.Data({
                    sig: _this
                  }));
                }
              } else if ((_ref4 = _this.type) === T.subkey_binding) {
                for (_j = 0, _len1 = data_packets.length; _j < _len1; _j++) {
                  d = data_packets[_j];
                  d.push_sig(new SKB({
                    primary: _this.primary,
                    sig: _this,
                    direction: SKB.DOWN
                  }));
                }
              }
              return __iced_k();
            });
          }
        });
      })(this)((function(_this) {
        return function() {
          return cb(err);
        };
      })(this));
    };

    return Signature_v2_or_v3;

  })(Packet);

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

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

    return Signature_v2;

  })(Signature_v2_or_v3);

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

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

    return Signature_v3;

  })(Signature_v2_or_v3);

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

    function Signature(_arg) {
      this.key = _arg.key, this.hasher = _arg.hasher, this.key_id = _arg.key_id, this.sig_data = _arg.sig_data, this.public_key_class = _arg.public_key_class, this.signed_hash_value_hash = _arg.signed_hash_value_hash, this.hashed_subpackets = _arg.hashed_subpackets, this.time = _arg.time, this.sig = _arg.sig, this.type = _arg.type, this.unhashed_subpackets = _arg.unhashed_subpackets, this.version = _arg.version;
      if (this.hasher == null) {
        this.hasher = SHA512;
      }
      if (this.hashed_subpackets == null) {
        this.hashed_subpackets = [];
      }
      if (this.unhashed_subpackets == null) {
        this.unhashed_subpackets = [];
      }
      this.subpacket_index = this._make_subpacket_index();
      this._framed_output = null;
    }

    Signature.prototype.get_key_id = function() {
      var _ref3;
      if (this.key_id) {
        return this.key_id;
      } else {
        return (_ref3 = this.subpacket_index.all[S.issuer]) != null ? _ref3.id : void 0;
      }
    };

    Signature.prototype._make_subpacket_index = function() {
      var p, ret, _i, _j, _len, _len1, _ref3, _ref4;
      ret = {
        hashed: {},
        unhashed: {},
        all: {}
      };
      _ref3 = this.hashed_subpackets;
      for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
        p = _ref3[_i];
        ret.hashed[p.type] = p;
        ret.all[p.type] = p;
      }
      _ref4 = this.unhashed_subpackets;
      for (_j = 0, _len1 = _ref4.length; _j < _len1; _j++) {
        p = _ref4[_j];
        ret.unhashed[p.type] = p;
        ret.all[p.type] = p;
      }
      return ret;
    };

    Signature.prototype.prepare_payload = function(data) {
      var flatsp, hvalue, payload, prefix, s, trailer;
      flatsp = Buffer.concat((function() {
        var _i, _len, _ref3, _results;
        _ref3 = this.hashed_subpackets;
        _results = [];
        for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
          s = _ref3[_i];
          _results.push(s.to_buffer());
        }
        return _results;
      }).call(this));
      prefix = Buffer.concat([new Buffer([C.versions.signature.V4, this.type, this.key.type, this.hasher.type]), uint_to_buffer(16, flatsp.length), flatsp]);
      trailer = Buffer.concat([new Buffer([C.versions.signature.V4, 0xff]), uint_to_buffer(32, prefix.length)]);
      payload = Buffer.concat([data, prefix, trailer]);
      hvalue = this.hasher(payload);
      return {
        prefix: prefix,
        payload: payload,
        hvalue: hvalue
      };
    };

    Signature.prototype.write_unframed = function(data, cb) {
      var esc, hvalue, payload, prefix, result2, results, s, sig, uhsp, ___iced_passed_deferral, __iced_deferrals, __iced_k, _ref3;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      esc = make_esc(cb, "write_unframed");
      uhsp = Buffer.concat((function() {
        var _i, _len, _ref3, _results;
        _ref3 = this.unhashed_subpackets;
        _results = [];
        for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
          s = _ref3[_i];
          _results.push(s.to_buffer());
        }
        return _results;
      }).call(this));
      _ref3 = this.prepare_payload(data), prefix = _ref3.prefix, payload = _ref3.payload, hvalue = _ref3.hvalue;
      (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/signature.iced",
            funcname: "Signature.write_unframed"
          });
          _this.key.pad_and_sign(payload, {
            hasher: _this.hasher
          }, esc(__iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return sig = arguments[0];
              };
            })(),
            lineno: 167
          })));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          result2 = Buffer.concat([uint_to_buffer(16, uhsp.length), uhsp, new Buffer([hvalue.readUInt8(0), hvalue.readUInt8(1)]), sig]);
          results = Buffer.concat([prefix, result2]);
          return cb(null, results);
        };
      })(this));
    };

    Signature.prototype.write = function(data, cb) {
      var err, ret, unframed, ___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/signature.iced",
            funcname: "Signature.write"
          });
          _this.write_unframed(data, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                err = arguments[0];
                return unframed = arguments[1];
              };
            })(),
            lineno: 180
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          if (typeof err === "undefined" || err === null) {
            _this._framed_output = ret = _this.frame_packet(C.packet_tags.signature, unframed);
          }
          return cb(err, ret);
        };
      })(this));
    };

    Signature.prototype.get_framed_output = function() {
      return this._framed_output || this.replay();
    };

    Signature.parse = function(slice) {
      return (new Parser(slice)).parse();
    };

    Signature.prototype.extract_key = function(data_packets) {
      var p, _i, _len, _results;
      _results = [];
      for (_i = 0, _len = data_packets.length; _i < _len; _i++) {
        p = data_packets[_i];
        if (p.key != null) {
          this.key = p.key;
          break;
        } else {
          _results.push(void 0);
        }
      }
      return _results;
    };

    Signature.prototype.verify = function(data_packets, cb, opts) {
      var err, p, s, subkey, ___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/signature.iced",
            funcname: "Signature.verify"
          });
          _this._verify(data_packets, __iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return err = arguments[0];
              };
            })(),
            lineno: 209
          }), opts);
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          (function(__iced_k) {
            var _i, _len, _ref3, _results, _while;
            _ref3 = _this.unhashed_subpackets;
            _len = _ref3.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 {
                p = _ref3[_i];
                if ((typeof err === "undefined" || err === null) && ((s = p.to_sig()) != null)) {
                  (function(__iced_k) {
                    if (s.type !== C.sig_types.primary_binding) {
                      return __iced_k(err = new Error("unknown subpacket signature type: " + s.type));
                    } else {
                      (function(__iced_k) {
                        if (data_packets.length !== 1) {
                          return __iced_k(err = new Error("Needed 1 data packet for a primary_binding signature"));
                        } else {
                          subkey = data_packets[0];
                          s.primary = _this.primary;
                          s.key = subkey.key;
                          (function(__iced_k) {
                            __iced_deferrals = new iced.Deferrals(__iced_k, {
                              parent: ___iced_passed_deferral,
                              filename: "/Users/max/src/keybase/kbpgp/src/openpgp/packet/signature.iced",
                              funcname: "Signature.verify"
                            });
                            s._verify([subkey], __iced_deferrals.defer({
                              assign_fn: (function() {
                                return function() {
                                  return err = arguments[0];
                                };
                              })(),
                              lineno: 219
                            }), opts);
                            __iced_deferrals._fulfill();
                          })(__iced_k);
                        }
                      })(__iced_k);
                    }
                  })(_next);
                } else {
                  return _continue();
                }
              }
            };
            _while(__iced_k);
          })(function() {
            return cb(err);
          });
        };
      })(this));
    };

    Signature.prototype._verify = function(data_packets, cb, opts) {
      var SKB, T, buffers, d, data, dp, err, hvalue, key_expiration, n, packets, payload, ps, sig, sig_expiration, subkey, user_attribute, userid, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      err = null;
      T = C.sig_types;
      subkey = null;
      this.data_packets = (function() {
        switch (this.type) {
          case T.binary_doc:
          case T.canonical_text:
            return data_packets;
          case T.issuer:
          case T.personal:
          case T.casual:
          case T.positive:
          case T.certificate_revocation:
            if ((n = data_packets.length) !== 1) {
              err = new Error("Only expecting one UserID-style packet in a self-sig (got " + n + ")");
              return [];
            } else {
              return [this.primary].concat(data_packets);
            }
            break;
          case T.subkey_binding:
          case T.primary_binding:
          case T.subkey_revocation:
            packets = [];
            if (data_packets.length !== 1) {
              err = new Error("Wrong number of data packets; expected only 1");
            } else if (this.primary == null) {
              err = new Error("Need a primary key for subkey signature");
            } else {
              subkey = data_packets[0];
              packets = [this.primary, subkey];
            }
            return packets;
          case T.direct:
            return [this.primary].concat(data_packets);
          default:
            err = new Error("cannot verify sigtype " + this.type);
            return [];
        }
      }).call(this);
      (function(_this) {
        return (function(__iced_k) {
          var _ref3;
          if (err == null) {
            buffers = (function() {
              var _i, _len, _ref3, _results;
              _ref3 = this.data_packets;
              _results = [];
              for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
                dp = _ref3[_i];
                _results.push(dp.to_signature_payload());
              }
              return _results;
            }).call(_this);
            data = Buffer.concat(buffers);
            _ref3 = _this.prepare_payload(data), payload = _ref3.payload, hvalue = _ref3.hvalue;
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/Users/max/src/keybase/kbpgp/src/openpgp/packet/signature.iced",
                funcname: "Signature._verify"
              });
              _this.key.verify_unpad_and_check_hash({
                sig: _this.sig,
                hash: hvalue,
                hasher: _this.hasher
              }, __iced_deferrals.defer({
                assign_fn: (function() {
                  return function() {
                    return err = arguments[0];
                  };
                })(),
                lineno: 269
              }));
              __iced_deferrals._fulfill();
            })(__iced_k);
          } else {
            return __iced_k();
          }
        });
      })(this)((function(_this) {
        return function() {
          var _i, _len, _ref3, _ref4;
          if ((err == null) && (_this.key_manager != null)) {
            err = _this.key_manager.pgp_check_not_expired({
              subkey_material: _this.subkey_material,
              now: opts != null ? opts.now : void 0
            });
          }
          if (err == null) {
            opts || (opts = {});
            opts.subkey = subkey;
            _ref3 = _this._check_key_sig_expiration(opts), err = _ref3[0], key_expiration = _ref3[1], sig_expiration = _ref3[2];
            opts.subkey = null;
          }
          sig = _this;
          if (err == null) {
            SKB = packetsigs.SubkeyBinding;
            switch (_this.type) {
              case T.binary_doc:
              case T.canonical_text:
                _ref4 = _this.data_packets;
                for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
                  d = _ref4[_i];
                  d.push_sig(new packetsigs.Data({
                    sig: sig
                  }));
                }
                break;
              case T.issuer:
              case T.personal:
              case T.casual:
              case T.positive:
                ps = null;
                if ((userid = _this.data_packets[1].to_userid()) != null) {
                  ps = new packetsigs.SelfSig({
                    type: _this.type,
                    userid: userid,
                    sig: sig
                  });
                  userid.push_sig(ps);
                } else if ((user_attribute = _this.data_packets[1].to_user_attribute()) != null) {
                  ps = new packetsigs.SelfSig({
                    type: _this.type,
                    user_attribute: user_attribute,
                    sig: sig,
                    key_expiration: key_expiration,
                    sig_expiration: sig_expiration
                  });
                  user_attribute.push_sig(ps);
                }
                if (ps) {
                  _this.primary.push_sig(ps);
                }
                break;
              case T.subkey_binding:
                subkey.push_sig(new SKB({
                  primary: _this.primary,
                  sig: sig,
                  direction: SKB.DOWN,
                  key_expiration: key_expiration,
                  sig_expiration: sig_expiration
                }));
                break;
              case T.primary_binding:
                subkey.push_sig(new SKB({
                  primary: _this.primary,
                  sig: sig,
                  direction: SKB.UP,
                  key_expiration: key_expiration,
                  sig_expiration: sig_expiration
                }));
                break;
              case T.subkey_revocation:
                subkey.mark_revoked(sig);
            }
          }
          return cb(err);
        };
      })(this));
    };

    Signature.prototype.is_signature = function() {
      return true;
    };

    Signature.prototype.when_generated = function() {
      var _ref3;
      return (_ref3 = this.subpacket_index.hashed[S.creation_time]) != null ? _ref3.time : void 0;
    };

    Signature.prototype.get_key_expires = function() {
      var _ref3;
      return (_ref3 = this.subpacket_index.hashed[S.key_expiration_time]) != null ? _ref3.time : void 0;
    };

    Signature.prototype.get_sig_expires = function() {
      var _ref3;
      return (_ref3 = this.subpacket_index.hashed[S.expiration_time]) != null ? _ref3.time : void 0;
    };

    Signature.prototype.time_primary_pair = function() {
      var T, _ref3, _ref4;
      T = C.sig_types;
      if ((_ref3 = this.type) === T.issuer || _ref3 === T.personal || _ref3 === T.casual || _ref3 === T.positive) {
        return [this.when_generated(), !!((_ref4 = this.subpacket_index.hashed[S.primary_user_id]) != null ? _ref4.flag : void 0)];
      } else {
        return null;
      }
    };

    Signature.prototype._check_key_sig_expiration = function(opts) {
      var T, err, key_creation, key_expiration, key_expiration_packet, n, now, sig_creation_packet, sig_expiration, sig_expiration_packet, _ref3;
      err = null;
      T = C.sig_types;
      key_expiration = 0;
      sig_expiration = 0;
      if ((_ref3 = this.type) === T.issuer || _ref3 === T.personal || _ref3 === T.casual || _ref3 === T.positive || _ref3 === T.subkey_binding || _ref3 === T.primary_binding) {
        key_creation = (opts.subkey || this.primary).timestamp;
        key_expiration_packet = this.subpacket_index.hashed[S.key_expiration_time];
        sig_creation_packet = this.subpacket_index.hashed[S.creation_time];
        sig_expiration_packet = this.subpacket_index.hashed[S.sig_expiration_time];
        now = (n = opts != null ? opts.now : void 0) != null ? n : unix_time();
        if ((key_creation != null) && (key_expiration_packet != null ? key_expiration_packet.time : void 0)) {
          key_expiration = key_creation + key_expiration_packet.time;
        }
        if ((sig_creation_packet != null) && (sig_expiration_packet != null ? sig_expiration_packet.time : void 0)) {
          sig_expiration = sig_creation_packet.time + sig_expiration_packet.time;
        }
        if (key_expiration && !opts.time_travel && now > key_expiration) {
          err = new Error("Key expired " + (now - key_expiration) + "s ago");
        }
        if (sig_expiration && !opts.time_travel && now > sig_expiration) {
          err = new Error("Sig expired " + (now - key_expiration) + "s ago");
        }
      }
      return [err, key_expiration, sig_expiration];
    };

    Signature.prototype.get_key_flags = function() {
      var _ref3, _ref4, _ref5;
      return ((_ref3 = this.subpacket_index) != null ? (_ref4 = _ref3.hashed) != null ? (_ref5 = _ref4[C.sig_subpacket.key_flags]) != null ? _ref5.all_flags() : void 0 : void 0 : void 0) || 0;
    };

    Signature.prototype.get_issuer_key_id = function() {
      var _ref3, _ref4;
      return (_ref3 = this.subpacket_index) != null ? (_ref4 = _ref3.all[C.sig_subpacket.issuer]) != null ? _ref4.id : void 0 : void 0;
    };

    return Signature;

  })(Packet);

  SubPacket = (function() {
    function SubPacket(type) {
      this.type = type;
      this.critical = false;
      this.five_byte_len = false;
    }

    SubPacket.prototype.set_opts = function(d) {
      var k, v;
      for (k in d) {
        v = d[k];
        this[k] = v;
      }
      return true;
    };

    SubPacket.prototype.to_buffer = function() {
      var inner;
      inner = this._v_to_buffer();
      return Buffer.concat([encode_length(inner.length + 1, this.five_byte_len), uint_to_buffer(8, this.type | (this.critical ? 0x80 : 0x00)), inner]);
    };

    SubPacket.prototype.to_sig = function() {
      return null;
    };

    SubPacket.prototype.export_to_option = function() {
      return null;
    };

    return SubPacket;

  })();

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

    function Experimental(buf, type) {
      this.buf = buf;
      this.type = type;
    }

    Experimental.parse = function(slice, type) {
      return new Experimental(slice.consume_rest_to_buffer(), type);
    };

    Experimental.prototype._v_to_buffer = function() {
      return this.buf;
    };

    return Experimental;

  })(SubPacket);

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

    function Time(type, time) {
      this.time = time;
      this.never_expires = this.time === 0;
      Time.__super__.constructor.call(this, type);
    }

    Time.parse = function(slice, klass) {
      return new klass(slice.read_uint32());
    };

    Time.prototype._v_to_buffer = function() {
      return uint_to_buffer(32, this.time);
    };

    return Time;

  })(SubPacket);

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

    function Preference(type, v) {
      var e, _i, _len, _ref3;
      this.v = v;
      Preference.__super__.constructor.call(this, type);
      _ref3 = this.v;
      for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
        e = _ref3[_i];
        assert(e != null);
      }
    }

    Preference.parse = function(slice, klass) {
      var c, v;
      v = (function() {
        var _i, _len, _ref3, _results;
        _ref3 = slice.consume_rest_to_buffer();
        _results = [];
        for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
          c = _ref3[_i];
          _results.push(c);
        }
        return _results;
      })();
      return new klass(v);
    };

    Preference.prototype._v_to_buffer = function() {
      var e;
      return new Buffer((function() {
        var _i, _len, _ref3, _results;
        _ref3 = this.v;
        _results = [];
        for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
          e = _ref3[_i];
          _results.push(e);
        }
        return _results;
      }).call(this));
    };

    return Preference;

  })(SubPacket);

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

    function CreationTime(t) {
      CreationTime.__super__.constructor.call(this, S.creation_time, t);
    }

    CreationTime.parse = function(slice) {
      return Time.parse(slice, CreationTime);
    };

    return CreationTime;

  })(Time);

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

    function ExpirationTime(t) {
      ExpirationTime.__super__.constructor.call(this, S.expiration_time, t);
    }

    ExpirationTime.parse = function(slice) {
      return Time.parse(slice, ExpirationTime);
    };

    return ExpirationTime;

  })(Time);

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

    function Exportable(flag) {
      this.flag = flag;
      Exportable.__super__.constructor.call(this, S.exportable_certificate);
    }

    Exportable.parse = function(slice) {
      return new Exportable(slice.read_uint8());
    };

    Exportable.prototype._v_to_buffer = function() {
      return uint_to_buffer(8, this.flag);
    };

    return Exportable;

  })(SubPacket);

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

    function Trust(level, amount) {
      this.level = level;
      this.amount = amount;
      Trust.__super__.constructor.call(this, S.trust_signature);
    }

    Trust.parse = function(slice) {
      return new Trust(slice.read_uint8(), slice.read_uint8());
    };

    Trust.prototype._v_to_buffer = function() {
      return Buffer.concat([uint_to_buffer(8, this.level), uint_to_buffer(8, this.amount)]);
    };

    return Trust;

  })(SubPacket);

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

    function RegularExpression(re) {
      this.re = re;
      RegularExpression.__super__.constructor.call(this, S.regular_expression);
    }

    RegularExpression.parse = function(slice) {
      var ret;
      ret = new RegularExpression(slice.consume_rest_to_buffer().toString('utf8'));
      return ret;
    };

    RegularExpression.prototype._v_to_buffer = function() {
      return new Buffer(this.re, 'utf8');
    };

    return RegularExpression;

  })(SubPacket);

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

    function Revocable(flag) {
      this.flag = flag;
      Revocable.__super__.constructor.call(this, S.revocable);
    }

    Revocable.parse = function(slice) {
      return new Revocable(slice.read_uint8());
    };

    Revocable.prototype._v_to_buffer = function() {
      return uint_to_buffer(8, this.flag);
    };

    return Revocable;

  })(SubPacket);

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

    function KeyExpirationTime(t) {
      KeyExpirationTime.__super__.constructor.call(this, S.key_expiration_time, t);
    }

    KeyExpirationTime.parse = function(slice) {
      return Time.parse(slice, KeyExpirationTime);
    };

    return KeyExpirationTime;

  })(Time);

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

    function PreferredSymmetricAlgorithms(v) {
      PreferredSymmetricAlgorithms.__super__.constructor.call(this, S.preferred_symmetric_algorithms, v);
    }

    PreferredSymmetricAlgorithms.parse = function(slice) {
      return Preference.parse(slice, PreferredSymmetricAlgorithms);
    };

    return PreferredSymmetricAlgorithms;

  })(Preference);

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

    function RevocationKey(key_class, alg, fingerprint) {
      this.key_class = key_class;
      this.alg = alg;
      this.fingerprint = fingerprint;
      RevocationKey.__super__.constructor.call(this, S.revocation_key);
    }

    RevocationKey.parse = function(slice) {
      var fp, ka, kc;
      kc = slice.read_uint8();
      ka = slice.read_uint8();
      fp = slice.read_buffer(SHA1.output_length);
      return new RevocationKey(kc, ka, fp);
    };

    RevocationKey.prototype._v_to_buffer = function() {
      return Buffer.concat([uint_to_buffer(8, this.key_class), uint_to_buffer(8, this.alg), new Buffer(this.fingerprint)]);
    };

    return RevocationKey;

  })(SubPacket);

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

    function Issuer(id) {
      this.id = id;
      Issuer.__super__.constructor.call(this, S.issuer);
    }

    Issuer.parse = function(slice) {
      return new Issuer(slice.read_buffer(8));
    };

    Issuer.prototype._v_to_buffer = function() {
      return new Buffer(this.id);
    };

    return Issuer;

  })(SubPacket);

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

    function NotationData(flags, name, value) {
      this.flags = flags;
      this.name = name;
      this.value = value;
      NotationData.__super__.constructor.call(this, S.notation_data);
    }

    NotationData.parse = function(slice) {
      var flags, name, nl, value, vl;
      flags = slice.read_uint32();
      nl = slice.read_uint16();
      vl = slice.read_uint16();
      name = slice.read_buffer(nl);
      value = slice.read_buffer(vl);
      return new NotationData(flags, name, value);
    };

    NotationData.prototype._v_to_buffer = function() {
      return Buffer.concat([uint_to_buffer(32, this.flags), uint_to_buffer(16, this.name.length), uint_to_buffer(16, this.value.length), new Buffer(this.name), new Buffer(this.value)]);
    };

    return NotationData;

  })(SubPacket);

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

    function PreferredHashAlgorithms(v) {
      PreferredHashAlgorithms.__super__.constructor.call(this, S.preferred_hash_algorithms, v);
    }

    PreferredHashAlgorithms.parse = function(slice) {
      return Preference.parse(slice, PreferredHashAlgorithms);
    };

    return PreferredHashAlgorithms;

  })(Preference);

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

    function PreferredCompressionAlgorithms(v) {
      PreferredCompressionAlgorithms.__super__.constructor.call(this, S.preferred_compression_algorithms, v);
    }

    PreferredCompressionAlgorithms.parse = function(slice) {
      return Preference.parse(slice, PreferredCompressionAlgorithms);
    };

    return PreferredCompressionAlgorithms;

  })(Preference);

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

    function KeyServerPreferences(v) {
      KeyServerPreferences.__super__.constructor.call(this, S.key_server_preferences, v);
    }

    KeyServerPreferences.parse = function(slice) {
      return Preference.parse(slice, KeyServerPreferences);
    };

    return KeyServerPreferences;

  })(Preference);

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

    function Features(v) {
      Features.__super__.constructor.call(this, S.features, v);
    }

    Features.parse = function(slice) {
      return Preference.parse(slice, Features);
    };

    return Features;

  })(Preference);

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

    function PreferredKeyServer(server) {
      this.server = server;
      PreferredKeyServer.__super__.constructor.call(this, S.preferred_key_server);
    }

    PreferredKeyServer.parse = function(slice) {
      return new PreferredKeyServer(slice.consume_rest_to_buffer());
    };

    PreferredKeyServer.prototype._v_to_buffer = function() {
      return this.server;
    };

    return PreferredKeyServer;

  })(SubPacket);

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

    function PrimaryUserId(flag) {
      this.flag = flag;
      PrimaryUserId.__super__.constructor.call(this, S.primary_user_id);
    }

    PrimaryUserId.parse = function(slice) {
      return new PrimaryUserId(slice.read_uint8());
    };

    PrimaryUserId.prototype._v_to_buffer = function() {
      return uint_to_buffer(8, this.flag);
    };

    return PrimaryUserId;

  })(SubPacket);

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

    function PolicyURI(flag) {
      this.flag = flag;
      PolicyURI.__super__.constructor.call(this, S.policy_uri);
    }

    PolicyURI.parse = function(slice) {
      return new PolicyURI(slice.consume_rest_to_buffer());
    };

    PolicyURI.prototype._v_to_buffer = function() {
      return this.flag;
    };

    return PolicyURI;

  })(SubPacket);

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

    function KeyFlags(v) {
      KeyFlags.__super__.constructor.call(this, S.key_flags, v);
    }

    KeyFlags.parse = function(slice) {
      return Preference.parse(slice, KeyFlags);
    };

    KeyFlags.prototype.all_flags = function() {
      var e, ret, _i, _len, _ref3;
      ret = 0;
      _ref3 = this.v;
      for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
        e = _ref3[_i];
        ret |= e;
      }
      return ret;
    };

    return KeyFlags;

  })(Preference);

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

    function SignersUserID(uid) {
      this.uid = uid;
      SignersUserID.__super__.constructor.call(this, S.signers_user_id);
    }

    SignersUserID.parse = function(slice) {
      return new SignersUserID(slice.consume_rest_to_buffer());
    };

    SignersUserID.prototype._v_to_buffer = function() {
      return this.uid;
    };

    return SignersUserID;

  })(SubPacket);

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

    function ReasonForRevocation(flag, reason) {
      this.flag = flag;
      this.reason = reason;
      ReasonForRevocation.__super__.constructor.call(this, S.reason_for_revocation);
    }

    ReasonForRevocation.parse = function(slice) {
      var flag, reason;
      flag = slice.read_uint8();
      reason = slice.consume_rest_to_buffer();
      return new ReasonForRevocation(flag, reason);
    };

    ReasonForRevocation.prototype._v_to_buffer = function() {
      return Buffer.concat([uint_to_buffer(8, this.flag), this.reason]);
    };

    return ReasonForRevocation;

  })(SubPacket);

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

    function SignatureTarget(pub_key_alg, hasher, hval) {
      this.pub_key_alg = pub_key_alg;
      this.hasher = hasher;
      this.hval = hval;
      SignatureTarget.__super__.constructor.call(this, S.signature_target);
    }

    SignatureTarget.parse = function(slice) {
      var hasher, hval, pka;
      pka = slice.read_uint8();
      hasher = alloc_or_throw(slice.read_uint8());
      hval = slice.read_buffer(hasher.output_length);
      return new SignatureTarget(pka, hasher, hval);
    };

    SignatureTarget.prototype._v_to_buffer = function() {
      return Buffer.concat([uint_to_buffer(8, this.pub_key_alg), uint_to_buffer(8, this.hasher.type), this.hval]);
    };

    return SignatureTarget;

  })(SubPacket);

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

    function EmbeddedSignature(_arg) {
      this.sig = _arg.sig, this.rawsig = _arg.rawsig;
      EmbeddedSignature.__super__.constructor.call(this, S.embedded_signature);
    }

    EmbeddedSignature.prototype._v_to_buffer = function() {
      return this.rawsig;
    };

    EmbeddedSignature.prototype.to_sig = function() {
      return this.sig;
    };

    EmbeddedSignature.parse = function(slice) {
      var rawsig, sig;
      rawsig = slice.peek_rest_to_buffer();
      sig = Signature.parse(slice);
      return new EmbeddedSignature({
        sig: sig,
        rawsig: rawsig
      });
    };

    return EmbeddedSignature;

  })(SubPacket);

  exports.Signature = Signature;

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

    Parser.prototype.parse_v2_or_v3 = function(v, klass) {
      var o;
      if (this.slice.read_uint8() !== 5) {
        throw new error("Bad one-octet length");
      }
      o = {};
      o.type = this.slice.read_uint8();
      o.time = this.slice.read_uint32();
      o.sig_data = this.slice.peek_rest_to_buffer();
      o.key_id = this.slice.read_buffer(8);
      o.public_key_class = asymmetric.get_class(this.slice.read_uint8());
      o.hasher = alloc_or_throw(this.slice.read_uint8());
      o.signed_hash_value_hash = this.slice.read_uint16();
      o.sig = o.public_key_class.parse_sig(this.slice);
      o.version = v;
      return new klass(o);
    };

    Parser.prototype.parse_v4 = function() {
      var end, hashed_subpacket_count, o, unhashed_subpacket_count;
      o = {};
      o.type = this.slice.read_uint8();
      o.public_key_class = asymmetric.get_class(this.slice.read_uint8());
      o.hasher = alloc_or_throw(this.slice.read_uint8());
      hashed_subpacket_count = this.slice.read_uint16();
      end = this.slice.i + hashed_subpacket_count;
      o.sig_data = this.slice.peek_to_buffer(hashed_subpacket_count);
      o.hashed_subpackets = ((function() {
        var _results;
        _results = [];
        while (this.slice.i < end) {
          _results.push(this.parse_subpacket());
        }
        return _results;
      }).call(this));
      unhashed_subpacket_count = this.slice.read_uint16();
      end = this.slice.i + unhashed_subpacket_count;
      o.unhashed_subpackets = ((function() {
        var _results;
        _results = [];
        while (this.slice.i < end) {
          _results.push(this.parse_subpacket());
        }
        return _results;
      }).call(this));
      o.signed_hash_value_hash = this.slice.read_uint16();
      o.sig = o.public_key_class.parse_sig(this.slice);
      o.version = 4;
      return new Signature(o);
    };

    Parser.prototype.parse_subpacket = function() {
      var critical, end, five_byte_len, klass, len, raw_type, ret, type, _ref3;
      _ref3 = this.slice.read_v4_length(), len = _ref3[0], five_byte_len = _ref3[1];
      raw_type = this.slice.read_uint8();
      type = raw_type & 0x7f;
      critical = !!(raw_type & 0x80);
      end = this.slice.clamp(len - 1);
      klass = (function() {
        switch (type) {
          case S.creation_time:
            return CreationTime;
          case S.expiration_time:
            return ExpirationTime;
          case S.exportable_certificate:
            return Exportable;
          case S.trust_signature:
            return Trust;
          case S.regular_expression:
            return RegularExpression;
          case S.revocable:
            return Revocable;
          case S.key_expiration_time:
            return KeyExpirationTime;
          case S.preferred_symmetric_algorithms:
            return PreferredSymmetricAlgorithms;
          case S.revocation_key:
            return RevocationKey;
          case S.issuer:
            return Issuer;
          case S.notation_data:
            return NotationData;
          case S.preferred_hash_algorithms:
            return PreferredHashAlgorithms;
          case S.preferred_compression_algorithms:
            return PreferredCompressionAlgorithms;
          case S.key_server_preferences:
            return KeyServerPreferences;
          case S.preferred_key_server:
            return PreferredKeyServer;
          case S.primary_user_id:
            return PrimaryUserId;
          case S.policy_uri:
            return PolicyURI;
          case S.key_flags:
            return KeyFlags;
          case S.signers_user_id:
            return SignersUserID;
          case S.reason_for_revocation:
            return ReasonForRevocation;
          case S.features:
            return Features;
          case S.signature_target:
            return SignatureTarget;
          case S.embedded_signature:
            return EmbeddedSignature;
          default:
            if (type >= S.experimental_low && type <= S.experimental_high) {
              return Experimental;
            } else {
              throw new Error("Unknown signature subpacket: " + type);
            }
        }
      })();
      ret = klass.parse(this.slice, type);
      ret.set_opts({
        critical: critical,
        five_byte_len: five_byte_len
      });
      this.slice.unclamp(end);
      return ret;
    };

    Parser.prototype.parse = function() {
      var version;
      version = this.slice.read_uint8();
      switch (version) {
        case C.versions.signature.V2:
          return this.parse_v2_or_v3(version, Signature_v2);
        case C.versions.signature.V3:
          return this.parse_v2_or_v3(version, Signature_v3);
        case C.versions.signature.V4:
          return this.parse_v4();
        default:
          throw new Error("Unknown signature version: " + version);
      }
    };

    return Parser;

  })();

  exports.CreationTime = CreationTime;

  exports.KeyFlags = KeyFlags;

  exports.KeyExpirationTime = KeyExpirationTime;

  exports.PreferredSymmetricAlgorithms = PreferredSymmetricAlgorithms;

  exports.PreferredHashAlgorithms = PreferredHashAlgorithms;

  exports.PreferredCompressionAlgorithms = PreferredCompressionAlgorithms;

  exports.Features = Features;

  exports.KeyServerPreferences = KeyServerPreferences;

  exports.Issuer = Issuer;

  exports.EmbeddedSignature = EmbeddedSignature;

  exports.PrimaryUserId = PrimaryUserId;

}).call(this);
