3 changed files with 164 additions and 1 deletions
@ -0,0 +1,67 @@ |
|||||
|
var point = require('./point'); |
||||
|
var bn = require('./bn'); |
||||
|
|
||||
|
var Pubkey = function(p) { |
||||
|
this.p = p; |
||||
|
}; |
||||
|
|
||||
|
Pubkey.prototype.fromDER = function(buf) { |
||||
|
if (buf[0] == 0x04) { |
||||
|
var xbuf = buf.slice(1, 33); |
||||
|
var ybuf = buf.slice(33, 65); |
||||
|
if (xbuf.length !== 32 || ybuf.length !== 32 || buf.length !== 65) |
||||
|
throw new Error('pubkey: Length of x and y must be 32 bytes'); |
||||
|
var x = bn(xbuf); |
||||
|
var y = bn(ybuf); |
||||
|
this.p = point(x, y); |
||||
|
} else if (buf[0] == 0x03) { |
||||
|
var xbuf = buf.slice(1); |
||||
|
var x = bn(xbuf); |
||||
|
this.fromX(true, x); |
||||
|
} else if (buf[0] == 0x02) { |
||||
|
var xbuf = buf.slice(1); |
||||
|
var x = bn(xbuf); |
||||
|
this.fromX(false, x); |
||||
|
} else { |
||||
|
throw new Error('pubkey: Invalid DER format pubkey'); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
Pubkey.prototype.fromString = function(str) { |
||||
|
this.fromDER(new Buffer(str, 'hex')); |
||||
|
}; |
||||
|
|
||||
|
Pubkey.prototype.fromX = function(odd, x) { |
||||
|
if (typeof odd !== 'boolean') |
||||
|
throw new Error('pubkey: Must specify whether y is odd or not (true or false)'); |
||||
|
this.p = point.fromX(odd, x); |
||||
|
}; |
||||
|
|
||||
|
Pubkey.prototype.toDER = function(compressed) { |
||||
|
if (typeof compressed !== 'boolean') |
||||
|
throw new Error('pubkey: Must specify whether the public key is compressed or not (true or false)'); |
||||
|
|
||||
|
var x = this.p.getX(); |
||||
|
var y = this.p.getY(); |
||||
|
|
||||
|
var xbuf = x.toBuffer({size: 32}); |
||||
|
var ybuf = y.toBuffer({size: 32}); |
||||
|
|
||||
|
if (!compressed) { |
||||
|
var prefix = new Buffer([0x04]); |
||||
|
return Buffer.concat([prefix, xbuf, ybuf]); |
||||
|
} else { |
||||
|
var odd = ybuf[ybuf.length - 1] % 2; |
||||
|
if (odd) |
||||
|
var prefix = new Buffer([0x03]); |
||||
|
else |
||||
|
var prefix = new Buffer([0x02]); |
||||
|
return Buffer.concat([prefix, xbuf]); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
Pubkey.prototype.toString = function() { |
||||
|
return this.toDER(true).toString('hex'); |
||||
|
}; |
||||
|
|
||||
|
module.exports = Pubkey; |
@ -0,0 +1,96 @@ |
|||||
|
var should = require('chai').should(); |
||||
|
var pubkey = require('../lib/pubkey'); |
||||
|
var point = require('../lib/point'); |
||||
|
var bn = require('../lib/bn'); |
||||
|
|
||||
|
describe('pubkey', function() { |
||||
|
|
||||
|
it('should create a blank public key', function() { |
||||
|
var pk = new pubkey(); |
||||
|
should.exist(pk); |
||||
|
}); |
||||
|
|
||||
|
it('should create a public key with a point', function() { |
||||
|
var p = point(); |
||||
|
var pk = new pubkey(p); |
||||
|
should.exist(pk.p); |
||||
|
}); |
||||
|
|
||||
|
describe('#fromDER', function() { |
||||
|
|
||||
|
it('should parse this uncompressed public key', function() { |
||||
|
var pk = new pubkey(); |
||||
|
pk.fromDER(new Buffer('041ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341', 'hex')); |
||||
|
pk.p.getX().toString(16).should.equal('1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a'); |
||||
|
pk.p.getY().toString(16).should.equal('7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341'); |
||||
|
}); |
||||
|
|
||||
|
it('should parse this compressed public key', function() { |
||||
|
var pk = new pubkey(); |
||||
|
pk.fromDER(new Buffer('031ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a', 'hex')); |
||||
|
pk.p.getX().toString(16).should.equal('1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a'); |
||||
|
pk.p.getY().toString(16).should.equal('7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341'); |
||||
|
}); |
||||
|
|
||||
|
it('should throw an error on this invalid public key', function() { |
||||
|
var pk = new pubkey(); |
||||
|
(function() { |
||||
|
pk.fromDER(new Buffer('091ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a', 'hex')); |
||||
|
}).should.throw(); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
describe('#fromString', function() { |
||||
|
|
||||
|
it('should parse this known valid public key', function() { |
||||
|
pk = new pubkey(); |
||||
|
pk.fromString('041ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341'); |
||||
|
pk.p.getX().toString(16).should.equal('1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a'); |
||||
|
pk.p.getY().toString(16).should.equal('7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341'); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
describe('#fromX', function() { |
||||
|
|
||||
|
it('should create this known public key', function() { |
||||
|
var x = bn.fromBuffer(new Buffer('1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a', 'hex')); |
||||
|
var pk = new pubkey(); |
||||
|
pk.fromX(true, x); |
||||
|
pk.p.getX().toString(16).should.equal('1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a'); |
||||
|
pk.p.getY().toString(16).should.equal('7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341'); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
describe('#toDER', function() { |
||||
|
|
||||
|
it('should return this compressed DER format', function() { |
||||
|
var x = bn.fromBuffer(new Buffer('1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a', 'hex')); |
||||
|
var pk = new pubkey(); |
||||
|
pk.fromX(true, x); |
||||
|
pk.toDER(true).toString('hex').should.equal('031ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a'); |
||||
|
}); |
||||
|
|
||||
|
it('should return this uncompressed DER format', function() { |
||||
|
var x = bn.fromBuffer(new Buffer('1ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a', 'hex')); |
||||
|
var pk = new pubkey(); |
||||
|
pk.fromX(true, x); |
||||
|
pk.toDER(false).toString('hex').should.equal('041ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a7baad41d04514751e6851f5304fd243751703bed21b914f6be218c0fa354a341'); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
describe('#toString', function() { |
||||
|
|
||||
|
it('should print this known public key', function() { |
||||
|
var hex = '031ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a'; |
||||
|
var pk = new pubkey(); |
||||
|
pk.fromString(hex); |
||||
|
pk.toString().should.equal(hex); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
}); |
Loading…
Reference in new issue