text: var sjcl    = require('./utils').sjcl;
  
  var UInt160 = require('./uint160').UInt160;
  var UInt256 = require('./uint256').UInt256;
  var Base    = require('./base').Base;
  
  function KeyPair() {
    this._curve  = sjcl.ecc.curves.k256;
    this._secret = null;
    this._pubkey = null;
  };
  
  KeyPair.from_bn_secret = function(j) {
    return (j instanceof this) ? j.clone() : (new this()).parse_bn_secret(j);
  };
  
  KeyPair.prototype.parse_bn_secret = function(j) {
    this._secret = new sjcl.ecc.ecdsa.secretKey(sjcl.ecc.curves.k256, j);
    return this;
  };
  
  /**
   * Returns public key as sjcl public key.
   *
   * @private
   */
  KeyPair.prototype._pub = function() {
    var curve = this._curve;
  
    if (!this._pubkey && this._secret) {
      var exponent = this._secret._exponent;
      this._pubkey = new sjcl.ecc.ecdsa.publicKey(curve, curve.G.mult(exponent));
    }
  
    return this._pubkey;
  };
  
  /**
   * Returns public key in compressed format as bit array.
   *
   * @private
   */
  KeyPair.prototype._pub_bits = function() {
    var pub = this._pub();
  
    if (!pub) {
      return null;
    }
  
    var point = pub._point, y_even = point.y.mod(2).equals(0);
  
    return sjcl.bitArray.concat(
      [sjcl.bitArray.partial(8, y_even ? 0x02 : 0x03)],
      point.x.toBits(this._curve.r.bitLength())
    );
  };
  
  /**
   * Returns public key as hex.
   *
   * Key will be returned as a compressed pubkey - 33 bytes converted to hex.
   */
  KeyPair.prototype.to_hex_pub = function() {
    var bits = this._pub_bits();
  
    if (!bits) {
      return null;
    }
  
    return sjcl.codec.hex.fromBits(bits).toUpperCase();
  };
  
  function SHA256_RIPEMD160(bits) {
    return sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));
  }
  
  KeyPair.prototype.get_address = function() {
    var bits = this._pub_bits();
  
    if (!bits) {
      return null;
    }
  
    var hash = SHA256_RIPEMD160(bits);
  
    var address = UInt160.from_bits(hash);
    address.set_version(Base.VER_ACCOUNT_ID);
    return address;
  };
  
  KeyPair.prototype.sign = function(hash) {
    hash = UInt256.from_json(hash);
    var sig = this._secret.sign(hash.to_bits(), 0);
    sig = this._secret.canonicalizeSignature(sig);
    return this._secret.encodeDER(sig);
  };
  
  exports.KeyPair = KeyPair;
  