From 5fc4ad4e87106d247e5768ba0ec6dd03e1c9de2a Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Mon, 30 Dec 2013 22:15:01 -0500 Subject: [PATCH] Support compressed public keys in PrivateKey.js --- PrivateKey.js | 48 ++++++++++++++++++++++++++++++++++++++++++++-- test/PrivateKey.js | 15 +++++++++++++++ test/basic.js | 2 +- 3 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 test/PrivateKey.js diff --git a/PrivateKey.js b/PrivateKey.js index 2e55af6..3bcba59 100644 --- a/PrivateKey.js +++ b/PrivateKey.js @@ -3,8 +3,11 @@ require('classtool'); function ClassSpec(b) { var superclass = b.superclass || require('./util/VersionedData').class(); - function PrivateKey() { + //compressed is true if public key is compressed; false otherwise + function PrivateKey(version, buf, compressed) { PrivateKey.super(this, arguments); + if (compressed !== undefined) + this.compressed(compressed); }; PrivateKey.superclass = superclass; @@ -13,11 +16,52 @@ function ClassSpec(b) { PrivateKey.prototype.validate = function() { this.doAsBinary(function() { PrivateKey.super(this, 'validate', arguments); - if (this.data.length < 32 || this.data.length > 33) + if (this.data.length < 32 || (this.data.length > 1+32 && !this.compressed()) || (this.data.length==1+32 && this.data[1+32+1-1]!=1) || this.data.length>1+32+1) throw new Error('invalid data length'); }); }; + // get or set the payload data (as a Buffer object) + // overloaded from VersionedData + PrivateKey.prototype.payload = function(data) { + if(data) { + this.doAsBinary(function() {data.copy(this.data,1);}); + return data; + } + var buf=this.as('binary'); + if (buf.length==1+32+1) + return buf.slice(1,1+32); + else if (buf.length==1+32) + return buf.slice(1); + }; + + // get or set whether the corresponding public key is compressed + PrivateKey.prototype.compressed = function(compressed) { + if (compressed !== undefined) { + this.doAsBinary(function(){ + var len=1+32+1; + if (compressed) { + var data=new Buffer(len); + this.data.copy(data); + this.data=data; + this.data[len-1]=1; + } else { + this.data=this.data.slice(0,len-1); + } + }); + } + else { + var len=1+32+1; + var data=this.as('binary'); + if (data.length==len && data[len-1]==1) + return true; + else if (data.length==len-1) + return false; + else + throw new Error('invalid private key'); + } + }; + return PrivateKey; }; module.defineClass(ClassSpec); diff --git a/test/PrivateKey.js b/test/PrivateKey.js new file mode 100644 index 0000000..2bfae56 --- /dev/null +++ b/test/PrivateKey.js @@ -0,0 +1,15 @@ +var assert = require('assert'); +var PrivateKey = require('../PrivateKey').class(); +var networks = require('../networks'); + +describe('PrivateKey', function(){ + describe('#as', function(){ + it('should convert hex testnet private key with compressed public key to base58check format', function() { + var hex='b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3'; + var buf=new Buffer(hex,'hex'); + var result='cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH'; + var privkey=new PrivateKey(networks.testnet.keySecret,buf,true); + assert.equal(privkey.as('base58'),result); + }); + }); +}); diff --git a/test/basic.js b/test/basic.js index 3b0f6ff..1ed1148 100644 --- a/test/basic.js +++ b/test/basic.js @@ -56,7 +56,7 @@ function test_decode_priv(b58, payload, isTestnet, isCompressed) var privkey = new PrivateKey(b58); assert.equal(version, privkey.version()); - assert.equal(buf.toString(), privkey.payload().toString()); + assert.equal(buf_pl.toString(), privkey.payload().toString()); } function test_decode_pub(b58, payload, isTestnet, addrType)