diff --git a/package.json b/package.json
index f5cceb8..cf3db97 100644
--- a/package.json
+++ b/package.json
@@ -31,14 +31,12 @@
   ],
   "dependencies": {
     "bech32": "^1.1.2",
-    "bigi": "^1.4.0",
     "bip32": "^0.1.0",
     "bip66": "^1.1.0",
     "bitcoin-ops": "^1.4.0",
     "bs58check": "^2.0.0",
     "create-hash": "^1.1.0",
     "create-hmac": "^1.1.3",
-    "ecurve": "^1.0.0",
     "merkle-lib": "^2.0.10",
     "pushdata-bitcoin": "^1.0.1",
     "randombytes": "^2.0.1",
diff --git a/src/ecdsa.js b/src/ecdsa.js
deleted file mode 100644
index 403ffd5..0000000
--- a/src/ecdsa.js
+++ /dev/null
@@ -1,163 +0,0 @@
-var Buffer = require('safe-buffer').Buffer
-var createHmac = require('create-hmac')
-var typeforce = require('typeforce')
-var types = require('./types')
-
-var BigInteger = require('bigi')
-
-var ZERO = Buffer.alloc(1, 0)
-var ONE = Buffer.alloc(1, 1)
-
-var ecurve = require('ecurve')
-var secp256k1 = ecurve.getCurveByName('secp256k1')
-
-// https://tools.ietf.org/html/rfc6979#section-3.2
-function deterministicGenerateK (hash, x, checkSig) {
-  typeforce(types.tuple(
-    types.Hash256bit,
-    types.Buffer256bit,
-    types.Function
-  ), arguments)
-
-  // Step A, ignored as hash already provided
-  // Step B
-  // Step C
-  var k = Buffer.alloc(32, 0)
-  var v = Buffer.alloc(32, 1)
-
-  // Step D
-  k = createHmac('sha256', k)
-    .update(v)
-    .update(ZERO)
-    .update(x)
-    .update(hash)
-    .digest()
-
-  // Step E
-  v = createHmac('sha256', k).update(v).digest()
-
-  // Step F
-  k = createHmac('sha256', k)
-    .update(v)
-    .update(ONE)
-    .update(x)
-    .update(hash)
-    .digest()
-
-  // Step G
-  v = createHmac('sha256', k).update(v).digest()
-
-  // Step H1/H2a, ignored as tlen === qlen (256 bit)
-  // Step H2b
-  v = createHmac('sha256', k).update(v).digest()
-
-  var T = BigInteger.fromBuffer(v)
-
-  // Step H3, repeat until T is within the interval [1, n - 1] and is suitable for ECDSA
-  while (T.signum() <= 0 || T.compareTo(secp256k1.n) >= 0 || !checkSig(T)) {
-    k = createHmac('sha256', k)
-      .update(v)
-      .update(ZERO)
-      .digest()
-
-    v = createHmac('sha256', k).update(v).digest()
-
-    // Step H1/H2a, again, ignored as tlen === qlen (256 bit)
-    // Step H2b again
-    v = createHmac('sha256', k).update(v).digest()
-    T = BigInteger.fromBuffer(v)
-  }
-
-  return T
-}
-
-var N_OVER_TWO = secp256k1.n.shiftRight(1)
-
-function sign (hash, d) {
-  typeforce(types.tuple(types.Hash256bit, types.BigInt), arguments)
-
-  var x = d.toBuffer(32)
-  var e = BigInteger.fromBuffer(hash)
-  var n = secp256k1.n
-  var G = secp256k1.G
-
-  var r, s
-  deterministicGenerateK(hash, x, function (k) {
-    var Q = G.multiply(k)
-
-    if (secp256k1.isInfinity(Q)) return false
-
-    r = Q.affineX.mod(n)
-    if (r.signum() === 0) return false
-
-    s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n)
-    if (s.signum() === 0) return false
-
-    return true
-  })
-
-  // enforce low S values, see bip62: 'low s values in signatures'
-  if (s.compareTo(N_OVER_TWO) > 0) {
-    s = n.subtract(s)
-  }
-
-  return {
-    r: r,
-    s: s
-  }
-}
-
-function verify (hash, signature, Q) {
-  typeforce(types.tuple(
-    types.Hash256bit,
-    types.ECSignature,
-    types.ECPoint
-  ), arguments)
-
-  var n = secp256k1.n
-  var G = secp256k1.G
-
-  var r = signature.r
-  var s = signature.s
-
-  // 1.4.1 Enforce r and s are both integers in the interval [1, n − 1]
-  if (r.signum() <= 0 || r.compareTo(n) >= 0) return false
-  if (s.signum() <= 0 || s.compareTo(n) >= 0) return false
-
-  // 1.4.2 H = Hash(M), already done by the user
-  // 1.4.3 e = H
-  var e = BigInteger.fromBuffer(hash)
-
-  // Compute s^-1
-  var sInv = s.modInverse(n)
-
-  // 1.4.4 Compute u1 = es^−1 mod n
-  //               u2 = rs^−1 mod n
-  var u1 = e.multiply(sInv).mod(n)
-  var u2 = r.multiply(sInv).mod(n)
-
-  // 1.4.5 Compute R = (xR, yR)
-  //               R = u1G + u2Q
-  var R = G.multiplyTwo(u1, Q, u2)
-
-  // 1.4.5 (cont.) Enforce R is not at infinity
-  if (secp256k1.isInfinity(R)) return false
-
-  // 1.4.6 Convert the field element R.x to an integer
-  var xR = R.affineX
-
-  // 1.4.7 Set v = xR mod n
-  var v = xR.mod(n)
-
-  // 1.4.8 If v = r, output "valid", and if v != r, output "invalid"
-  return v.equals(r)
-}
-
-module.exports = {
-  deterministicGenerateK: deterministicGenerateK,
-  sign: sign,
-  verify: verify,
-
-  // TODO: remove
-  __curve: secp256k1
-}
diff --git a/src/ecpair.js b/src/ecpair.js
index b491f53..d0653be 100644
--- a/src/ecpair.js
+++ b/src/ecpair.js
@@ -1,63 +1,70 @@
-let ecdsa = require('./ecdsa')
+let ecc = require('tiny-secp256k1')
 let randomBytes = require('randombytes')
 let typeforce = require('typeforce')
 let types = require('./types')
 let wif = require('wif')
 
 let NETWORKS = require('./networks')
-let BigInteger = require('bigi')
 
-let ecurve = require('ecurve')
-let secp256k1 = ecdsa.__curve
+// TODO: why is the function name toJSON weird?
+function isPoint (x) { return ecc.isPoint(x) }
+let isOptions = typeforce.maybe(typeforce.compile({
+  compressed: types.maybe(types.Boolean),
+  network: types.maybe(types.Network)
+}))
 
 function ECPair (d, Q, options) {
-  if (options) {
-    typeforce({
-      compressed: types.maybe(types.Boolean),
-      network: types.maybe(types.Network)
-    }, options)
-  }
-
   options = options || {}
 
-  if (d) {
-    if (d.signum() <= 0) throw new Error('Private key must be greater than 0')
-    if (d.compareTo(secp256k1.n) >= 0) throw new Error('Private key must be less than the curve order')
-    if (Q) throw new TypeError('Unexpected publicKey parameter')
-
-    this.d = d
-  } else {
-    typeforce(types.ECPoint, Q)
-
-    this.__Q = Q
-  }
-
   this.compressed = options.compressed === undefined ? true : options.compressed
   this.network = options.network || NETWORKS.bitcoin
+
+  this.__d = d || null
+  this.__Q = null
+  if (Q) this.__Q = ecc.pointCompress(Q, this.compressed)
 }
 
