ECPubKey/ECKey: separate to two files

This commit is contained in:
Daniel Cousens 2014-05-13 16:44:29 +10:00
parent 05e0d08098
commit e27c97a791
8 changed files with 164 additions and 151 deletions

View file

@ -4,15 +4,12 @@ var ecdsa = require('./ecdsa')
var networks = require('./networks') var networks = require('./networks')
var secureRandom = require('secure-random') var secureRandom = require('secure-random')
var Address = require('./address') var BigInteger = require('bigi')
var crypto = require('./crypto') var ECPubKey = require('./ecpubkey')
var sec = require('./sec') var sec = require('./sec')
var ecparams = sec('secp256k1') var ecparams = sec('secp256k1')
var BigInteger = require('bigi')
var ECPointFp = require('./ec').ECPointFp
function ECKey(D, compressed) { function ECKey(D, compressed) {
assert(D.compareTo(BigInteger.ZERO) > 0, 'Private key must be greater than 0') assert(D.compareTo(BigInteger.ZERO) > 0, 'Private key must be greater than 0')
assert(D.compareTo(ecparams.getN()) < 0, 'Private key must be less than the curve order') assert(D.compareTo(ecparams.getN()) < 0, 'Private key must be less than the curve order')
@ -31,6 +28,7 @@ ECKey.fromBuffer = function(buffer, compressed) {
var D = BigInteger.fromBuffer(buffer) var D = BigInteger.fromBuffer(buffer)
return new ECKey(D, compressed) return new ECKey(D, compressed)
} }
ECKey.fromHex = function(hex, compressed) { ECKey.fromHex = function(hex, compressed) {
return ECKey.fromBuffer(new Buffer(hex, 'hex'), compressed) return ECKey.fromBuffer(new Buffer(hex, 'hex'), compressed)
} }
@ -67,6 +65,7 @@ ECKey.prototype.sign = function(hash) {
ECKey.prototype.toBuffer = function() { ECKey.prototype.toBuffer = function() {
return this.D.toBuffer(32) return this.D.toBuffer(32)
} }
ECKey.prototype.toHex = function() { ECKey.prototype.toHex = function() {
return this.toBuffer().toString('hex') return this.toBuffer().toString('hex')
} }
@ -82,53 +81,4 @@ ECKey.prototype.toWIF = function(version) {
return base58check.encode(buffer, version) return base58check.encode(buffer, version)
} }
////////////////////////////////////////////////////// module.exports = ECKey
function ECPubKey(Q, compressed) {
assert(Q instanceof ECPointFp, 'Q must be an ECPointFP')
if (compressed == undefined) compressed = true
assert.strictEqual(typeof compressed, 'boolean', 'Invalid compression flag')
this.compressed = compressed
this.Q = Q
}
// 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)
}
ECPubKey.fromHex = function(hex) {
return ECPubKey.fromBuffer(new Buffer(hex, 'hex'))
}
// Operations
ECPubKey.prototype.verify = function(hash, sig) {
return ecdsa.verify(hash, sig, this.Q)
}
ECPubKey.prototype.getAddress = function(version) {
version = version || networks.bitcoin.pubKeyHash
return new Address(crypto.hash160(this.toBuffer()), version)
}
// Export functions
ECPubKey.prototype.toBuffer = function() {
return new Buffer(this.Q.getEncoded(this.compressed))
}
ECPubKey.prototype.toHex = function() {
return this.toBuffer().toString('hex')
}
module.exports = {
ECKey: ECKey,
ECPubKey: ECPubKey
}

58
src/ecpubkey.js Normal file
View file

@ -0,0 +1,58 @@
var assert = require('assert')
var crypto = require('./crypto')
var ecdsa = require('./ecdsa')
var networks = require('./networks')
var Address = require('./address')
var ECPointFp = require('./ec').ECPointFp
var sec = require('./sec')
var ecparams = sec('secp256k1')
function ECPubKey(Q, compressed) {
assert(Q instanceof ECPointFp, 'Q must be an ECPointFP')
if (compressed == undefined) compressed = true
assert.strictEqual(typeof compressed, 'boolean', 'Invalid compression flag')
this.compressed = compressed
this.Q = Q
}
// 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)
}
ECPubKey.fromHex = function(hex) {
return ECPubKey.fromBuffer(new Buffer(hex, 'hex'))
}
// Operations
ECPubKey.prototype.getAddress = function(version) {
version = version || networks.bitcoin.pubKeyHash
return new Address(crypto.hash160(this.toBuffer()), version)
}
ECPubKey.prototype.verify = function(hash, sig) {
return ecdsa.verify(hash, sig, this.Q)
}
// Export functions
ECPubKey.prototype.toBuffer = function() {
return new Buffer(this.Q.getEncoded(this.compressed))
}
ECPubKey.prototype.toHex = function() {
return this.toBuffer().toString('hex')
}
module.exports = ECPubKey

