mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 12:15:51 +00:00
Use es7 decorator syntax for cached methods
This commit is contained in:
@@ -1,14 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const util = require('util');
|
||||
const elliptic = require('elliptic');
|
||||
const {utils: {parseBytes}} = elliptic;
|
||||
const Ed25519 = elliptic.eddsa('ed25519');
|
||||
const {KeyPair, KeyType} = require('./keypair');
|
||||
const {
|
||||
Sha512,
|
||||
cachedProperty
|
||||
} = require('./utils');
|
||||
const {Sha512, cached} = require('./utils');
|
||||
|
||||
/*
|
||||
@param {Array} seed bytes
|
||||
@@ -17,51 +13,51 @@ function deriveEdKeyPairSeed(seed) {
|
||||
return new Sha512().add(seed).first256();
|
||||
}
|
||||
|
||||
/*
|
||||
* @class
|
||||
*/
|
||||
function Ed25519Pair() {
|
||||
KeyPair.apply(this, arguments);
|
||||
this.type = KeyType.ed25519;
|
||||
}
|
||||
|
||||
util.inherits(Ed25519Pair, KeyPair);
|
||||
|
||||
/**
|
||||
* @param {Seed} publicKey - public key in canonical form (0xED + 32 bytes)
|
||||
* @return {Ed25519Pair} key pair
|
||||
*/
|
||||
Ed25519Pair.fromPublic = function(publicKey) {
|
||||
return new Ed25519Pair({pubBytes: parseBytes(publicKey)});
|
||||
};
|
||||
|
||||
Ed25519Pair.prototype.sign = function(message) {
|
||||
return this.key().sign(message).toBytes();
|
||||
};
|
||||
|
||||
Ed25519Pair.prototype.verify = function(message, signature) {
|
||||
return this.key().verify(message, signature);
|
||||
};
|
||||
|
||||
cachedProperty(Ed25519Pair, function key() {
|
||||
if (this.seedBytes) {
|
||||
const seed256 = deriveEdKeyPairSeed(this.seedBytes);
|
||||
return Ed25519.keyFromSecret(seed256);
|
||||
class Ed25519Pair extends KeyPair {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
this.type = KeyType.ed25519;
|
||||
}
|
||||
return Ed25519.keyFromPublic(this.pubKeyCanonicalBytes().slice(1));
|
||||
});
|
||||
|
||||
cachedProperty(Ed25519Pair, function pubKeyCanonicalBytes() {
|
||||
return [0xED].concat(this.key().pubBytes());
|
||||
});
|
||||
/**
|
||||
* @param {String|Array} publicKey - public key in canonical form
|
||||
* (0xED + 32 bytes)
|
||||
* @return {Ed25519Pair} key pair
|
||||
*/
|
||||
static fromPublic(publicKey) {
|
||||
return new Ed25519Pair({pubBytes: parseBytes(publicKey)});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<Number>} seedBytes - A 128 bit seed
|
||||
* @return {Ed25519Pair} key pair
|
||||
*/
|
||||
Ed25519Pair.fromSeed = function(seedBytes) {
|
||||
return new Ed25519Pair({seedBytes});
|
||||
};
|
||||
/**
|
||||
* @param {Array<Number>} seedBytes - A 128 bit seed
|
||||
* @return {Ed25519Pair} key pair
|
||||
*/
|
||||
static fromSeed(seedBytes) {
|
||||
return new Ed25519Pair({seedBytes});
|
||||
}
|
||||
|
||||
sign(message) {
|
||||
return this.key().sign(message).toBytes();
|
||||
}
|
||||
|
||||
verify(message, signature) {
|
||||
return this.key().verify(message, signature);
|
||||
}
|
||||
|
||||
@cached
|
||||
key() {
|
||||
if (this.seedBytes) {
|
||||
const seed256 = deriveEdKeyPairSeed(this.seedBytes);
|
||||
return Ed25519.keyFromSecret(seed256);
|
||||
}
|
||||
return Ed25519.keyFromPublic(this.pubKeyCanonicalBytes().slice(1));
|
||||
}
|
||||
|
||||
@cached
|
||||
pubKeyCanonicalBytes() {
|
||||
return [0xED].concat(this.key().pubBytes());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Ed25519Pair
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
const codec = require('ripple-address-codec');
|
||||
const {
|
||||
bytesToHex,
|
||||
cachedProperty,
|
||||
cached,
|
||||
isVirtual,
|
||||
createAccountID
|
||||
} = require('./utils');
|
||||
@@ -13,51 +13,56 @@ const KeyType = {
|
||||
ed25519: 'ed25519'
|
||||
};
|
||||
|
||||
function KeyPair({seedBytes, pubBytes}) {
|
||||
this.seedBytes = seedBytes;
|
||||
this._pubKeyCanonicalBytes = pubBytes;
|
||||
class KeyPair {
|
||||
constructor({seedBytes, pubBytes}) {
|
||||
this.seedBytes = seedBytes;
|
||||
this._pubKeyCanonicalBytes = pubBytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param {Array} message
|
||||
*/
|
||||
@isVirtual
|
||||
sign() {}
|
||||
|
||||
/*
|
||||
* @param {Array<Byte>} message
|
||||
* @param {Array<Byte>} signature
|
||||
*/
|
||||
@isVirtual
|
||||
verify() {}
|
||||
|
||||
/*
|
||||
* @return {Array<Byte>} of bytes, in canonical form, for signing
|
||||
*/
|
||||
@isVirtual
|
||||
pubKeyCanonicalBytes() {}
|
||||
|
||||
@cached
|
||||
pubKeyHex() {
|
||||
return bytesToHex(this.pubKeyCanonicalBytes());
|
||||
}
|
||||
|
||||
@cached
|
||||
accountBytes() {
|
||||
return createAccountID(this.pubKeyCanonicalBytes());
|
||||
}
|
||||
|
||||
@cached
|
||||
accountID() {
|
||||
return codec.encodeAccountID(this.accountBytes());
|
||||
}
|
||||
|
||||
@cached
|
||||
seed() {
|
||||
return codec.encodeSeed(this.seedBytes, this.type);
|
||||
}
|
||||
|
||||
signHex(message) {
|
||||
return bytesToHex(this.sign(message));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@param {Array} message
|
||||
@virtual
|
||||
*/
|
||||
KeyPair.prototype.sign = isVirtual;
|
||||
|
||||
|
||||
/*
|
||||
@param {Array<Byte>} message
|
||||
@param {Array<Byte>} signature
|
||||
@virtual
|
||||
*/
|
||||
KeyPair.prototype.verify = isVirtual;
|
||||
|
||||
/*
|
||||
@return {Array<Byte>} of bytes, in canonical form, for signing
|
||||
@virtual
|
||||
*/
|
||||
KeyPair.prototype.pubKeyCanonicalBytes = isVirtual;
|
||||
|
||||
cachedProperty(KeyPair, function pubKeyHex() {
|
||||
return bytesToHex(this.pubKeyCanonicalBytes());
|
||||
});
|
||||
|
||||
cachedProperty(KeyPair, function accountBytes() {
|
||||
return createAccountID(this.pubKeyCanonicalBytes());
|
||||
});
|
||||
|
||||
cachedProperty(KeyPair, function accountID() {
|
||||
return codec.encodeAccountID(this.accountBytes());
|
||||
});
|
||||
|
||||
cachedProperty(KeyPair, function seed() {
|
||||
return codec.encodeSeed(this.seedBytes, this.type);
|
||||
});
|
||||
|
||||
KeyPair.prototype.signHex = function(message) {
|
||||
return bytesToHex(this.sign(message));
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
KeyPair,
|
||||
KeyType
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const util = require('util');
|
||||
const elliptic = require('elliptic');
|
||||
const secp256k1 = elliptic.ec('secp256k1');
|
||||
const hashjs = require('hash.js');
|
||||
const {KeyPair, KeyType} = require('./keypair');
|
||||
const {
|
||||
Sha512,
|
||||
cachedProperty
|
||||
} = require('./utils');
|
||||
const {Sha512, cached} = require('./utils');
|
||||
|
||||
function deriveScalar(bytes, discrim) {
|
||||
const order = secp256k1.curve.n;
|
||||
@@ -65,65 +61,64 @@ function accountPublicFromPublicGenerator(publicGenBytes) {
|
||||
return offset.encodeCompressed();
|
||||
}
|
||||
|
||||
/*
|
||||
* @class
|
||||
*/
|
||||
function K256Pair({validator}) {
|
||||
KeyPair.apply(this, arguments);
|
||||
this.type = KeyType.secp256k1;
|
||||
this.validator = validator;
|
||||
class K256Pair extends KeyPair {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
this.type = KeyType.secp256k1;
|
||||
this.validator = options.validator;
|
||||
}
|
||||
|
||||
static fromSeed(seedBytes, opts={}) {
|
||||
return new K256Pair({seedBytes, validator: opts.validator});
|
||||
}
|
||||
|
||||
/*
|
||||
@param {Array<Byte>} message (bytes)
|
||||
*/
|
||||
sign(message) {
|
||||
return this._createSignature(message).toDER();
|
||||
}
|
||||
|
||||
_createSignature(message) {
|
||||
// The key.sign message silently discards options
|
||||
return this.key().sign(this.hashMessage(message), {canonical: true});
|
||||
}
|
||||
|
||||
/*
|
||||
@param {Array<Byte>} message - (bytes)
|
||||
@return {Array<Byte>} - 256 bit hash of the message
|
||||
*/
|
||||
hashMessage(message) {
|
||||
return hashjs.sha512().update(message).digest().slice(0, 32);
|
||||
}
|
||||
|
||||
/*
|
||||
@param {Array<Byte>} message - bytes
|
||||
@param {Array<Byte>} signature - DER encoded signature bytes
|
||||
*/
|
||||
verify(message, signature) {
|
||||
try {
|
||||
return this.key().verify(this.hashMessage(message), signature);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@cached
|
||||
key() {
|
||||
if (this.seedBytes) {
|
||||
const options = {validator: this.validator};
|
||||
return secp256k1.keyFromPrivate(deriveSecret(this.seedBytes, options));
|
||||
}
|
||||
return secp256k1.keyFromPublic(this.pubKeyCanonicalBytes());
|
||||
}
|
||||
|
||||
@cached
|
||||
pubKeyCanonicalBytes() {
|
||||
return this.key().getPublic().encodeCompressed();
|
||||
}
|
||||
}
|
||||
|
||||
util.inherits(K256Pair, KeyPair);
|
||||
|
||||
/*
|
||||
@param {Array<Byte>} message (bytes)
|
||||
*/
|
||||
K256Pair.prototype.sign = function(message) {
|
||||
return this._createSignature(message).toDER();
|
||||
};
|
||||
|
||||
K256Pair.prototype._createSignature = function(message) {
|
||||
// The key.sign message silently discards options
|
||||
return this.key().sign(this.hashMessage(message), {canonical: true});
|
||||
};
|
||||
|
||||
/*
|
||||
@param {Array<Byte>} message - (bytes)
|
||||
@return {Array<Byte>} - 256 bit hash of the message
|
||||
*/
|
||||
K256Pair.prototype.hashMessage = function(message) {
|
||||
return hashjs.sha512().update(message).digest().slice(0, 32);
|
||||
};
|
||||
|
||||
/*
|
||||
@param {Array<Byte>} message - bytes
|
||||
@param {Array<Byte>} signature - DER encoded signature bytes
|
||||
*/
|
||||
K256Pair.prototype.verify = function(message, signature) {
|
||||
try {
|
||||
return this.key().verify(this.hashMessage(message), signature);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
cachedProperty(K256Pair, function key() {
|
||||
if (this.seedBytes) {
|
||||
const options = {validator: this.validator};
|
||||
return secp256k1.keyFromPrivate(deriveSecret(this.seedBytes, options));
|
||||
}
|
||||
return secp256k1.keyFromPublic(this.pubKeyCanonicalBytes());
|
||||
});
|
||||
|
||||
cachedProperty(K256Pair, function pubKeyCanonicalBytes() {
|
||||
return this.key().getPublic().encodeCompressed();
|
||||
});
|
||||
|
||||
K256Pair.fromSeed = function(seedBytes, opts={}) {
|
||||
return new K256Pair({seedBytes, validator: opts.validator});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
K256Pair,
|
||||
accountPublicFromPublicGenerator
|
||||
|
||||
@@ -3,19 +3,21 @@
|
||||
const hashjs = require('hash.js');
|
||||
const Sha512 = require('./sha512');
|
||||
|
||||
function isVirtual() {
|
||||
throw new Error('virtual method not implemented ');
|
||||
function isVirtual(target, name, descriptor) {
|
||||
descriptor.value = function() {
|
||||
throw new Error('virtual method not implemented ');
|
||||
};
|
||||
}
|
||||
|
||||
function cachedProperty(obj, computer) {
|
||||
const name = computer.name;
|
||||
function cached(target, name, descriptor) {
|
||||
const computer = descriptor.value;
|
||||
const key = '_' + name;
|
||||
obj.prototype[name] = function() {
|
||||
let cached = this[key];
|
||||
if (cached === undefined) {
|
||||
cached = this[key] = computer.call(this);
|
||||
descriptor.value = function() {
|
||||
let value = this[key];
|
||||
if (value === undefined) {
|
||||
value = this[key] = computer.call(this);
|
||||
}
|
||||
return cached;
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -45,8 +47,8 @@ function seedFromPhrase(phrase) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
cached,
|
||||
bytesToHex,
|
||||
cachedProperty,
|
||||
createAccountID,
|
||||
isVirtual,
|
||||
seedFromPhrase,
|
||||
|
||||
Reference in New Issue
Block a user