-Object.defineProperty(ECPair.prototype, 'Q', {
-  get: function () {
-    if (!this.__Q && this.d) {
-      this.__Q = secp256k1.G.multiply(this.d)
-    }
-
-    return this.__Q
-  }
+Object.defineProperty(ECPair.prototype, 'privateKey', {
+  enumerable: false,
+  get: function () { return this.__d }
 })
 
-ECPair.fromPublicKeyBuffer = function (buffer, network) {
-  var Q = ecurve.Point.decodeFrom(secp256k1, buffer)
+Object.defineProperty(ECPair.prototype, 'publicKey', { get: function () {
+  if (!this.__Q) this.__Q = ecc.pointFromScalar(this.__d, this.compressed)
+  return this.__Q
+}})
 
-  return new ECPair(null, Q, {
-    compressed: Q.compressed,
-    network: network
-  })
+ECPair.prototype.toWIF = function () {
+  if (!this.__d) throw new Error('Missing private key')
+  return wif.encode(this.network.wif, this.__d, this.compressed)
 }
 
-ECPair.fromWIF = function (string, network) {
-  var decoded = wif.decode(string)
-  var version = decoded.version
+ECPair.prototype.sign = function (hash) {
+  if (!this.__d) throw new Error('Missing private key')
+  return ecc.sign(hash, this.__d)
+}
+
+ECPair.prototype.verify = function (hash, signature) {
+  return ecc.verify(hash, this.publicKey, signature)
+}
+
+function fromPrivateKey (buffer, options) {
+  typeforce(types.Buffer256bit, buffer)
+  if (!ecc.isPrivate(buffer)) throw new TypeError('Private key not in range [1, n)')
+  typeforce(isOptions, options)
+
+  return new ECPair(buffer, null, options)
+}
+
+function fromPublicKey (buffer, options) {
+  typeforce(isPoint, buffer)
+  typeforce(isOptions, options)
+  return new ECPair(null, buffer, options)
+}
+
+function fromWIF (string, network) {
+  let decoded = wif.decode(string)
+  let version = decoded.version
 
   // list of networks?
   if (types.Array(network)) {
@@ -74,58 +81,29 @@ ECPair.fromWIF = function (string, network) {
     if (version !== network.wif) throw new Error('Invalid network version')
   }
 
-  var d = BigInteger.fromBuffer(decoded.privateKey)
-
-  return new ECPair(d, null, {
+  return fromPrivateKey(decoded.privateKey, {
     compressed: decoded.compressed,
     network: network
   })
 }
 
-ECPair.makeRandom = function (options) {
+function makeRandom (options) {
+  typeforce(isOptions, options)
   options = options || {}
+  let rng = options.rng || randomBytes
 
-  var rng = options.rng || randomBytes
-
-  var d
+  let d
   do {
-    var buffer = rng(32)
-    typeforce(types.Buffer256bit, buffer)
+    d = rng(32)
+    typeforce(types.Buffer256bit, d)
+  } while (!ecc.isPrivate(d))
 
-    d = BigInteger.fromBuffer(buffer)
-  } while (d.signum() <= 0 || d.compareTo(secp256k1.n) >= 0)
-
-  return new ECPair(d, null, options)
+  return fromPrivateKey(d, options)
 }
 
-ECPair.prototype.getNetwork = function () {
-  return this.network
+module.exports = {
+  makeRandom,
+  fromPrivateKey,
+  fromPublicKey,
+  fromWIF
 }
-
-ECPair.prototype.getPublicKeyBuffer = function () {
-  return this.Q.getEncoded(this.compressed)
-}
-
-ECPair.prototype.sign = function (hash) {
-  if (!this.d) throw new Error('Missing private key')
-
-  let signature = ecdsa.sign(hash, this.d)
-  return Buffer.concat([signature.r.toBuffer(32), signature.s.toBuffer(32)], 64)
-}
-
-ECPair.prototype.toWIF = function () {
-  if (!this.d) throw new Error('Missing private key')
-
-  return wif.encode(this.network.wif, this.d.toBuffer(32), this.compressed)
-}
-
-ECPair.prototype.verify = function (hash, signature) {
-  signature = {
-    r: BigInteger.fromBuffer(signature.slice(0, 32)),
-    s: BigInteger.fromBuffer(signature.slice(32, 64))
-  }
-
-  return ecdsa.verify(hash, signature, this.Q)
-}
-
-module.exports = ECPair
diff --git a/src/transaction_builder.js b/src/transaction_builder.js
index 3a1310b..4f731dc 100644
--- a/src/transaction_builder.js
+++ b/src/transaction_builder.js
@@ -180,7 +180,7 @@ function fixMultisigOrder (input, transaction, vin) {
   var unmatched = input.signatures.concat()
 
   input.signatures = input.pubKeys.map(function (pubKey) {
-    var keyPair = ECPair.fromPublicKeyBuffer(pubKey)
+    var keyPair = ECPair.fromPublicKey(pubKey)
     var match
 
     // check for a signature
@@ -686,7 +686,7 @@ TransactionBuilder.prototype.sign = function (vin, keyPair, redeemScript, hashTy
     throw new Error('Inconsistent redeemScript')
   }
 
-  var kpPubKey = keyPair.publicKey || keyPair.getPublicKeyBuffer()
+  var kpPubKey = keyPair.publicKey || keyPair.getPublicKey()
   if (!canSign(input)) {
     if (witnessValue !== undefined) {
       if (input.value !== undefined && input.value !== witnessValue) throw new Error('Input didn\'t match witnessValue')
diff --git a/src/types.js b/src/types.js
index c1e5fb1..302043f 100644
--- a/src/types.js
+++ b/src/types.js
@@ -16,11 +16,9 @@ function Satoshi (value) {
 }
 
 // external dependent types
-var BigInt = typeforce.quacksLike('BigInteger')
 var ECPoint = typeforce.quacksLike('Point')
 
 // exposed, external API
-var ECSignature = typeforce.compile({ r: BigInt, s: BigInt })
 var Network = typeforce.compile({
   messagePrefix: typeforce.oneOf(typeforce.Buffer, typeforce.String),
   bip32: {
@@ -34,11 +32,9 @@ var Network = typeforce.compile({
 
 // extend typeforce types with ours
 var types = {
-  BigInt: BigInt,
   BIP32Path: BIP32Path,
   Buffer256bit: typeforce.BufferN(32),
   ECPoint: ECPoint,
-  ECSignature: ECSignature,
   Hash160bit: typeforce.BufferN(20),
   Hash256bit: typeforce.BufferN(32),
   Network: Network,
diff --git a/test/bitcoin.core.js b/test/bitcoin.core.js
index b042ae1..4d73c2a 100644
--- a/test/bitcoin.core.js
+++ b/test/bitcoin.core.js
@@ -94,7 +94,7 @@ describe('Bitcoin-core', function () {
       var keyPair = bitcoin.ECPair.fromWIF(string, network)
 
       it('fromWIF imports ' + string, function () {
-        assert.strictEqual(keyPair.d.toHex(), hex)
+        assert.strictEqual(keyPair.privateKey.toString('hex'), hex)
         assert.strictEqual(keyPair.compressed, params.isCompressed)
       })
 
diff --git a/test/ecdsa.js b/test/ecdsa.js
deleted file mode 100644
index 1f20a41..0000000
--- a/test/ecdsa.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/* global describe, it */
-
-var assert = require('assert')
-var bcrypto = require('../src/crypto')
-var ecdsa = require('../src/ecdsa')
-var hoodwink = require('hoodwink')
-
-var BigInteger = require('bigi')
-
-var curve = ecdsa.__curve
-
-var fixtures = require('./fixtures/ecdsa.json')
-
-describe('ecdsa', function () {
-  function fromRaw (signature) {
-    return {
-      r: new BigInteger(signature.r, 16),
-      s: new BigInteger(signature.s, 16)
-    }
-  }
-
-  function toRaw (signature) {
-    return {
-      r: signature.r.toHex(),
-      s: signature.s.toHex()
-    }
-  }
-
-  describe('deterministicGenerateK', function () {
-    function checkSig () {
-      return true
-    }
-
-    fixtures.valid.ecdsa.forEach(function (f) {
-      it('for "' + f.message + '"', function () {
-        var x = BigInteger.fromHex(f.d).toBuffer(32)
-        var h1 = bcrypto.sha256(f.message)
-
-        var k = ecdsa.deterministicGenerateK(h1, x, checkSig)
-        assert.strictEqual(k.toHex(), f.k)
-      })
-    })
-
-    it('loops until an appropriate k value is found', hoodwink(function () {
-      this.mock(BigInteger, 'fromBuffer', function f (b) {
-        assert.strictEqual(b.length, 32)
-        if (f.calls === 0) return BigInteger.ZERO // < 1
-        if (f.calls === 1) return curve.n // > n - 1
-        if (f.calls === 2) return new BigInteger('42') // valid
-      }, 3)
-
-      var x = new BigInteger('1').toBuffer(32)
-      var h1 = Buffer.alloc(32)
-      var k = ecdsa.deterministicGenerateK(h1, x, checkSig)
-
-      assert.strictEqual(k.toString(), '42')
-    }))
-
-    it('loops until a suitable signature is found', hoodwink(function () {
-      var checkSigStub = this.stub(function f () {
-        if (f.calls === 0) return false // bad signature
-        if (f.calls === 1) return true // good signature
-      }, 2)
-
-      var x = BigInteger.ONE.toBuffer(32)
-      var h1 = Buffer.alloc(32)
-      var k = ecdsa.deterministicGenerateK(h1, x, checkSigStub)
-
-      assert.strictEqual(k.toHex(), 'a9b1a1a84a4c2f96b6158ed7a81404c50cb74373c22e8d9e02d0411d719acae2')
-    }))
-
-    fixtures.valid.rfc6979.forEach(function (f) {
-      it('produces the expected k values for ' + f.message + " if k wasn't suitable", function () {
-        var x = BigInteger.fromHex(f.d).toBuffer(32)
-        var h1 = bcrypto.sha256(f.message)
-
-        var results = []
-        ecdsa.deterministicGenerateK(h1, x, function (k) {
-          results.push(k)
-
-          return results.length === 16
-        })
-
-        assert.strictEqual(results[0].toHex(), f.k0)
-        assert.strictEqual(results[1].toHex(), f.k1)
-        assert.strictEqual(results[15].toHex(), f.k15)
-      })
-    })
-  })
-
-  describe('sign', function () {
-    fixtures.valid.ecdsa.forEach(function (f) {
-      it('produces a deterministic signature for "' + f.message + '"', function () {
-        var d = BigInteger.fromHex(f.d)
-        var hash = bcrypto.sha256(f.message)
-        var signature = ecdsa.sign(hash, d)
-
-        assert.deepEqual(toRaw(signature), f.signature)
-      })
-    })
-
-    it('should sign with low S value', function () {
-      var hash = bcrypto.sha256('Vires in numeris')
-      var sig = ecdsa.sign(hash, BigInteger.ONE)
-
-      // See BIP62 for more information
-      var N_OVER_TWO = curve.n.shiftRight(1)
-      assert(sig.s.compareTo(N_OVER_TWO) <= 0)
-    })
-  })
-
-  describe('verify', function () {
-    fixtures.valid.ecdsa.forEach(function (f) {
-      it('verifies a valid signature for "' + f.message + '"', function () {
-        var d = BigInteger.fromHex(f.d)
-        var H = bcrypto.sha256(f.message)
-        var signature = fromRaw(f.signature)
-        var Q = curve.G.multiply(d)
-
-        assert(ecdsa.verify(H, signature, Q))
-      })
-    })
-
-    fixtures.invalid.verify.forEach(function (f) {
-      it('fails to verify with ' + f.description, function () {
-        var H = bcrypto.sha256(f.message)
-        var d = BigInteger.fromHex(f.d)
-        var signature = fromRaw(f.signature)
-        var Q = curve.G.multiply(d)
-
-        assert.strictEqual(ecdsa.verify(H, signature, Q), false)
-      })
-    })
-  })
-})
diff --git a/test/ecpair.js b/test/ecpair.js
index 52e5499..5e2ea59 100644
--- a/test/ecpair.js
+++ b/test/ecpair.js
@@ -1,34 +1,36 @@
 /* global describe, it, beforeEach */
 /* eslint-disable no-new */
 
-var assert = require('assert')
-var ecdsa = require('../src/ecdsa')
-var ecurve = require('ecurve')
-var proxyquire = require('proxyquire')
-var hoodwink = require('hoodwink')
+let assert = require('assert')
+let proxyquire = require('proxyquire')
+let hoodwink = require('hoodwink')
 
-var BigInteger = require('bigi')
-var ECPair = require('../src/ecpair')
+let ECPair = require('../src/ecpair')
+let tinysecp = require('tiny-secp256k1')
 
-var fixtures = require('./fixtures/ecpair.json')
-var curve = ecdsa.__curve
+let fixtures = require('./fixtures/ecpair.json')
 
-var NETWORKS = require('../src/networks')
-var NETWORKS_LIST = [] // Object.values(NETWORKS)
-for (var networkName in NETWORKS) {
+let NETWORKS = require('../src/networks')
+let NETWORKS_LIST = [] // Object.values(NETWORKS)
+for (let networkName in NETWORKS) {
   NETWORKS_LIST.push(NETWORKS[networkName])
 }
 
+let ZERO = Buffer.alloc(32, 0)
+let ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')
+let GROUP_ORDER = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex')
+let GROUP_ORDER_LESS_1 = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140', 'hex')
+
 describe('ECPair', function () {
   describe('constructor', function () {
     it('defaults to compressed', function () {
-      var keyPair = new ECPair(BigInteger.ONE)
+      let keyPair = ECPair.fromPrivateKey(ONE)
 
       assert.strictEqual(keyPair.compressed, true)
     })
 
     it('supports the uncompressed option', function () {
-      var keyPair = new ECPair(BigInteger.ONE, null, {
+      let keyPair = ECPair.fromPrivateKey(ONE, {
         compressed: false
       })
 
@@ -36,7 +38,7 @@ describe('ECPair', function () {
     })
 
     it('supports the network option', function () {
-      var keyPair = new ECPair(BigInteger.ONE, null, {
+      let keyPair = ECPair.fromPrivateKey(ONE, {
         compressed: false,
         network: NETWORKS.testnet
       })
@@ -45,51 +47,58 @@ describe('ECPair', function () {
     })
 
     fixtures.valid.forEach(function (f) {
-      it('calculates the public point for ' + f.WIF, function () {
-        var d = new BigInteger(f.d)
-        var keyPair = new ECPair(d, null, {
+      it('derives public key for ' + f.WIF, function () {
+        let d = Buffer.from(f.d, 'hex')
+        console.log(d)
+
+        let keyPair = ECPair.fromPrivateKey(d, {
           compressed: f.compressed
         })
 
-        assert.strictEqual(keyPair.getPublicKeyBuffer().toString('hex'), f.Q)
+        assert.strictEqual(keyPair.publicKey.toString('hex'), f.Q)
       })
     })
 
     fixtures.invalid.constructor.forEach(function (f) {
       it('throws ' + f.exception, function () {
-        var d = f.d && new BigInteger(f.d)
-        var Q = f.Q && ecurve.Point.decodeFrom(curve, Buffer.from(f.Q, 'hex'))
-
-        assert.throws(function () {
-          new ECPair(d, Q, f.options)
-        }, new RegExp(f.exception))
+        if (f.d) {
+          let d = Buffer.from(f.d, 'hex')
+          assert.throws(function () {
+            ECPair.fromPrivateKey(d, f.options)
+          }, new RegExp(f.exception))
+        } else {
+          let Q = Buffer.from(f.Q, 'hex')
+          assert.throws(function () {
+            ECPair.fromPublicKey(Q, f.options)
+          }, new RegExp(f.exception))
+        }
       })
     })
   })
 
-  describe('getPublicKeyBuffer', function () {
-    var keyPair
+  describe('getPublicKey', function () {
+    let keyPair
 
     beforeEach(function () {
-      keyPair = new ECPair(BigInteger.ONE)
+      keyPair = ECPair.fromPrivateKey(ONE)
     })
 
-    it('wraps Q.getEncoded', hoodwink(function () {
-      this.mock(keyPair.Q, 'getEncoded', function (compressed) {
-        assert.strictEqual(compressed, keyPair.compressed)
-      }, 1)
+    it('calls pointFromScalar lazily', hoodwink(function () {
+      assert.strictEqual(keyPair.__Q, null)
 
-      keyPair.getPublicKeyBuffer()
+      // .publicKey forces the memoization
+      assert.strictEqual(keyPair.publicKey.toString('hex'), '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798')
+      assert.strictEqual(keyPair.__Q.toString('hex'), '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798')
     }))
   })
 
   describe('fromWIF', function () {
     fixtures.valid.forEach(function (f) {
       it('imports ' + f.WIF + ' (' + f.network + ')', function () {
-        var network = NETWORKS[f.network]
-        var keyPair = ECPair.fromWIF(f.WIF, network)
+        let network = NETWORKS[f.network]
+        let keyPair = ECPair.fromWIF(f.WIF, network)
 
-        assert.strictEqual(keyPair.d.toString(), f.d)
+        assert.strictEqual(keyPair.privateKey.toString('hex'), f.d)
         assert.strictEqual(keyPair.compressed, f.compressed)
         assert.strictEqual(keyPair.network, network)
       })
@@ -97,9 +106,9 @@ describe('ECPair', function () {
 
     fixtures.valid.forEach(function (f) {
       it('imports ' + f.WIF + ' (via list of networks)', function () {
-        var keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
+        let keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
 
-        assert.strictEqual(keyPair.d.toString(), f.d)
+        assert.strictEqual(keyPair.privateKey.toString('hex'), f.d)
         assert.strictEqual(keyPair.compressed, f.compressed)
         assert.strictEqual(keyPair.network, NETWORKS[f.network])
       })
@@ -108,7 +117,7 @@ describe('ECPair', function () {
     fixtures.invalid.fromWIF.forEach(function (f) {
       it('throws on ' + f.WIF, function () {
         assert.throws(function () {
-          var networks = f.network ? NETWORKS[f.network] : NETWORKS_LIST
+          let networks = f.network ? NETWORKS[f.network] : NETWORKS_LIST
 
           ECPair.fromWIF(f.WIF, networks)
         }, new RegExp(f.exception))
@@ -119,30 +128,29 @@ describe('ECPair', function () {
   describe('toWIF', function () {
     fixtures.valid.forEach(function (f) {
       it('exports ' + f.WIF, function () {
-        var keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
-        var result = keyPair.toWIF()
-
+        let keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
+        let result = keyPair.toWIF()
         assert.strictEqual(result, f.WIF)
       })
     })
   })
 
   describe('makeRandom', function () {
-    var d = Buffer.from('0404040404040404040404040404040404040404040404040404040404040404', 'hex')
-    var exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv'
+    let d = Buffer.alloc(32, 4)
+    let exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv'
 
     describe('uses randombytes RNG', function () {
       it('generates a ECPair', function () {
-        var stub = { randombytes: function () { return d } }
-        var ProxiedECPair = proxyquire('../src/ecpair', stub)
+        let stub = { randombytes: function () { return d } }
+        let ProxiedECPair = proxyquire('../src/ecpair', stub)
 
-        var keyPair = ProxiedECPair.makeRandom()
+        let keyPair = ProxiedECPair.makeRandom()
         assert.strictEqual(keyPair.toWIF(), exWIF)
       })
     })
 
     it('allows a custom RNG to be used', function () {
-      var keyPair = ECPair.makeRandom({
+      let keyPair = ECPair.makeRandom({
         rng: function (size) { return d.slice(0, size) }
       })
 
@@ -150,14 +158,14 @@ describe('ECPair', function () {
     })
 
     it('retains the same defaults as ECPair constructor', function () {
-      var keyPair = ECPair.makeRandom()
+      let keyPair = ECPair.makeRandom()
 
       assert.strictEqual(keyPair.compressed, true)
       assert.strictEqual(keyPair.network, NETWORKS.bitcoin)
     })
 
     it('supports the options parameter', function () {
-      var keyPair = ECPair.makeRandom({
+      let keyPair = ECPair.makeRandom({
         compressed: false,
         network: NETWORKS.testnet
       })
@@ -168,7 +176,7 @@ describe('ECPair', function () {
 
     it('throws if d is bad length', function () {
       function rng () {
-        return BigInteger.ZERO.toBuffer(28)
+        return Buffer.alloc(28)
       }
 
       assert.throws(function () {
@@ -176,58 +184,59 @@ describe('ECPair', function () {
       }, /Expected Buffer\(Length: 32\), got Buffer\(Length: 28\)/)
     })
 
-    it('loops until d is within interval [1, n - 1] : 1', hoodwink(function () {
-      var rng = this.stub(function f () {
-        if (f.calls === 0) return BigInteger.ZERO.toBuffer(32) // 0
-        return BigInteger.ONE.toBuffer(32) // >0
+    it('loops until d is within interval [1, n) : 1', hoodwink(function () {
+      let rng = this.stub(function f () {
+        if (f.calls === 0) return ZERO // 0
+        return ONE // >0
       }, 2)
 
       ECPair.makeRandom({ rng: rng })
     }))
 
-    it('loops until d is within interval [1, n - 1] : n - 1', hoodwink(function () {
-      var rng = this.stub(function f () {
-        if (f.calls === 0) return BigInteger.ZERO.toBuffer(32) // <1
-        if (f.calls === 1) return curve.n.toBuffer(32) // >n-1
-        return curve.n.subtract(BigInteger.ONE).toBuffer(32) // n-1
+    it('loops until d is within interval [1, n) : n - 1', hoodwink(function () {
+      let rng = this.stub(function f () {
+        if (f.calls === 0) return ZERO // <1
+        if (f.calls === 1) return GROUP_ORDER // >n-1
+        return GROUP_ORDER_LESS_1 // n-1
       }, 3)
 
       ECPair.makeRandom({ rng: rng })
     }))
   })
 
-  describe('getNetwork', function () {
+  describe('.network', function () {
     fixtures.valid.forEach(function (f) {
       it('returns ' + f.network + ' for ' + f.WIF, function () {
-        var network = NETWORKS[f.network]
-        var keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
+        let network = NETWORKS[f.network]
+        let keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
 
-        assert.strictEqual(keyPair.getNetwork(), network)
+        assert.strictEqual(keyPair.network, network)
       })
     })
   })
 
-  describe('ecdsa wrappers', function () {
-    var keyPair, hash
+  describe('tinysecp wrappers', function () {
+    let keyPair, hash, signature
 
     beforeEach(function () {
       keyPair = ECPair.makeRandom()
-      hash = Buffer.alloc(32)
+      hash = ZERO
+      signature = Buffer.alloc(64, 1)
     })
 
     describe('signing', function () {
-      it('wraps ecdsa.sign', hoodwink(function () {
-        this.mock(ecdsa, 'sign', function (h, d) {
+      it('wraps tinysecp.sign', hoodwink(function () {
+        this.mock(tinysecp, 'sign', function (h, d) {
           assert.strictEqual(h, hash)
-          assert.strictEqual(d, keyPair.d)
-          return { r: BigInteger.ONE, s: BigInteger.ONE }
+          assert.strictEqual(d, keyPair.privateKey)
+          return signature
         }, 1)
 
-        keyPair.sign(hash)
+        assert.strictEqual(keyPair.sign(hash), signature)
       }))
 
       it('throws if no private key is found', function () {
-        keyPair.d = null
+        delete keyPair.__d
 
         assert.throws(function () {
           keyPair.sign(hash)
@@ -236,24 +245,15 @@ describe('ECPair', function () {
     })
 
     describe('verify', function () {
-      var signature
-
-      beforeEach(function () {
-        signature = keyPair.sign(hash)
-      })
-
-      it('wraps ecdsa.verify', hoodwink(function () {
-        this.mock(ecdsa, 'verify', function (h, s, q) {
+      it('wraps tinysecp.verify', hoodwink(function () {
+        this.mock(tinysecp, 'verify', function (h, q, s) {
           assert.strictEqual(h, hash)
-          // assert.strictEqual(s, signature)
-          assert.deepEqual(s, {
-            r: BigInteger.fromBuffer(signature.slice(0, 32)),
-            s: BigInteger.fromBuffer(signature.slice(32, 64))
-          })
-          assert.strictEqual(q, keyPair.Q)
+          assert.strictEqual(q, keyPair.publicKey)
+          assert.strictEqual(s, signature)
+          return true
         }, 1)
 
-        keyPair.verify(hash, signature)
+        assert.strictEqual(keyPair.verify(hash, signature), true)
       }))
     })
   })
diff --git a/test/fixtures/ecpair.json b/test/fixtures/ecpair.json
index 6f0a1a2..77eee08 100644
--- a/test/fixtures/ecpair.json
+++ b/test/fixtures/ecpair.json
@@ -1,7 +1,7 @@
 {
   "valid": [
     {
-      "d": "1",
+      "d": "0000000000000000000000000000000000000000000000000000000000000001",
       "Q": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
       "compressed": true,
       "network": "bitcoin",
@@ -9,7 +9,7 @@
       "WIF": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
     },
     {
-      "d": "1",
+      "d": "0000000000000000000000000000000000000000000000000000000000000001",
       "Q": "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
       "compressed": false,
       "network": "bitcoin",
@@ -17,7 +17,7 @@
       "WIF": "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf"
     },
     {
-      "d": "19898843618908353587043383062236220484949425084007183071220218307100305431102",
+      "d": "2bfe58ab6d9fd575bdc3a624e4825dd2b375d64ac033fbc46ea79dbab4f69a3e",
       "Q": "02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340",
       "compressed": true,
       "network": "bitcoin",
@@ -25,7 +25,7 @@
       "WIF": "KxhEDBQyyEFymvfJD96q8stMbJMbZUb6D1PmXqBWZDU2WvbvVs9o"
     },
     {
-      "d": "48968302285117906840285529799176770990048954789747953886390402978935544927851",
+      "d": "6c4313b03f2e7324d75e642f0ab81b734b724e13fec930f309e222470236d66b",
       "Q": "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34",
       "compressed": true,
       "network": "bitcoin",
@@ -33,7 +33,7 @@
       "WIF": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx"
     },
     {
-      "d": "48968302285117906840285529799176770990048954789747953886390402978935544927851",
+      "d": "6c4313b03f2e7324d75e642f0ab81b734b724e13fec930f309e222470236d66b",
       "Q": "044289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34cec320a0565fb7caf11b1ca2f445f9b7b012dda5718b3cface369ee3a034ded6",
       "compressed": false,
       "network": "bitcoin",
@@ -41,7 +41,7 @@
       "WIF": "5JdxzLtFPHNe7CAL8EBC6krdFv9pwPoRo4e3syMZEQT9srmK8hh"
     },
     {
-      "d": "48968302285117906840285529799176770990048954789747953886390402978935544927851",
+      "d": "6c4313b03f2e7324d75e642f0ab81b734b724e13fec930f309e222470236d66b",
       "Q": "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34",
       "compressed": true,
       "network": "testnet",
@@ -49,7 +49,7 @@
       "WIF": "cRD9b1m3vQxmwmjSoJy7Mj56f4uNFXjcWMCzpQCEmHASS4edEwXv"
     },
     {
-      "d": "48968302285117906840285529799176770990048954789747953886390402978935544927851",
+      "d": "6c4313b03f2e7324d75e642f0ab81b734b724e13fec930f309e222470236d66b",
       "Q": "044289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34cec320a0565fb7caf11b1ca2f445f9b7b012dda5718b3cface369ee3a034ded6",
       "compressed": false,
       "network": "testnet",
@@ -57,7 +57,7 @@
       "WIF": "92Qba5hnyWSn5Ffcka56yMQauaWY6ZLd91Vzxbi4a9CCetaHtYj"
     },
     {
-      "d": "115792089237316195423570985008687907852837564279074904382605163141518161494336",
+      "d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
       "Q": "0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
       "compressed": true,
       "network": "bitcoin",
@@ -68,36 +68,27 @@
   "invalid": {
     "constructor": [
       {
-        "exception": "Private key must be greater than 0",
-        "d": "-1"
+        "exception": "Private key not in range \\[1, n\\)",
+        "d": "0000000000000000000000000000000000000000000000000000000000000000"
       },
       {
-        "exception": "Private key must be greater than 0",
-        "d": "0"
+        "exception": "Private key not in range \\[1, n\\)",
+        "d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
       },
       {
-        "exception": "Private key must be less than the curve order",
-        "d": "115792089237316195423570985008687907852837564279074904382605163141518161494337"
-      },
-      {
-        "exception": "Private key must be less than the curve order",
-        "d": "115792089237316195423570985008687907853269984665640564039457584007913129639935"
+        "exception": "Private key not in range \\[1, n\\)",
+        "d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142"
       },
       {
         "exception": "Expected property \"compressed\" of type \\?Boolean, got Number 2",
-        "d": "1",
+        "d": "0000000000000000000000000000000000000000000000000000000000000001",
         "options": {
           "compressed": 2
         }
       },
-      {
-        "exception": "Unexpected publicKey parameter",
-        "d": "1",
-        "Q": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
-      },
       {
         "exception": "Expected property \"network.messagePrefix\" of type Buffer|String, got undefined",
-        "d": "1",
+        "d": "0000000000000000000000000000000000000000000000000000000000000001",
         "options": {
           "network": {}
         }
diff --git a/test/integration/_regtest.js b/test/integration/_regtest.js
index 0baaffa..346fa41 100644
--- a/test/integration/_regtest.js
+++ b/test/integration/_regtest.js
@@ -72,7 +72,7 @@ let baddress = bitcoin.address
 let bcrypto = bitcoin.crypto
 function getAddress (node, network) {
   network = network || bitcoin.networks.bitcoin
-  return baddress.toBase58Check(bcrypto.hash160(node.getPublicKeyBuffer()), network.pubKeyHash)
+  return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash)
 }
 
 function randomAddress () {
diff --git a/test/integration/addresses.js b/test/integration/addresses.js
index 0f8ae52..9451c69 100644
--- a/test/integration/addresses.js
+++ b/test/integration/addresses.js
@@ -12,7 +12,7 @@ let baddress = bitcoin.address
 let bcrypto = bitcoin.crypto
 function getAddress (node, network) {
   network = network || bitcoin.networks.bitcoin
-  return baddress.toBase58Check(bcrypto.hash160(node.getPublicKeyBuffer()), network.pubKeyHash)
+  return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash)
 }
 
 describe('bitcoinjs-lib (addresses)', function () {
@@ -26,7 +26,7 @@ describe('bitcoinjs-lib (addresses)', function () {
   it('can generate an address from a SHA256 hash', function () {
     var hash = bitcoin.crypto.sha256(Buffer.from('correct horse battery staple'))
 
-    var keyPair = bitcoin.ECPair.makeRandom({ rng: () => hash })
+    var keyPair = bitcoin.ECPair.fromPrivateKey(hash)
     var address = getAddress(keyPair)
 
     // Generating addresses from SHA256 hashes is not secure if the input to the hash function is predictable
@@ -57,9 +57,8 @@ describe('bitcoinjs-lib (addresses)', function () {
 
   it('can generate a SegWit address', function () {
     var keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
-    var pubKey = keyPair.getPublicKeyBuffer()
 
-    var scriptPubKey = bitcoin.script.witnessPubKeyHash.output.encode(bitcoin.crypto.hash160(pubKey))
+    var scriptPubKey = bitcoin.script.witnessPubKeyHash.output.encode(bitcoin.crypto.hash160(keyPair.publicKey))
     var address = bitcoin.address.fromOutputScript(scriptPubKey)
 
     assert.strictEqual(address, 'bc1qt97wqg464zrhnx23upykca5annqvwkwujjglky')
@@ -67,9 +66,8 @@ describe('bitcoinjs-lib (addresses)', function () {
 
   it('can generate a SegWit address (via P2SH)', function () {
     var keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
-    var pubKey = keyPair.getPublicKeyBuffer()
 
-    var redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(bitcoin.crypto.hash160(pubKey))
+    var redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(bitcoin.crypto.hash160(keyPair.publicKey))
     var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
     var address = bitcoin.address.fromOutputScript(scriptPubKey)
 
diff --git a/test/integration/cltv.js b/test/integration/cltv.js
index 2b51ed7..b7c6c2c 100644
--- a/test/integration/cltv.js
+++ b/test/integration/cltv.js
@@ -25,11 +25,11 @@ describe('bitcoinjs-lib (transactions w/ CLTV)', function () {
       bitcoin.opcodes.OP_DROP,
 
       bitcoin.opcodes.OP_ELSE,
-      bQ.getPublicKeyBuffer(),
+      bQ.publicKey,
       bitcoin.opcodes.OP_CHECKSIGVERIFY,
       bitcoin.opcodes.OP_ENDIF,
 
-      aQ.getPublicKeyBuffer(),
+      aQ.publicKey,
       bitcoin.opcodes.OP_CHECKSIG
     ])
   }
diff --git a/test/integration/crypto.js b/test/integration/crypto.js
index 8566628..58ae431 100644
--- a/test/integration/crypto.js
+++ b/test/integration/crypto.js
@@ -24,7 +24,7 @@ describe('bitcoinjs-lib (crypto)', function () {
       assert(bitcoin.script.pubKeyHash.input.check(scriptChunks), 'Expected pubKeyHash script')
       var prevOutScript = bitcoin.address.toOutputScript('1ArJ9vRaQcoQ29mTWZH768AmRwzb6Zif1z')
       var scriptSignature = bitcoin.script.signature.decode(scriptChunks[0])
-      var publicKey = bitcoin.ECPair.fromPublicKeyBuffer(scriptChunks[1])
+      var publicKey = bitcoin.ECPair.fromPublicKey(scriptChunks[1])
 
       var m = tx.hashForSignature(vin, prevOutScript, scriptSignature.hashType)
       assert(publicKey.verify(m, scriptSignature.signature), 'Invalid m')
diff --git a/test/integration/csv.js b/test/integration/csv.js
index ef9c30f..adb28b5 100644
--- a/test/integration/csv.js
+++ b/test/integration/csv.js
@@ -26,11 +26,11 @@ describe('bitcoinjs-lib (transactions w/ CSV)', function () {
       bitcoin.opcodes.OP_DROP,
 
       bitcoin.opcodes.OP_ELSE,
-      bQ.getPublicKeyBuffer(),
+      bQ.publicKey,
       bitcoin.opcodes.OP_CHECKSIGVERIFY,
       bitcoin.opcodes.OP_ENDIF,
 
-      aQ.getPublicKeyBuffer(),
+      aQ.publicKey,
       bitcoin.opcodes.OP_CHECKSIG
     ])
   }
diff --git a/test/integration/stealth.js b/test/integration/stealth.js
index b3cea41..90acb7b 100644
--- a/test/integration/stealth.js
+++ b/test/integration/stealth.js
@@ -1,74 +1,72 @@
 /* global describe, it */
 
 let assert = require('assert')
-let bigi = require('bigi')
 let bitcoin = require('../../')
-
-let ecurve = require('ecurve')
-let secp256k1 = ecurve.getCurveByName('secp256k1')
-let G = secp256k1.G
-let n = secp256k1.n
+let ecc = require('tiny-secp256k1')
 
 // TODO: remove
 let baddress = bitcoin.address
 let bcrypto = bitcoin.crypto
 function getAddress (node) {
-  return baddress.toBase58Check(bcrypto.hash160(node.getPublicKeyBuffer()), bitcoin.networks.bitcoin.pubKeyHash)
+  return baddress.toBase58Check(bcrypto.hash160(node.publicKey), bitcoin.networks.bitcoin.pubKeyHash)
 }
 
 // vG = (dG \+ sha256(e * dG)G)
 function stealthSend (e, Q) {
-  var eQ = Q.multiply(e) // shared secret
-  var c = bigi.fromBuffer(bitcoin.crypto.sha256(eQ.getEncoded()))
-  var cG = G.multiply(c)
-  var vG = new bitcoin.ECPair(null, Q.add(cG))
+  var eQ = ecc.pointMultiply(Q, e, true) // shared secret
+  var c = bitcoin.crypto.sha256(eQ)
+  var Qc = ecc.pointAddScalar(Q, c)
+  var vG = bitcoin.ECPair.fromPublicKey(Qc)
 
   return vG
 }
 
 // v = (d + sha256(eG * d))
 function stealthReceive (d, eG) {
-  var eQ = eG.multiply(d) // shared secret
-  var c = bigi.fromBuffer(bitcoin.crypto.sha256(eQ.getEncoded()))
-  var v = new bitcoin.ECPair(d.add(c).mod(n))
+  var eQ = ecc.pointMultiply(eG, d) // shared secret
+  var c = bitcoin.crypto.sha256(eQ)
+  var dc = ecc.privateAdd(d, c)
+  var v = bitcoin.ECPair.fromPrivateKey(dc)
 
   return v
 }
 
 // d = (v - sha256(e * dG))
 function stealthRecoverLeaked (v, e, Q) {
-  var eQ = Q.multiply(e) // shared secret
-  var c = bigi.fromBuffer(bitcoin.crypto.sha256(eQ.getEncoded()))
-  var d = new bitcoin.ECPair(v.subtract(c).mod(n))
+  var eQ = ecc.pointMultiply(Q, e) // shared secret
+  var c = bitcoin.crypto.sha256(eQ)
+  var vc = ecc.privateSub(v, c)
+  var d = bitcoin.ECPair.fromPrivateKey(vc)
 
   return d
 }
 
 // vG = (rG \+ sha256(e * dG)G)
 function stealthDualSend (e, R, Q) {
-  var eQ = Q.multiply(e) // shared secret
-  var c = bigi.fromBuffer(bitcoin.crypto.sha256(eQ.getEncoded()))
-  var cG = G.multiply(c)
-  var vG = new bitcoin.ECPair(null, R.add(cG))
+  var eQ = ecc.pointMultiply(Q, e) // shared secret
+  var c = bitcoin.crypto.sha256(eQ)
+  var Rc = ecc.pointAddScalar(R, c)
+  var vG = bitcoin.ECPair.fromPublicKey(Rc)
 
   return vG
 }
 
 // vG = (rG \+ sha256(eG * d)G)
 function stealthDualScan (d, R, eG) {
-  var eQ = eG.multiply(d) // shared secret
-  var c = bigi.fromBuffer(bitcoin.crypto.sha256(eQ.getEncoded()))
-  var cG = G.multiply(c)
-  var vG = new bitcoin.ECPair(null, R.add(cG))
+  var eQ = ecc.pointMultiply(eG, d) // shared secret
+  var c = bitcoin.crypto.sha256(eQ)
+  var Rc = ecc.pointAddScalar(R, c)
+  var vG = bitcoin.ECPair.fromPublicKey(Rc)
 
   return vG
 }
 
 // v = (r + sha256(eG * d))
 function stealthDualReceive (d, r, eG) {
-  var eQ = eG.multiply(d) // shared secret
-  var c = bigi.fromBuffer(bitcoin.crypto.sha256(eQ.getEncoded()))
-  var v = new bitcoin.ECPair(r.add(c).mod(n))
+  var eQ = ecc.pointMultiply(eG, d) // shared secret
+  var c = bitcoin.crypto.sha256(eQ)
+  var rc = ecc.privateAdd(r, c)
+  var v = bitcoin.ECPair.fromPrivateKey(rc)
 
   return v
 }
@@ -80,12 +78,12 @@ describe('bitcoinjs-lib (crypto)', function () {
     var nonce = bitcoin.ECPair.fromWIF('KxVqB96pxbw1pokzQrZkQbLfVBjjHFfp2mFfEp8wuEyGenLFJhM9') // private to sender
 
     // ... recipient reveals public key (recipient.Q) to sender
-    var forSender = stealthSend(nonce.d, recipient.Q)
+    var forSender = stealthSend(nonce.privateKey, recipient.publicKey)
     assert.equal(getAddress(forSender), '1CcZWwCpACJL3AxqoDbwEt4JgDFuTHUspE')
     assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/)
 
     // ... sender reveals nonce public key (nonce.Q) to recipient
-    var forRecipient = stealthReceive(recipient.d, nonce.Q)
+    var forRecipient = stealthReceive(recipient.privateKey, nonce.publicKey)
     assert.equal(getAddress(forRecipient), '1CcZWwCpACJL3AxqoDbwEt4JgDFuTHUspE')
     assert.equal(forRecipient.toWIF(), 'L1yjUN3oYyCXV3LcsBrmxCNTa62bZKWCybxVJMvqjMmmfDE8yk7n')
 
@@ -98,11 +96,11 @@ describe('bitcoinjs-lib (crypto)', function () {
     var nonce = bitcoin.ECPair.makeRandom() // private to sender
 
     // ... recipient reveals public key (recipient.Q) to sender
-    var forSender = stealthSend(nonce.d, recipient.Q)
+    var forSender = stealthSend(nonce.privateKey, recipient.publicKey)
     assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/)
 
     // ... sender reveals nonce public key (nonce.Q) to recipient
-    var forRecipient = stealthReceive(recipient.d, nonce.Q)
+    var forRecipient = stealthReceive(recipient.privateKey, nonce.publicKey)
     assert.doesNotThrow(function () { forRecipient.toWIF() })
 
     // sender and recipient, both derived same address
@@ -114,15 +112,15 @@ describe('bitcoinjs-lib (crypto)', function () {
     var nonce = bitcoin.ECPair.makeRandom() // private to sender
 
     // ... recipient reveals public key (recipient.Q) to sender
-    var forSender = stealthSend(nonce.d, recipient.Q)
+    var forSender = stealthSend(nonce.privateKey, recipient.publicKey)
     assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/)
 
     // ... sender reveals nonce public key (nonce.Q) to recipient
-    var forRecipient = stealthReceive(recipient.d, nonce.Q)
+    var forRecipient = stealthReceive(recipient.privateKey, nonce.publicKey)
     assert.doesNotThrow(function () { forRecipient.toWIF() })
 
     // ... recipient accidentally leaks forRecipient.d on the blockchain
-    var leaked = stealthRecoverLeaked(forRecipient.d, nonce.d, recipient.Q)
+    var leaked = stealthRecoverLeaked(forRecipient.privateKey, nonce.privateKey, recipient.publicKey)
     assert.equal(leaked.toWIF(), recipient.toWIF())
   })
 
@@ -133,15 +131,15 @@ describe('bitcoinjs-lib (crypto)', function () {
     var nonce = bitcoin.ECPair.fromWIF('KxVqB96pxbw1pokzQrZkQbLfVBjjHFfp2mFfEp8wuEyGenLFJhM9') // private to sender
 
     // ... recipient reveals public key(s) (recipient.Q, scan.Q) to sender
-    var forSender = stealthDualSend(nonce.d, recipient.Q, scan.Q)
+    var forSender = stealthDualSend(nonce.privateKey, recipient.publicKey, scan.publicKey)
     assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/)
 
     // ... sender reveals nonce public key (nonce.Q) to scanner
-    var forScanner = stealthDualScan(scan.d, recipient.Q, nonce.Q)
+    var forScanner = stealthDualScan(scan.privateKey, recipient.publicKey, nonce.publicKey)
     assert.throws(function () { forScanner.toWIF() }, /Error: Missing private key/)
 
     // ... scanner reveals relevant transaction + nonce public key (nonce.Q) to recipient
-    var forRecipient = stealthDualReceive(scan.d, recipient.d, nonce.Q)
+    var forRecipient = stealthDualReceive(scan.privateKey, recipient.privateKey, nonce.publicKey)
     assert.doesNotThrow(function () { forRecipient.toWIF() })
 
     // scanner, sender and recipient, all derived same address
@@ -155,15 +153,15 @@ describe('bitcoinjs-lib (crypto)', function () {
     var nonce = bitcoin.ECPair.makeRandom() // private to sender
 
     // ... recipient reveals public key(s) (recipient.Q, scan.Q) to sender
-    var forSender = stealthDualSend(nonce.d, recipient.Q, scan.Q)
+    var forSender = stealthDualSend(nonce.privateKey, recipient.publicKey, scan.publicKey)
     assert.throws(function () { forSender.toWIF() }, /Error: Missing private key/)
 
     // ... sender reveals nonce public key (nonce.Q) to scanner
-    var forScanner = stealthDualScan(scan.d, recipient.Q, nonce.Q)
+    var forScanner = stealthDualScan(scan.privateKey, recipient.publicKey, nonce.publicKey)
     assert.throws(function () { forScanner.toWIF() }, /Error: Missing private key/)
 
     // ... scanner reveals relevant transaction + nonce public key (nonce.Q) to recipient
-    var forRecipient = stealthDualReceive(scan.d, recipient.d, nonce.Q)
+    var forRecipient = stealthDualReceive(scan.privateKey, recipient.privateKey, nonce.publicKey)
     assert.doesNotThrow(function () { forRecipient.toWIF() })
 
     // scanner, sender and recipient, all derived same address
diff --git a/test/integration/transactions.js b/test/integration/transactions.js
index c1e4862..7f78ee8 100644
--- a/test/integration/transactions.js
+++ b/test/integration/transactions.js
@@ -10,7 +10,7 @@ let baddress = bitcoin.address
 let bcrypto = bitcoin.crypto
 function getAddress (node, network) {
   network = network || bitcoin.networks.bitcoin
-  return baddress.toBase58Check(bcrypto.hash160(node.getPublicKeyBuffer()), network.pubKeyHash)
+  return baddress.toBase58Check(bcrypto.hash160(node.publicKey), network.pubKeyHash)
 }
 
 function rng () {
@@ -115,7 +115,7 @@ describe('bitcoinjs-lib (transactions)', function () {
       '91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe',
       '91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx9rcrL7'
     ].map(function (wif) { return bitcoin.ECPair.fromWIF(wif, regtest) })
-    var pubKeys = keyPairs.map(function (x) { return x.getPublicKeyBuffer() })
+    var pubKeys = keyPairs.map(function (x) { return x.publicKey })
 
     var redeemScript = bitcoin.script.multisig.output.encode(2, pubKeys)
     var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
@@ -150,8 +150,7 @@ describe('bitcoinjs-lib (transactions)', function () {
     this.timeout(30000)
 
     var keyPair = bitcoin.ECPair.fromWIF('cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87JcbXMTcA', regtest)
-    var pubKey = keyPair.getPublicKeyBuffer()
-    var pubKeyHash = bitcoin.crypto.hash160(pubKey)
+    var pubKeyHash = bitcoin.crypto.hash160(keyPair.publicKey)
 
     var redeemScript = bitcoin.script.witnessPubKeyHash.output.encode(pubKeyHash)
     var redeemScriptHash = bitcoin.crypto.hash160(redeemScript)
@@ -191,7 +190,7 @@ describe('bitcoinjs-lib (transactions)', function () {
       'cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87KcLPVfXz',
       'cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87L7FgDCKE'
     ].map(function (wif) { return bitcoin.ECPair.fromWIF(wif, regtest) })
-    var pubKeys = keyPairs.map(function (x) { return x.getPublicKeyBuffer() })
+    var pubKeys = keyPairs.map(function (x) { return x.publicKey })
 
     var witnessScript = bitcoin.script.multisig.output.encode(3, pubKeys)
     var redeemScript = bitcoin.script.witnessScriptHash.output.encode(bitcoin.crypto.sha256(witnessScript))
@@ -230,7 +229,7 @@ describe('bitcoinjs-lib (transactions)', function () {
       '032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63d',
       '0216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2a',
       '039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18f'
-    ].map(function (q) { return bitcoin.ECPair.fromPublicKeyBuffer(Buffer.from(q, 'hex')) })
+    ].map(function (q) { return bitcoin.ECPair.fromPublicKey(Buffer.from(q, 'hex')) })
 
     var tx = bitcoin.Transaction.fromHex(txHex)
 
@@ -241,7 +240,7 @@ describe('bitcoinjs-lib (transactions)', function () {
       var ss = bitcoin.script.signature.decode(scriptSig.signature)
       var hash = tx.hashForSignature(i, prevOutScript, ss.hashType)
 
-      assert.strictEqual(scriptSig.pubKey.toString('hex'), keyPair.getPublicKeyBuffer().toString('hex'))
+      assert.strictEqual(scriptSig.pubKey.toString('hex'), keyPair.publicKey.toString('hex'))
       assert.strictEqual(keyPair.verify(hash, ss.signature), true)
     })
   })
diff --git a/test/transaction_builder.js b/test/transaction_builder.js
index 86f7eca..c5c7c1e 100644
--- a/test/transaction_builder.js
+++ b/test/transaction_builder.js
@@ -7,7 +7,6 @@ let bscript = require('../src/script')
 let btemplates = require('../src/templates')
 let ops = require('bitcoin-ops')
 
-let BigInteger = require('bigi')
 let ECPair = require('../src/ecpair')
 let Transaction = require('../src/transaction')
 let TransactionBuilder = require('../src/transaction_builder')
@@ -17,7 +16,7 @@ let fixtures = require('./fixtures/transaction_builder')
 
 // TODO: remove
 function getAddress (node) {
-  return baddress.toBase58Check(bcrypto.hash160(node.getPublicKeyBuffer()), NETWORKS.bitcoin.pubKeyHash)
+  return baddress.toBase58Check(bcrypto.hash160(node.publicKey), NETWORKS.bitcoin.pubKeyHash)
 }
 
 function construct (f, dontSign) {
@@ -89,7 +88,7 @@ function construct (f, dontSign) {
 
 describe('TransactionBuilder', function () {
   // constants
-  var keyPair = new ECPair(BigInteger.ONE)
+  var keyPair = ECPair.fromPrivateKey(Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex'))
   var scripts = [
     '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH',
     '1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP'
diff --git a/test/types.js b/test/types.js
index 832b32d..2dbc554 100644
--- a/test/types.js
+++ b/test/types.js
@@ -5,18 +5,6 @@ var types = require('../src/types')
 var typeforce = require('typeforce')
 
 describe('types', function () {
-  describe('BigInt/ECPoint', function () {
-    it('return true for duck types', function () {
-      assert(types.BigInt(new function BigInteger () {}()))
-      assert(types.ECPoint(new function Point () {}()))
-    })
-
-    it('return false for bad types', function () {
-      assert(!types.BigInt(new function NotABigInteger () {}()))
-      assert(!types.ECPoint(new function NotAPoint () {}()))
-    })
-  })
-
   describe('Buffer Hash160/Hash256', function () {
     var buffer20byte = Buffer.alloc(20)
     var buffer32byte = Buffer.alloc(32)