Browse Source

ec: decodeFrom now uses Buffers and handles errors

hk-custom-address
Daniel Cousens 11 years ago
parent
commit
24371425f9
  1. 60
      src/ec.js
  2. 10
      src/ecpubkey.js
  3. 29
      test/ec.js

60
src/ec.js

@ -2,6 +2,7 @@
// Ported loosely from BouncyCastle's Java EC code // Ported loosely from BouncyCastle's Java EC code
// Only Fp curves implemented for now // Only Fp curves implemented for now
var assert = require('assert')
var BigInteger = require('bigi') var BigInteger = require('bigi')
function ECFieldElementFp(q,x) { function ECFieldElementFp(q,x) {
@ -326,34 +327,43 @@ ECPointFp.prototype.getEncoded = function(compressed) {
return buffer return buffer
} }
ECPointFp.decodeFrom = function (curve, enc) { var SEVEN = BigInteger.valueOf(7)
var type = enc[0];
var dataLen = enc.length-1;
// Extract x and y as byte arrays ECPointFp.decodeFrom = function (curve, buffer) {
if (type == 4) { var type = buffer.readUInt8(0)
var xBa = enc.slice(1, 1 + dataLen/2), var compressed = type !== 0x04
yBa = enc.slice(1 + dataLen/2, 1 + dataLen), var x = BigInteger.fromBuffer(buffer.slice(1, 33))
x = BigInteger.fromBuffer(xBa), var y
y = BigInteger.fromBuffer(yBa);
} if (compressed) {
else { assert.equal(buffer.length, 33, 'Invalid sequence length')
var xBa = enc.slice(1), assert(type === 0x02 || type === 0x03, 'Invalid sequence tag')
x = BigInteger.fromBuffer(xBa),
p = curve.getQ(), var isYEven = type === 0x03
xCubedPlus7 = x.multiply(x).multiply(x).add(new BigInteger('7')).mod(p), var p = curve.getQ()
pPlus1Over4 = p.add(new BigInteger('1'))
.divide(new BigInteger('4')), // We precalculate (p + 1) / 4 where p is the field order
y = xCubedPlus7.modPow(pPlus1Over4,p); var P_OVER_FOUR = p.add(BigInteger.ONE).shiftRight(2)
if (y.mod(new BigInteger('2')).toString() != ''+(type % 2)) {
y = p.subtract(y) // 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, var Q = new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y))
curve.fromBigInteger(x),
curve.fromBigInteger(y)); return {
}; Q: Q,
compressed: compressed
}
}
ECPointFp.prototype.add2D = function (b) { ECPointFp.prototype.add2D = function (b) {
if(this.isInfinity()) return b; if(this.isInfinity()) return b;

10
src/ecpubkey.js

@ -21,14 +21,8 @@ function ECPubKey(Q, compressed) {
// Static constructors // Static constructors
ECPubKey.fromBuffer = function(buffer) { ECPubKey.fromBuffer = function(buffer) {
var type = buffer.readUInt8(0) var decode = ECPointFp.decodeFrom(ecparams.getCurve(), buffer)
assert(type >= 0x02 || type <= 0x04, 'Invalid public key') return new ECPubKey(decode.Q, decode.compressed)
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)
} }
ECPubKey.fromHex = function(hex) { ECPubKey.fromHex = function(hex) {

29
test/ec.js

@ -48,25 +48,22 @@ describe('ec', function() {
var buffer = new Buffer(f.hex, 'hex') var buffer = new Buffer(f.hex, 'hex')
var decoded = ECPointFp.decodeFrom(curve, buffer) var decoded = ECPointFp.decodeFrom(curve, buffer)
assert.equal(decoded.getX().toBigInteger().toString(), f.x) assert.equal(decoded.Q.getX().toBigInteger().toString(), f.x)
assert.equal(decoded.getY().toBigInteger().toString(), f.y) assert.equal(decoded.Q.getY().toBigInteger().toString(), f.y)
assert.equal(decoded.compressed, f.compressed)
// TODO
// assert.equal(decoded.compressed, f.compressed)
}) })
}) })
// FIXME fixtures.invalid.ECPointFp.forEach(function(f) {
// fixtures.invalid.ECPointFp.forEach(function(f) { it('throws on ' + f.description, function() {
// it('throws on ' + f.description, function() { var curve = ecparams.getCurve()
// var curve = ecparams.getCurve() var buffer = new Buffer(f.hex, 'hex')
// var buffer = new Buffer(f.hex, 'hex')
// assert.throws(function() {
// assert.throws(function() { ECPointFp.decodeFrom(curve, buffer)
// ECPointFp.decodeFrom(curve, buffer) })
// }) })
// }) })
// })
}) })
}) })
}) })

Loading…
Cancel
Save