ec: decodeFrom now uses Buffers and handles errors
This commit is contained in:
parent
a3f691bf7c
commit
24371425f9
3 changed files with 50 additions and 49 deletions
60
src/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;
|
||||||
|
|
|
@ -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
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…
Add table
Reference in a new issue