mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-05 13:25:48 +00:00
337 lines
11 KiB
JavaScript
337 lines
11 KiB
JavaScript
var assert = require('assert');
|
|
var sjcl = require('ripple-lib').sjcl;
|
|
var Message = require('ripple-lib').Message;
|
|
var Seed = require('ripple-lib').Seed;
|
|
var Remote = require('ripple-lib').Remote;
|
|
|
|
describe('Message', function(){
|
|
|
|
describe('signMessage', function(){
|
|
|
|
it('should prepend the MAGIC_BYTES, call the HASH_FUNCTION, and then call signHash', function(){
|
|
|
|
var normal_signHash = Message.signHash;
|
|
|
|
var message_text = 'Hello World!';
|
|
|
|
var signHash_called = false;
|
|
Message.signHash = function(hash) {
|
|
signHash_called = true;
|
|
assert.deepEqual(hash, Message.HASH_FUNCTION(Message.MAGIC_BYTES + message_text));
|
|
};
|
|
|
|
Message.signMessage(message_text);
|
|
assert(signHash_called);
|
|
|
|
Message.signHash = normal_signHash;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe('signHash', function(){
|
|
|
|
it('should accept the hash as either a hex string or a bitArray', function(){
|
|
|
|
var normal_random = sjcl.random.randomWords;
|
|
|
|
sjcl.random.randomWords = function(num_words){
|
|
var words = [];
|
|
for (var w = 0; w < num_words; w++) {
|
|
words.push(sjcl.codec.hex.toBits('00000000'));
|
|
}
|
|
return words;
|
|
};
|
|
|
|
var secret_string = 'safRpB5euNL52PZPTSqrE9gvuFwTC';
|
|
// var address = 'rLLzaq61D633b5hhbNXKM9CkrYHboobVv3';
|
|
var hash = 'e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778';
|
|
|
|
var signature1 = Message.signHash(hash, secret_string);
|
|
var signature2 = Message.signHash(sjcl.codec.hex.toBits(hash), secret_string);
|
|
|
|
assert.strictEqual(signature1, signature2);
|
|
|
|
sjcl.random.randomWords = normal_random;
|
|
|
|
});
|
|
|
|
it('should accept the secret as a string or scjl.ecc.ecdsa.secretKey object', function(){
|
|
|
|
var normal_random = sjcl.random.randomWords;
|
|
|
|
sjcl.random.randomWords = function(num_words){
|
|
var words = [];
|
|
for (var w = 0; w < num_words; w++) {
|
|
words.push(sjcl.codec.hex.toBits('00000000'));
|
|
}
|
|
return words;
|
|
};
|
|
|
|
var secret_string = 'safRpB5euNL52PZPTSqrE9gvuFwTC';
|
|
// var address = 'rLLzaq61D633b5hhbNXKM9CkrYHboobVv3';
|
|
var hash = 'e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778';
|
|
|
|
var signature1 = Message.signHash(hash, secret_string);
|
|
var signature2 = Message.signHash(hash, Seed.from_json(secret_string).get_key()._secret);
|
|
|
|
assert.strictEqual(signature1, signature2);
|
|
|
|
sjcl.random.randomWords = normal_random;
|
|
|
|
});
|
|
|
|
it('should throw an error if given an invalid secret key', function(){
|
|
// Annoyingly non hex can be fed to the BigInteger(s, 16) constructor and
|
|
// it will parse as a number. Before the commit of this comment, this test
|
|
// involved a fixture of 32 chars, which was assumed to be hex. The test
|
|
// passed, but for the wrong wreasons. There was a bug in Seed.parse_json.
|
|
|
|
// Seed.from_json only creates invalid seeds from empty strings or invalid
|
|
// base58 starting with an s, which it tries to base 58 decode/check sum.
|
|
// The rest will be assumed to be a passphrase.
|
|
|
|
// This is a bad b58 seed
|
|
var secret_string = 'sbadsafRpB5euNL52PZPTSqrE9gvuFwTC';
|
|
var hash = 'e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778';
|
|
|
|
assert.throws(function(){
|
|
Message.signHash(hash, secret_string);
|
|
}, /Cannot\ generate\ keys\ from\ invalid\ seed/);
|
|
|
|
});
|
|
|
|
it('should throw an error if the parameters are reversed', function(){
|
|
|
|
var secret_string = 'safRpB5euNL52PZPTSqrE9gvuFwTC';
|
|
var hash = 'e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778';
|
|
|
|
assert.throws(function(){
|
|
Message.signHash(secret_string, hash);
|
|
}, Error);
|
|
|
|
assert.throws(function(){
|
|
Message.signHash(secret_string, sjcl.codec.hex.toBits(hash));
|
|
}, Error);
|
|
|
|
assert.throws(function(){
|
|
Message.signHash(Seed.from_json(secret_string).get_key()._secret, hash);
|
|
}, Error);
|
|
|
|
assert.throws(function(){
|
|
Message.signHash(Seed.from_json(secret_string).get_key()._secret, sjcl.codec.hex.toBits(hash));
|
|
}, Error);
|
|
|
|
});
|
|
|
|
it('should produce a base64-encoded signature', function(){
|
|
var REGEX_BASE64 = /^([A-Za-z0-9\+]{4})*([A-Za-z0-9\+]{2}==)|([A-Za-z0-9\+]{3}=)?$/;
|
|
|
|
var normal_random = sjcl.random.randomWords;
|
|
|
|
sjcl.random.randomWords = function(num_words){
|
|
var words = [];
|
|
for (var w = 0; w < num_words; w++) {
|
|
words.push(sjcl.codec.hex.toBits('00000000'));
|
|
}
|
|
return words;
|
|
};
|
|
|
|
var secret_string = 'safRpB5euNL52PZPTSqrE9gvuFwTC';
|
|
// var address = 'rLLzaq61D633b5hhbNXKM9CkrYHboobVv3';
|
|
var hash = 'e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778';
|
|
|
|
var signature = Message.signHash(hash, secret_string);
|
|
|
|
assert(REGEX_BASE64.test(signature));
|
|
|
|
sjcl.random.randomWords = normal_random;
|
|
});
|
|
|
|
});
|
|
|
|
describe('verifyMessageSignature', function(){
|
|
|
|
it('should prepend the MAGIC_BYTES, call the HASH_FUNCTION, and then call verifyHashSignature', function(){
|
|
|
|
var normal_verifyHashSignature = Message.verifyHashSignature;
|
|
|
|
var data = {
|
|
message: 'Hello world!',
|
|
signature: 'AAAAGzFa1pYjhssCpDFZgFSnYQ8qCnMkLaZrg0mXZyNQ2NxgMQ8z9U3ngYerxSZCEt3Q4raMIpt03db7jDNGbfmHy8I='
|
|
};
|
|
|
|
var verifyHashSignature_called = false;
|
|
Message.verifyHashSignature = function(vhs_data, remote, callback) {
|
|
verifyHashSignature_called = true;
|
|
|
|
assert.deepEqual(vhs_data.hash, Message.HASH_FUNCTION(Message.MAGIC_BYTES + data.message));
|
|
assert.strictEqual(vhs_data.signature, data.signature);
|
|
callback();
|
|
|
|
};
|
|
|
|
Message.verifyMessageSignature(data, {}, function(err){
|
|
assert(!err);
|
|
});
|
|
assert(verifyHashSignature_called);
|
|
|
|
Message.verifyHashSignature = normal_verifyHashSignature;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
describe('verifyHashSignature', function(){
|
|
|
|
it('should throw an error if a callback function is not supplied', function(){
|
|
|
|
var data = {
|
|
message: 'Hello world!',
|
|
hash: '861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8',
|
|
signature: 'AAAAHOUJQzG/7BO82fGNt1TNE+GGVXKuQQ0N2nTO+iJETE69PiHnaAkkOzovM177OosxbKjpt3KvwuJflgUB2YGvgjk=',
|
|
account: 'rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz'
|
|
};
|
|
|
|
//Remote.prototype.addServer = function(){};
|
|
var test_remote = new Remote();
|
|
|
|
assert.throws(function(){
|
|
Message.verifyHashSignature(data);
|
|
}, /(?=.*callback\ function).*/);
|
|
});
|
|
|
|
it('should respond with an error if the hash is missing or invalid', function(done){
|
|
|
|
var data = {
|
|
message: 'Hello world!',
|
|
signature: 'AAAAHOUJQzG/7BO82fGNt1TNE+GGVXKuQQ0N2nTO+iJETE69PiHnaAkkOzovM177OosxbKjpt3KvwuJflgUB2YGvgjk=',
|
|
account: 'rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz'
|
|
};
|
|
|
|
//Remote.prototype.addServer = function(){};
|
|
var test_remote = new Remote();
|
|
test_remote.state = 'online';
|
|
|
|
Message.verifyHashSignature(data, test_remote, function(err, valid){
|
|
assert(/hash/i.test(err.message));
|
|
done();
|
|
});
|
|
|
|
});
|
|
|
|
it('should respond with an error if the account is missing or invalid', function(done){
|
|
|
|
var data = {
|
|
message: 'Hello world!',
|
|
hash: '861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8',
|
|
signature: 'AAAAHOUJQzG/7BO82fGNt1TNE+GGVXKuQQ0N2nTO+iJETE69PiHnaAkkOzovM177OosxbKjpt3KvwuJflgUB2YGvgjk='
|
|
};
|
|
|
|
//Remote.prototype.addServer = function(){};
|
|
var test_remote = new Remote();
|
|
test_remote.state = 'online';
|
|
|
|
Message.verifyHashSignature(data, test_remote, function(err, valid){
|
|
assert(/account|address/i.test(err.message));
|
|
done();
|
|
});
|
|
|
|
});
|
|
|
|
it('should respond with an error if the signature is missing or invalid', function(done){
|
|
|
|
var data = {
|
|
message: 'Hello world!',
|
|
hash: '861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8',
|
|
account: 'rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz'
|
|
};
|
|
|
|
//Remote.prototype.addServer = function(){};
|
|
var test_remote = new Remote();
|
|
test_remote.state = 'online';
|
|
|
|
Message.verifyHashSignature(data, test_remote, function(err, valid){
|
|
assert(/signature/i.test(err.message));
|
|
done();
|
|
});
|
|
|
|
});
|
|
|
|
it('should respond true if the signature is valid and corresponds to an active public key for the account', function(done){
|
|
|
|
var data = {
|
|
message: 'Hello world!',
|
|
hash: 'e9a82ea40514787918959b1100481500a5d384030f8770575c6a587675025fe212e6623e25643f251666a7b8b23af476c2850a8ea92153de5724db432892c752',
|
|
account: 'rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz',
|
|
signature: 'AAAAHMIPCQGLgdnpX1Ccv1wHb56H4NggxIM6U08Qkb9mUjN2Vn9pZ3CHvq1yWLBi6NqpW+7kedLnmfu4VG2+y43p4Xs='
|
|
};
|
|
|
|
//Remote.prototype.addServer = function(){};
|
|
var test_remote = new Remote();
|
|
test_remote.state = 'online';
|
|
test_remote.requestAccountInfo = function(options, callback) {
|
|
var account = options.account;
|
|
if (account === data.account) {
|
|
callback(null, {
|
|
"account_data": {
|
|
"Account": "rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz",
|
|
"Flags": 1114112,
|
|
"LedgerEntryType": "AccountRoot",
|
|
"RegularKey": "rHq2wyUtLkAad3vURUk33q9gozd97skhSf"
|
|
}
|
|
});
|
|
} else {
|
|
callback(new Error('wrong account'));
|
|
}
|
|
};
|
|
|
|
Message.verifyHashSignature(data, test_remote, function(err, valid){
|
|
assert(!err);
|
|
assert(valid);
|
|
done();
|
|
});
|
|
|
|
});
|
|
|
|
it('should respond false if a key can be recovered from the signature but it does not correspond to an active public key', function(done){
|
|
|
|
// Signature created by disabled master key
|
|
var data = {
|
|
message: 'Hello world!',
|
|
hash: 'e9a82ea40514787918959b1100481500a5d384030f8770575c6a587675025fe212e6623e25643f251666a7b8b23af476c2850a8ea92153de5724db432892c752',
|
|
account: 'rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz',
|
|
signature: 'AAAAG+dB/rAjZ5m8eQ/opcqQOJsFbKxOu9jq9KrOAlNO4OdcBDXyCBlkZqS9Xr8oZI2uh0boVsgYOS3pOLJz+Dh3Otk='
|
|
};
|
|
|
|
//Remote.prototype.addServer = function(){};
|
|
var test_remote = new Remote();
|
|
test_remote.state = 'online';
|
|
test_remote.requestAccountInfo = function(options, callback) {
|
|
var account = options.account;
|
|
if (account === data.account) {
|
|
callback(null, {
|
|
"account_data": {
|
|
"Account": "rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz",
|
|
"Flags": 1114112,
|
|
"LedgerEntryType": "AccountRoot",
|
|
"RegularKey": "rHq2wyUtLkAad3vURUk33q9gozd97skhSf"
|
|
}
|
|
});
|
|
} else {
|
|
callback(new Error('wrong account'));
|
|
}
|
|
};
|
|
|
|
Message.verifyHashSignature(data, test_remote, function(err, valid){
|
|
assert(!err);
|
|
assert(!valid);
|
|
done();
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|