diff --git a/src/ec.js b/src/ec.js
index 24d488c..22705e9 100644
--- a/src/ec.js
+++ b/src/ec.js
@@ -2,6 +2,7 @@
 // Ported loosely from BouncyCastle's Java EC code
 // Only Fp curves implemented for now
 
+var assert = require('assert')
 var BigInteger = require('bigi')
 
 function ECFieldElementFp(q,x) {
@@ -326,34 +327,43 @@ ECPointFp.prototype.getEncoded = function(compressed) {
   return buffer
 }
 
-ECPointFp.decodeFrom = function (curve, enc) {
-  var type = enc[0];
-  var dataLen = enc.length-1;
+var SEVEN = BigInteger.valueOf(7)
 
-  // Extract x and y as byte arrays
-  if (type == 4) {
-    var xBa = enc.slice(1, 1 + dataLen/2),
-        yBa = enc.slice(1 + dataLen/2, 1 + dataLen),
-        x = BigInteger.fromBuffer(xBa),
-        y = BigInteger.fromBuffer(yBa);
-  }
-  else {
-    var xBa = enc.slice(1),
-        x = BigInteger.fromBuffer(xBa),
-        p = curve.getQ(),
-        xCubedPlus7 = x.multiply(x).multiply(x).add(new BigInteger('7')).mod(p),
-        pPlus1Over4 = p.add(new BigInteger('1'))
-                       .divide(new BigInteger('4')),
-        y = xCubedPlus7.modPow(pPlus1Over4,p);
-    if (y.mod(new BigInteger('2')).toString() != ''+(type % 2)) {
-        y = p.subtract(y)
-    }
+ECPointFp.decodeFrom = function (curve, buffer) {
+  var type = buffer.readUInt8(0)
+  var compressed = type !== 0x04
+  var x = BigInteger.fromBuffer(buffer.slice(1, 33))
+  var y
+
+  if (compressed) {
+    assert.equal(buffer.length, 33, 'Invalid sequence length')
+    assert(type === 0x02 || type === 0x03, 'Invalid sequence tag')
+
+    var isYEven = type === 0x03
+    var p = curve.getQ()
+
+    // We precalculate (p + 1) / 4 where p is the field order
+    var P_OVER_FOUR = p.add(BigInteger.ONE).shiftRight(2)
+
+    // Convert x to point
+    var alpha = x.square().multiply(x).add(SEVEN).mod(p)
+    var beta = alpha.modPow(P_OVER_FOUR, p)
+
+    y = (beta.isEven() ? !isYEven : isYEven) ? beta : p.subtract(beta)
+
+  } else {
+    assert.equal(buffer.length, 65, 'Invalid sequence length')
+
+    y = BigInteger.fromBuffer(buffer.slice(33))
   }
 
-  return new ECPointFp(curve,
-                       curve.fromBigInteger(x),
-                       curve.fromBigInteger(y));
-};
+  var Q = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y))
+
+  return {
+    Q: Q,
+    compressed: compressed
+  }
+}
 
 ECPointFp.prototype.add2D = function (b) {
   if(this.isInfinity()) return b;
diff --git a/src/ecpubkey.js b/src/ecpubkey.js
index 0c7dafb..bd2e7e8 100644
--- a/src/ecpubkey.js
+++ b/src/ecpubkey.js
@@ -21,14 +21,8 @@ function ECPubKey(Q, compressed) {
 
 // Static constructors
 ECPubKey.fromBuffer = function(buffer) {
-  var type = buffer.readUInt8(0)
-  assert(type >= 0x02 || type <= 0x04, 'Invalid public key')
-
-  var compressed = (type !== 0x04)
-  assert.strictEqual(buffer.length, compressed ? 33 : 65, 'Invalid public key')
-
-  var Q = ECPointFp.decodeFrom(ecparams.getCurve(), buffer)
-  return new ECPubKey(Q, compressed)
+  var decode = ECPointFp.decodeFrom(ecparams.getCurve(), buffer)
+  return new ECPubKey(decode.Q, decode.compressed)
 }
 
 ECPubKey.fromHex = function(hex) {
diff --git a/test/ec.js b/test/ec.js
index a547ea1..9cd74c8 100644
--- a/test/ec.js
+++ b/test/ec.js
@@ -48,25 +48,22 @@ describe('ec', function() {
           var buffer = new Buffer(f.hex, 'hex')
 
           var decoded = ECPointFp.decodeFrom(curve, buffer)
-          assert.equal(decoded.getX().toBigInteger().toString(), f.x)
-          assert.equal(decoded.getY().toBigInteger().toString(), f.y)
-
-          // TODO
-//          assert.equal(decoded.compressed, f.compressed)
+          assert.equal(decoded.Q.getX().toBigInteger().toString(), f.x)
+          assert.equal(decoded.Q.getY().toBigInteger().toString(), f.y)
+          assert.equal(decoded.compressed, f.compressed)
         })
       })
 
-      // FIXME
-  //    fixtures.invalid.ECPointFp.forEach(function(f) {
-  //      it('throws on ' + f.description, function() {
-  //        var curve = ecparams.getCurve()
-  //        var buffer = new Buffer(f.hex, 'hex')
-  //
-  //        assert.throws(function() {
-  //          ECPointFp.decodeFrom(curve, buffer)
-  //        })
-  //      })
-  //    })
+      fixtures.invalid.ECPointFp.forEach(function(f) {
+        it('throws on ' + f.description, function() {
+          var curve = ecparams.getCurve()
+          var buffer = new Buffer(f.hex, 'hex')
+
+          assert.throws(function() {
+            ECPointFp.decodeFrom(curve, buffer)
+          })
+        })
+      })
     })
   })
 })