tic-chaintool/utils/signing-key.js
2018-10-09 23:03:05 +08:00

105 lines
3.2 KiB
JavaScript

'use strict';
/**
* SigningKey
*
*
*/
var secp256k1 = new (require('elliptic')).ec('secp256k1');
var utils = (function() {
var convert = require('../utils/convert');
return {
defineProperty: require('../utils/properties').defineProperty,
arrayify: convert.arrayify,
hexlify: convert.hexlify,
padZeros: convert.padZeros,
getAddress: require('../utils/address').getAddress,
keccak256: require('../utils/keccak256')
};
})();
var errors = require('../utils/errors');
function SigningKey(privateKey) {
errors.checkNew(this, SigningKey);
try {
privateKey = utils.arrayify(privateKey);
if (privateKey.length !== 32) {
errors.throwError('exactly 32 bytes required', errors.INVALID_ARGUMENT, { value: privateKey });
}
} catch(error) {
var params = { arg: 'privateKey', reason: error.reason, value: '[REDACTED]' }
if (error.value) {
if(typeof(error.value.length) === 'number') {
params.length = error.value.length;
}
params.type = typeof(error.value);
}
errors.throwError('invalid private key', error.code, params);
}
utils.defineProperty(this, 'privateKey', utils.hexlify(privateKey))
var keyPair = secp256k1.keyFromPrivate(privateKey);
utils.defineProperty(this, 'publicKey', '0x' + keyPair.getPublic(true, 'hex'))
var address = SigningKey.publicKeyToAddress('0x' + keyPair.getPublic(false, 'hex'));
utils.defineProperty(this, 'address', address)
utils.defineProperty(this, 'signDigest', function(digest) {
var signature = keyPair.sign(utils.arrayify(digest), {canonical: true});
var r = '0x' + signature.r.toString(16);
var s = '0x' + signature.s.toString(16);
return {
recoveryParam: signature.recoveryParam,
r: utils.hexlify(utils.padZeros(r, 32)),
s: utils.hexlify(utils.padZeros(s, 32))
}
});
}
utils.defineProperty(SigningKey, 'recover', function(digest, r, s, recoveryParam) {
var signature = {
r: utils.arrayify(r),
s: utils.arrayify(s)
};
var publicKey = secp256k1.recoverPubKey(utils.arrayify(digest), signature, recoveryParam);
return SigningKey.publicKeyToAddress('0x' + publicKey.encode('hex', false));
});
utils.defineProperty(SigningKey, 'getPublicKey', function(value, compressed) {
value = utils.arrayify(value);
compressed = !!compressed;
if (value.length === 32) {
var keyPair = secp256k1.keyFromPrivate(value);
return '0x' + keyPair.getPublic(compressed, 'hex');
} else if (value.length === 33) {
var keyPair = secp256k1.keyFromPublic(value);
return '0x' + keyPair.getPublic(compressed, 'hex');
} else if (value.length === 65) {
var keyPair = secp256k1.keyFromPublic(value);
return '0x' + keyPair.getPublic(compressed, 'hex');
}
throw new Error('invalid value');
});
utils.defineProperty(SigningKey, 'publicKeyToAddress', function(publicKey) {
publicKey = '0x' + SigningKey.getPublicKey(publicKey, false).slice(4);
return utils.getAddress('0x' + utils.keccak256(publicKey).substring(26));
});
module.exports = SigningKey;