View file

@ -5,8 +5,8 @@ var convert = require('./convert')
var Address = require('./address') var Address = require('./address')
var BigInteger = require('bigi') var BigInteger = require('bigi')
var crypto = require('./crypto') var crypto = require('./crypto')
var ECKey = require('./eckey').ECKey var ECKey = require('./eckey')
var ECPubKey = require('./eckey').ECPubKey var ECPubKey = require('./ecpubkey')
var networks = require('./networks') var networks = require('./networks')
var sec = require('./sec') var sec = require('./sec')

View file

@ -11,9 +11,9 @@ module.exports = {
crypto: require('./crypto'), crypto: require('./crypto'),
ec: ec, ec: ec,
ecdsa: require('./ecdsa'), ecdsa: require('./ecdsa'),
ECKey: Key.ECKey, ECKey: require('./eckey'),
ECPointFp: ec.ECPointFp, ECPointFp: ec.ECPointFp,
ECPubKey: Key.ECPubKey, ECPubKey: require('./ecpubkey'),
Message: require('./message'), Message: require('./message'),
Opcode: require('./opcode'), Opcode: require('./opcode'),
HDWallet: require('./hdwallet'), HDWallet: require('./hdwallet'),

View file

@ -3,7 +3,7 @@ var Address = require('./address')
var bufferutils = require('./bufferutils') var bufferutils = require('./bufferutils')
var crypto = require('./crypto') var crypto = require('./crypto')
var ecdsa = require('./ecdsa') var ecdsa = require('./ecdsa')
var ECPubKey = require('./eckey').ECPubKey var ECPubKey = require('./ecpubkey')
// FIXME: incompatible with other networks (Litecoin etc) // FIXME: incompatible with other networks (Litecoin etc)
var MAGIC_PREFIX = new Buffer('\x18Bitcoin Signed Message:\n') var MAGIC_PREFIX = new Buffer('\x18Bitcoin Signed Message:\n')

View file

@ -7,7 +7,7 @@ var bufferutils = require('./bufferutils')
var Script = require('./script') var Script = require('./script')
var convert = require('./convert') var convert = require('./convert')
var crypto = require('./crypto') var crypto = require('./crypto')
var ECKey = require('./eckey').ECKey var ECKey = require('./eckey')
var ecdsa = require('./ecdsa') var ecdsa = require('./ecdsa')
function Transaction(doc) { function Transaction(doc) {

View file

@ -51,77 +51,6 @@ describe('ECKey', function() {
}) })
}) })
describe('toAddress', function() {
var privkeys = [
'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458',
'1111111111111111111111111111111111111111111111111111111111111111',
'18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725'
]
// compressed pubkeys
var cpubkeys = [
'024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992',
'034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa',
'0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352'
]
var pubkeys = cpubkeys.map(function(x) {
var pk = ECPubKey.fromHex(x)
pk.compressed = false
return pk.toHex()
})
it('bitcoin', function() {
var addresses = [
'19SgmoUj4xowEjwtXvNAtYTAgbvR9iBCui',
'1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a',
'16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM'
]
var compressedAddresses = [
'1AA4sjKW2aUmbtN3MtegdvhYtDBbDEke1q',
'1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9',
'1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs',
]
for (var i = 0; i < addresses.length; ++i) {
var pub = ECPubKey.fromHex(pubkeys[i])
var cpub = ECPubKey.fromHex(cpubkeys[i])
cpub.compressed = true
var addr = addresses[i]
var caddr = compressedAddresses[i]
assert.equal(pub.getAddress().toString(), addr)
assert.equal(cpub.getAddress().toString(), caddr)
}
})
it('testnet', function() {
var addresses = [
'19SgmoUj4xowEjwtXvNAtYTAgbvR9iBCui',
'1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a',
'16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM'
]
var compressedAddresses = [
'1AA4sjKW2aUmbtN3MtegdvhYtDBbDEke1q',
'1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9',
'1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs',
]
for (var i = 0; i < addresses.length; ++i) {
var pub = ECPubKey.fromHex(pubkeys[i])
var cpub = ECPubKey.fromHex(cpubkeys[i])
cpub.compressed = true
var addr = addresses[i]
var caddr = compressedAddresses[i]
assert.equal(pub.getAddress().toString(), addr)
assert.equal(cpub.getAddress().toString(), caddr)
}
})
})
describe('signing', function() { describe('signing', function() {
var hpriv = 'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458' var hpriv = 'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458'
var hcpub = '024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992' var hcpub = '024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992'
@ -151,23 +80,4 @@ describe('ECKey', function() {
assert(!priv2.pub.verify(hash, signature)) assert(!priv2.pub.verify(hash, signature))
}) })
}) })
describe('output of ECPubKey', function() {
var hcpub = '024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992'
var hpub = '044b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea81199283fbec990dad6fb98f93f712d50cb874dd717de6a184158d63886dda3090f566'
it('using toHex should support compression', function() {
var pub = ECPubKey.fromHex(hcpub)
assert.equal(pub.toHex(), hcpub)
assert.equal(pub.compressed, true)
})
it('using toHex should support uncompressed', function() {
var pub = ECPubKey.fromHex(hpub)
assert.equal(pub.toHex(), hpub)
assert.equal(pub.compressed, false)
})
})
}) })

