text: 'use strict';
  
  var elliptic = require('../ecc');
  var utils = elliptic.utils;
  var assert = utils.assert;
  var parseBytes = utils.parseBytes;
  var cachedProperty = utils.cachedProperty;
  
  /**
  * @param {EDDSA} eddsa - instance
  * @param {Object} params - public/private key parameters
  *
  * @param {Array<Byte>} [params.secret] - secret seed bytes
  * @param {Point} [params.pub] - public key point (aka `A` in eddsa terms)
  * @param {Array<Byte>} [params.pub] - public key point encoded as bytes
  *
  */
  function KeyPair(eddsa, params) {
    this.eddsa = eddsa;
    this._secret = parseBytes(params.secret);
    if (eddsa.isPoint(params.pub))
      this._pub = params.pub;
    else
      this._pubBytes = parseBytes(params.pub);
  }
  
  KeyPair.fromPublic = function fromPublic(eddsa, pub) {
    if (pub instanceof KeyPair)
      return pub;
    return new KeyPair(eddsa, { pub: pub });
  };
  
  KeyPair.fromSecret = function fromSecret(eddsa, secret) {
    if (secret instanceof KeyPair)
      return secret;
    return new KeyPair(eddsa, { secret: secret });
  };
  
  KeyPair.prototype.secret = function secret() {
    return this._secret;
  };
  
  cachedProperty(KeyPair, 'pubBytes', function pubBytes() {
    return this.eddsa.encodePoint(this.pub());
  });
  
  cachedProperty(KeyPair, 'pub', function pub() {
    if (this._pubBytes)
      return this.eddsa.decodePoint(this._pubBytes);
    return this.eddsa.g.mul(this.priv());
  });
  
  cachedProperty(KeyPair, 'privBytes', function privBytes() {
    var eddsa = this.eddsa;
    var hash = this.hash();
    var lastIx = eddsa.encodingLength - 1;
  
    var a = hash.slice(0, eddsa.encodingLength);
    a[0] &= 248;
    a[lastIx] &= 127;
    a[lastIx] |= 64;
  
    return a;
  });
  
  cachedProperty(KeyPair, 'priv', function priv() {
    return this.eddsa.decodeInt(this.privBytes());
  });
  
  cachedProperty(KeyPair, 'hash', function hash() {
    return this.eddsa.hash().update(this.secret()).digest();
  });
  
  cachedProperty(KeyPair, 'messagePrefix', function messagePrefix() {
    return this.hash().slice(this.eddsa.encodingLength);
  });
  
  KeyPair.prototype.sign = function sign(message) {
    assert(this._secret, 'KeyPair can only verify');
    return this.eddsa.sign(message, this);
  };
  
  KeyPair.prototype.verify = function verify(message, sig) {
    return this.eddsa.verify(message, sig, this);
  };
  
  KeyPair.prototype.getSecret = function getSecret(enc) {
    assert(this._secret, 'KeyPair is public only');
    return utils.encode(this.secret(), enc);
  };
  
  KeyPair.prototype.getPublic = function getPublic(enc) {
    return utils.encode(this.pubBytes(), enc);
  };
  
  module.exports = KeyPair;
  