95
test/ecpubkey.js Normal file
View file

@ -0,0 +1,95 @@
var assert = require('assert')
var ECPubKey = require('..').ECPubKey
describe('ECPubKey', function() {
describe('toBuffer/toHex', function() {
var hcpub = '024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992'
var hpub = '044b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea81199283fbec990dad6fb98f93f712d50cb874dd717de6a184158d63886dda3090f566'
it('using toHex should support compression', function() {
var pub = ECPubKey.fromHex(hcpub)
assert.equal(pub.toHex(), hcpub)
assert.equal(pub.compressed, true)
})
it('using toHex should support uncompressed', function() {
var pub = ECPubKey.fromHex(hpub)
assert.equal(pub.toHex(), hpub)
assert.equal(pub.compressed, false)
})
})
describe('getAddress', function() {
var privkeys = [
'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458',
'1111111111111111111111111111111111111111111111111111111111111111',
'18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725'
]
// compressed pubkeys
var cpubkeys = [
'024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992',
'034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa',
'0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352'
]
var pubkeys = cpubkeys.map(function(x) {
var pk = ECPubKey.fromHex(x)
pk.compressed = false
return pk.toHex()
})
it('bitcoin', function() {
var addresses = [
'19SgmoUj4xowEjwtXvNAtYTAgbvR9iBCui',
'1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a',
'16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM'
]
var compressedAddresses = [
'1AA4sjKW2aUmbtN3MtegdvhYtDBbDEke1q',
'1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9',
'1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs',
]
for (var i = 0; i < addresses.length; ++i) {
var pub = ECPubKey.fromHex(pubkeys[i])
var cpub = ECPubKey.fromHex(cpubkeys[i])
cpub.compressed = true
var addr = addresses[i]
var caddr = compressedAddresses[i]
assert.equal(pub.getAddress().toString(), addr)
assert.equal(cpub.getAddress().toString(), caddr)
}
})
it('testnet', function() {
var addresses = [
'19SgmoUj4xowEjwtXvNAtYTAgbvR9iBCui',
'1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a',
'16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM'
]
var compressedAddresses = [
'1AA4sjKW2aUmbtN3MtegdvhYtDBbDEke1q',
'1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9',
'1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs',
]
for (var i = 0; i < addresses.length; ++i) {
var pub = ECPubKey.fromHex(pubkeys[i])
var cpub = ECPubKey.fromHex(cpubkeys[i])
cpub.compressed = true
var addr = addresses[i]
var caddr = compressedAddresses[i]
assert.equal(pub.getAddress().toString(), addr)
assert.equal(cpub.getAddress().toString(), caddr)
}
})
})
})