mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-15 01:55:48 +00:00
Fix lint errors in crypt.js, messages.js, remote.js, message-test.js
This commit is contained in:
committed by
Geert Weening
parent
c7ba822320
commit
10ca2da2d6
@@ -1,20 +1,20 @@
|
||||
var sjcl = require('./utils').sjcl;
|
||||
var base = require('./base').Base;
|
||||
var Seed = require('./seed').Seed;
|
||||
var UInt160 = require('./uint160').UInt160;
|
||||
var UInt256 = require('./uint256').UInt256;
|
||||
var request = require('superagent');
|
||||
var querystring = require('querystring');
|
||||
var extend = require("extend");
|
||||
var parser = require("url");
|
||||
var Crypt = { };
|
||||
/* eslint-disable new-cap */
|
||||
'use strict';
|
||||
var sjcl = require('./utils').sjcl;
|
||||
var base = require('./base').Base;
|
||||
var Seed = require('./seed').Seed;
|
||||
var UInt160 = require('./uint160').UInt160;
|
||||
var UInt256 = require('./uint256').UInt256;
|
||||
var request = require('superagent');
|
||||
var extend = require('extend');
|
||||
var Crypt = { };
|
||||
|
||||
var cryptConfig = {
|
||||
cipher : 'aes',
|
||||
mode : 'ccm',
|
||||
ts : 128, // tag length
|
||||
ks : 256, // key size
|
||||
iter : 1000 // iterations (key derivation)
|
||||
cipher: 'aes',
|
||||
mode: 'ccm',
|
||||
ts: 128, // tag length
|
||||
ks: 256, // key size
|
||||
iter: 1000 // iterations (key derivation)
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -41,10 +41,10 @@ function fdh(data, bytelen) {
|
||||
output = sjcl.bitArray.clamp(output, bitlen);
|
||||
|
||||
return output;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a function to derive different hashes from the same key.
|
||||
* This is a function to derive different hashes from the same key.
|
||||
* Each hash is derived as HMAC-SHA512HALF(key, token).
|
||||
*
|
||||
* @param {string} key
|
||||
@@ -53,12 +53,14 @@ function fdh(data, bytelen) {
|
||||
|
||||
function keyHash(key, token) {
|
||||
var hmac = new sjcl.misc.hmac(key, sjcl.hash.sha512);
|
||||
return sjcl.codec.hex.fromBits(sjcl.bitArray.bitSlice(hmac.encrypt(token), 0, 256));
|
||||
};
|
||||
return sjcl.codec.hex.fromBits(
|
||||
sjcl.bitArray.bitSlice(hmac.encrypt(token), 0, 256));
|
||||
}
|
||||
|
||||
/**
|
||||
* add entropy at each call to get random words
|
||||
* @param {number} nWords
|
||||
* @param {number} nWords - number of words to generate
|
||||
* @return {array} random words (4 byte unsigned integers)
|
||||
*/
|
||||
function randomWords(nWords) {
|
||||
var PARANOIA_256_BITS = 6; // sjcl constant for ensuring 256 bits of entropy
|
||||
@@ -91,19 +93,21 @@ Crypt.derive = function(opts, purpose, username, secret, fn) {
|
||||
}
|
||||
|
||||
var iExponent = new sjcl.bn(String(opts.exponent));
|
||||
var iModulus = new sjcl.bn(String(opts.modulus));
|
||||
var iAlpha = new sjcl.bn(String(opts.alpha));
|
||||
var iModulus = new sjcl.bn(String(opts.modulus));
|
||||
var iAlpha = new sjcl.bn(String(opts.alpha));
|
||||
|
||||
var publicInfo = [ 'PAKDF_1_0_0', opts.host.length, opts.host, username.length, username, purpose.length, purpose ].join(':') + ':';
|
||||
var publicSize = Math.ceil(Math.min((7 + iModulus.bitLength()) >>> 3, 256) / 8);
|
||||
var publicInfo = ['PAKDF_1_0_0', opts.host.length, opts.host,
|
||||
username.length, username, purpose.length, purpose].join(':') + ':';
|
||||
var publicSize = Math.ceil(Math.min(
|
||||
(7 + iModulus.bitLength()) >>> 3, 256) / 8);
|
||||
var publicHash = fdh(publicInfo, publicSize);
|
||||
var publicHex = sjcl.codec.hex.fromBits(publicHash);
|
||||
var iPublic = new sjcl.bn(String(publicHex)).setBitM(0);
|
||||
var secretInfo = [ publicInfo, secret.length, secret ].join(':') + ':';
|
||||
var publicHex = sjcl.codec.hex.fromBits(publicHash);
|
||||
var iPublic = new sjcl.bn(String(publicHex)).setBitM(0);
|
||||
var secretInfo = [publicInfo, secret.length, secret].join(':') + ':';
|
||||
var secretSize = (7 + iModulus.bitLength()) >>> 3;
|
||||
var secretHash = fdh(secretInfo, secretSize);
|
||||
var secretHex = sjcl.codec.hex.fromBits(secretHash);
|
||||
var iSecret = new sjcl.bn(String(secretHex)).mod(iModulus);
|
||||
var secretHex = sjcl.codec.hex.fromBits(secretHash);
|
||||
var iSecret = new sjcl.bn(String(secretHex)).mod(iModulus);
|
||||
|
||||
if (iSecret.jacobi(iModulus) !== 1) {
|
||||
iSecret = iSecret.mul(iAlpha).mod(iModulus);
|
||||
@@ -119,12 +123,12 @@ Crypt.derive = function(opts, purpose, username, secret, fn) {
|
||||
}
|
||||
}
|
||||
|
||||
var iBlind = iRandom.powermodMontgomery(iPublic.mul(iExponent), iModulus);
|
||||
var iBlind = iRandom.powermodMontgomery(iPublic.mul(iExponent), iModulus);
|
||||
var iSignreq = iSecret.mulmod(iBlind, iModulus);
|
||||
var signreq = sjcl.codec.hex.fromBits(iSignreq.toBits());
|
||||
var signreq = sjcl.codec.hex.fromBits(iSignreq.toBits());
|
||||
|
||||
request.post(opts.url)
|
||||
.send({ info: publicInfo, signreq: signreq })
|
||||
.send({info: publicInfo, signreq: signreq})
|
||||
.end(function(err, resp) {
|
||||
if (err || !resp) {
|
||||
return fn(new Error('Could not query PAKDF server ' + opts.host));
|
||||
@@ -133,14 +137,14 @@ Crypt.derive = function(opts, purpose, username, secret, fn) {
|
||||
var data = resp.body || resp.text ? JSON.parse(resp.text) : {};
|
||||
|
||||
if (data.result !== 'success') {
|
||||
return fn(new Error('Could not query PAKDF server '+opts.host));
|
||||
return fn(new Error('Could not query PAKDF server ' + opts.host));
|
||||
}
|
||||
|
||||
var iSignres = new sjcl.bn(String(data.signres));
|
||||
var iRandomInv = iRandom.inverseMod(iModulus);
|
||||
var iSigned = iSignres.mulmod(iRandomInv, iModulus);
|
||||
var key = iSigned.toBits();
|
||||
var result = { };
|
||||
var iSigned = iSignres.mulmod(iRandomInv, iModulus);
|
||||
var key = iSigned.toBits();
|
||||
var result = { };
|
||||
|
||||
tokens.forEach(function(token) {
|
||||
result[token] = keyHash(key, token);
|
||||
@@ -154,8 +158,6 @@ Crypt.derive = function(opts, purpose, username, secret, fn) {
|
||||
* Imported from ripple-client
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encrypt data
|
||||
*
|
||||
@@ -186,20 +188,22 @@ Crypt.encrypt = function(key, data) {
|
||||
* @param {string} data
|
||||
*/
|
||||
|
||||
Crypt.decrypt = function (key, data) {
|
||||
|
||||
Crypt.decrypt = function(key, data) {
|
||||
|
||||
key = sjcl.codec.hex.toBits(key);
|
||||
var encryptedBits = sjcl.codec.base64.toBits(data);
|
||||
|
||||
var version = sjcl.bitArray.extract(encryptedBits, 0, 8);
|
||||
|
||||
if (version !== 0) {
|
||||
throw new Error('Unsupported encryption version: '+version);
|
||||
throw new Error('Unsupported encryption version: ' + version);
|
||||
}
|
||||
|
||||
var encrypted = extend(true, {}, cryptConfig, {
|
||||
iv: sjcl.codec.base64.fromBits(sjcl.bitArray.bitSlice(encryptedBits, 8, 8+128)),
|
||||
ct: sjcl.codec.base64.fromBits(sjcl.bitArray.bitSlice(encryptedBits, 8+128))
|
||||
iv: sjcl.codec.base64.fromBits(
|
||||
sjcl.bitArray.bitSlice(encryptedBits, 8, 8 + 128)),
|
||||
ct: sjcl.codec.base64.fromBits(
|
||||
sjcl.bitArray.bitSlice(encryptedBits, 8 + 128))
|
||||
});
|
||||
|
||||
return sjcl.decrypt(key, JSON.stringify(encrypted));
|
||||
@@ -212,7 +216,7 @@ Crypt.decrypt = function (key, data) {
|
||||
* @param {string} address
|
||||
*/
|
||||
|
||||
Crypt.isValidAddress = function (address) {
|
||||
Crypt.isValidAddress = function(address) {
|
||||
return UInt160.is_valid(address);
|
||||
};
|
||||
|
||||
@@ -222,7 +226,7 @@ Crypt.isValidAddress = function (address) {
|
||||
* @param {integer} nWords - number of words
|
||||
*/
|
||||
|
||||
Crypt.createSecret = function (nWords) {
|
||||
Crypt.createSecret = function(nWords) {
|
||||
return sjcl.codec.hex.fromBits(randomWords(nWords));
|
||||
};
|
||||
|
||||
@@ -230,7 +234,7 @@ Crypt.createSecret = function (nWords) {
|
||||
* Create a new master key
|
||||
*/
|
||||
|
||||
Crypt.createMaster = function () {
|
||||
Crypt.createMaster = function() {
|
||||
return base.encode_check(33, sjcl.codec.bytes.fromBits(randomWords(4)));
|
||||
};
|
||||
|
||||
@@ -241,7 +245,7 @@ Crypt.createMaster = function () {
|
||||
* @param {string} masterkey
|
||||
*/
|
||||
|
||||
Crypt.getAddress = function (masterkey) {
|
||||
Crypt.getAddress = function(masterkey) {
|
||||
return Seed.from_json(masterkey).get_key().get_address().to_json();
|
||||
};
|
||||
|
||||
@@ -252,9 +256,9 @@ Crypt.getAddress = function (masterkey) {
|
||||
* @return {string} Hash of the data
|
||||
*/
|
||||
|
||||
Crypt.hashSha512 = function (data) {
|
||||
Crypt.hashSha512 = function(data) {
|
||||
// XXX Should return a UInt512
|
||||
return sjcl.codec.hex.fromBits(sjcl.hash.sha512.hash(data));
|
||||
return sjcl.codec.hex.fromBits(sjcl.hash.sha512.hash(data));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -263,7 +267,8 @@ Crypt.hashSha512 = function (data) {
|
||||
* @param {string|bitArray} data
|
||||
* @return {UInt256} Hash of the data
|
||||
*/
|
||||
Crypt.hashSha512Half = function (data) {
|
||||
|
||||
Crypt.hashSha512Half = function(data) {
|
||||
return UInt256.from_hex(Crypt.hashSha512(data).substr(0, 64));
|
||||
};
|
||||
|
||||
@@ -276,7 +281,8 @@ Crypt.hashSha512Half = function (data) {
|
||||
*/
|
||||
|
||||
Crypt.signString = function(secret, data) {
|
||||
var hmac = new sjcl.misc.hmac(sjcl.codec.hex.toBits(secret), sjcl.hash.sha512);
|
||||
var hmac = new sjcl.misc.hmac(
|
||||
sjcl.codec.hex.toBits(secret), sjcl.hash.sha512);
|
||||
return sjcl.codec.hex.fromBits(hmac.mac(data));
|
||||
};
|
||||
|
||||
@@ -289,8 +295,8 @@ Crypt.signString = function(secret, data) {
|
||||
Crypt.deriveRecoveryEncryptionKeyFromSecret = function(secret) {
|
||||
var seed = Seed.from_json(secret).to_bits();
|
||||
var hmac = new sjcl.misc.hmac(seed, sjcl.hash.sha512);
|
||||
var key = hmac.mac('ripple/hmac/recovery_encryption_key/v1');
|
||||
key = sjcl.bitArray.bitSlice(key, 0, 256);
|
||||
var key = sjcl.bitArray.bitSlice(
|
||||
hmac.mac('ripple/hmac/recovery_encryption_key/v1'), 0, 256);
|
||||
return sjcl.codec.hex.fromBits(key);
|
||||
};
|
||||
|
||||
@@ -301,7 +307,8 @@ Crypt.deriveRecoveryEncryptionKeyFromSecret = function(secret) {
|
||||
*/
|
||||
|
||||
Crypt.base64ToBase64Url = function(encodedData) {
|
||||
return encodedData.replace(/\+/g, '-').replace(/\//g, '_').replace(/[=]+$/, '');
|
||||
return encodedData.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_').replace(/[=]+$/, '');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -324,8 +331,8 @@ Crypt.base64UrlToBase64 = function(encodedData) {
|
||||
* base64 to UTF8
|
||||
*/
|
||||
|
||||
Crypt.decodeBase64 = function (data) {
|
||||
Crypt.decodeBase64 = function(data) {
|
||||
return sjcl.codec.utf8String.fromBits(sjcl.codec.base64.toBits(data));
|
||||
}
|
||||
};
|
||||
|
||||
exports.Crypt = Crypt;
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
var async = require('async');
|
||||
var crypto = require('crypto');
|
||||
var sjcl = require('./utils').sjcl;
|
||||
var Remote = require('./remote').Remote;
|
||||
var Seed = require('./seed').Seed;
|
||||
var KeyPair = require('./keypair').KeyPair;
|
||||
var Account = require('./account').Account;
|
||||
var UInt160 = require('./uint160').UInt160;
|
||||
/* eslint-disable valid-jsdoc */
|
||||
'use strict';
|
||||
var async = require('async');
|
||||
var sjcl = require('./utils').sjcl;
|
||||
var Remote = require('./remote').Remote;
|
||||
var Seed = require('./seed').Seed;
|
||||
var KeyPair = require('./keypair').KeyPair;
|
||||
var Account = require('./account').Account;
|
||||
var UInt160 = require('./uint160').UInt160;
|
||||
|
||||
// Message class (static)
|
||||
var Message = {};
|
||||
|
||||
Message.HASH_FUNCTION = sjcl.hash.sha512.hash;
|
||||
Message.MAGIC_BYTES = 'Ripple Signed Message:\n';
|
||||
Message.hashFunction = sjcl.hash.sha512.hash;
|
||||
Message.MAGIC_BYTES = 'Ripple Signed Message:\n';
|
||||
|
||||
var REGEX_HEX = /^[0-9a-fA-F]+$/;
|
||||
var REGEX_BASE64 = /^([A-Za-z0-9\+]{4})*([A-Za-z0-9\+]{2}==)|([A-Za-z0-9\+]{3}=)?$/;
|
||||
var REGEX_BASE64 =
|
||||
/^([A-Za-z0-9\+]{4})*([A-Za-z0-9\+]{2}==)|([A-Za-z0-9\+]{3}=)?$/;
|
||||
|
||||
/**
|
||||
* Produce a Base64-encoded signature on the given message with
|
||||
@@ -27,15 +29,16 @@ var REGEX_BASE64 = /^([A-Za-z0-9\+]{4})*([A-Za-z0-9\+]{2}==)|([A-Za-z0-9\+]{3}=)
|
||||
* @static
|
||||
*
|
||||
* @param {String} message
|
||||
* @param {sjcl.ecc.ecdsa.secretKey|Any format accepted by Seed.from_json} secret_key
|
||||
* @param {RippleAddress} [The first key] account Field to specify the signing account.
|
||||
* If this is omitted the first account produced by the secret generator will be used.
|
||||
* @returns {Base64-encoded String} signature
|
||||
* @param {sjcl.ecc.ecdsa.secretKey|Any format accepted by Seed.from_json}
|
||||
* secret_key
|
||||
* @param {RippleAddress} [The first key] account Field to specify the signing
|
||||
* account. If this is omitted the first account produced by the secret
|
||||
* generator will be used.
|
||||
* @return {Base64-encoded String} signature
|
||||
*/
|
||||
Message.signMessage = function(message, secret_key, account) {
|
||||
|
||||
return Message.signHash(Message.HASH_FUNCTION(Message.MAGIC_BYTES + message), secret_key, account);
|
||||
|
||||
return Message.signHash(Message.hashFunction(Message.MAGIC_BYTES + message),
|
||||
secret_key, account);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -48,9 +51,11 @@ Message.signMessage = function(message, secret_key, account) {
|
||||
* @static
|
||||
*
|
||||
* @param {bitArray|Hex-encoded String} hash
|
||||
* @param {sjcl.ecc.ecdsa.secretKey|Any format accepted by Seed.from_json} secret_key
|
||||
* @param {RippleAddress} [The first key] account Field to specify the signing account.
|
||||
* If this is omitted the first account produced by the secret generator will be used.
|
||||
* @param {sjcl.ecc.ecdsa.secretKey|Any format accepted by Seed.from_json}
|
||||
* secret_key
|
||||
* @param {RippleAddress} [The first key] account Field to specify the
|
||||
* signing account. If this is omitted the first account produced by
|
||||
* the secret generator will be used.
|
||||
* @returns {Base64-encoded String} signature
|
||||
*/
|
||||
Message.signHash = function(hash, secret_key, account) {
|
||||
@@ -59,7 +64,8 @@ Message.signHash = function(hash, secret_key, account) {
|
||||
hash = sjcl.codec.hex.toBits(hash);
|
||||
}
|
||||
|
||||
if (typeof hash !== 'object' || hash.length <= 0 || typeof hash[0] !== 'number') {
|
||||
if (typeof hash !== 'object' || hash.length <= 0
|
||||
|| typeof hash[0] !== 'number') {
|
||||
throw new Error('Hash must be a bitArray or hex-encoded string');
|
||||
}
|
||||
|
||||
@@ -80,7 +86,7 @@ Message.signHash = function(hash, secret_key, account) {
|
||||
/**
|
||||
* Verify the signature on a given message.
|
||||
*
|
||||
* Note that this function is asynchronous.
|
||||
* Note that this function is asynchronous.
|
||||
* The ripple-lib remote is used to check that the public
|
||||
* key extracted from the signature corresponds to one that is currently
|
||||
* active for the given account.
|
||||
@@ -100,9 +106,10 @@ Message.signHash = function(hash, secret_key, account) {
|
||||
Message.verifyMessageSignature = function(data, remote, callback) {
|
||||
|
||||
if (typeof data.message === 'string') {
|
||||
data.hash = Message.HASH_FUNCTION(Message.MAGIC_BYTES + data.message);
|
||||
data.hash = Message.hashFunction(Message.MAGIC_BYTES + data.message);
|
||||
} else {
|
||||
return callback(new Error('Data object must contain message field to verify signature'));
|
||||
return callback(new Error(
|
||||
'Data object must contain message field to verify signature'));
|
||||
}
|
||||
|
||||
return Message.verifyHashSignature(data, remote, callback);
|
||||
@@ -113,7 +120,7 @@ Message.verifyMessageSignature = function(data, remote, callback) {
|
||||
/**
|
||||
* Verify the signature on a given hash.
|
||||
*
|
||||
* Note that this function is asynchronous.
|
||||
* Note that this function is asynchronous.
|
||||
* The ripple-lib remote is used to check that the public
|
||||
* key extracted from the signature corresponds to one that is currently
|
||||
* active for the given account.
|
||||
@@ -136,7 +143,7 @@ Message.verifyHashSignature = function(data, remote, callback) {
|
||||
account,
|
||||
signature;
|
||||
|
||||
if(typeof callback !== 'function') {
|
||||
if (typeof callback !== 'function') {
|
||||
throw new Error('Must supply callback function');
|
||||
}
|
||||
|
||||
@@ -145,7 +152,8 @@ Message.verifyHashSignature = function(data, remote, callback) {
|
||||
hash = sjcl.codec.hex.toBits(hash);
|
||||
}
|
||||
|
||||
if (typeof hash !== 'object' || hash.length <= 0 || typeof hash[0] !== 'number') {
|
||||
if (typeof hash !== 'object' || hash.length <= 0
|
||||
|| typeof hash[0] !== 'number') {
|
||||
return callback(new Error('Hash must be a bitArray or hex-encoded string'));
|
||||
}
|
||||
|
||||
@@ -161,14 +169,16 @@ Message.verifyHashSignature = function(data, remote, callback) {
|
||||
signature = sjcl.codec.base64.toBits(signature);
|
||||
|
||||
if (!(remote instanceof Remote) || remote.state !== 'online') {
|
||||
return callback(new Error('Must supply connected Remote to verify signature'));
|
||||
return callback(new Error(
|
||||
'Must supply connected Remote to verify signature'));
|
||||
}
|
||||
|
||||
function recoverPublicKey (async_callback) {
|
||||
function recoverPublicKey(async_callback) {
|
||||
|
||||
var public_key;
|
||||
try {
|
||||
public_key = sjcl.ecc.ecdsa.publicKey.recoverFromSignature(hash, signature);
|
||||
public_key =
|
||||
sjcl.ecc.ecdsa.publicKey.recoverFromSignature(hash, signature);
|
||||
} catch (err) {
|
||||
return async_callback(err);
|
||||
}
|
||||
@@ -179,9 +189,9 @@ Message.verifyHashSignature = function(data, remote, callback) {
|
||||
async_callback(new Error('Could not recover public key from signature'));
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
function checkPublicKeyIsValid (public_key, async_callback) {
|
||||
function checkPublicKeyIsValid(public_key, async_callback) {
|
||||
|
||||
// Get hex-encoded public key
|
||||
var key_pair = new KeyPair();
|
||||
@@ -191,7 +201,7 @@ Message.verifyHashSignature = function(data, remote, callback) {
|
||||
var account_class_instance = new Account(remote, account);
|
||||
account_class_instance.publicKeyIsActive(public_key_hex, async_callback);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
var steps = [
|
||||
recoverPublicKey,
|
||||
|
||||
@@ -33,7 +33,6 @@ var PathFind = require('./pathfind').PathFind;
|
||||
var SerializedObject = require('./serializedobject').SerializedObject;
|
||||
var RippleError = require('./rippleerror').RippleError;
|
||||
var utils = require('./utils');
|
||||
var sjcl = require('./utils').sjcl;
|
||||
var hashprefixes = require('./hashprefixes');
|
||||
var config = require('./config');
|
||||
var log = require('./log').internal.sub('remote');
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
var assert = require('assert');
|
||||
var sjcl = require('ripple-lib').sjcl;
|
||||
/* eslint-disable max-len */
|
||||
'use strict';
|
||||
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;
|
||||
var Seed = require('ripple-lib').Seed;
|
||||
var Remote = require('ripple-lib').Remote;
|
||||
|
||||
describe('Message', function(){
|
||||
describe('Message', function() {
|
||||
|
||||
describe('signMessage', function(){
|
||||
describe('signMessage', function() {
|
||||
|
||||
it('should prepend the MAGIC_BYTES, call the HASH_FUNCTION, and then call signHash', function(){
|
||||
it('should prepend the MAGIC_BYTES, call the hashFunction, and then call signHash', function() {
|
||||
|
||||
var normal_signHash = Message.signHash;
|
||||
|
||||
@@ -17,7 +19,7 @@ describe('Message', function(){
|
||||
var signHash_called = false;
|
||||
Message.signHash = function(hash) {
|
||||
signHash_called = true;
|
||||
assert.deepEqual(hash, Message.HASH_FUNCTION(Message.MAGIC_BYTES + message_text));
|
||||
assert.deepEqual(hash, Message.hashFunction(Message.MAGIC_BYTES + message_text));
|
||||
};
|
||||
|
||||
Message.signMessage(message_text);
|
||||
@@ -29,13 +31,13 @@ describe('Message', function(){
|
||||
|
||||
});
|
||||
|
||||
describe('signHash', function(){
|
||||
describe('signHash', function() {
|
||||
|
||||
it('should accept the hash as either a hex string or a bitArray', 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){
|
||||
sjcl.random.randomWords = function(num_words) {
|
||||
var words = [];
|
||||
for (var w = 0; w < num_words; w++) {
|
||||
words.push(sjcl.codec.hex.toBits('00000000'));
|
||||
@@ -56,11 +58,11 @@ describe('Message', function(){
|
||||
|
||||
});
|
||||
|
||||
it('should accept the secret as a string or scjl.ecc.ecdsa.secretKey object', function(){
|
||||
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){
|
||||
sjcl.random.randomWords = function(num_words) {
|
||||
var words = [];
|
||||
for (var w = 0; w < num_words; w++) {
|
||||
words.push(sjcl.codec.hex.toBits('00000000'));
|
||||
@@ -81,7 +83,7 @@ describe('Message', function(){
|
||||
|
||||
});
|
||||
|
||||
it('should throw an error if given an invalid secret key', function(){
|
||||
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
|
||||
@@ -95,41 +97,41 @@ describe('Message', function(){
|
||||
var secret_string = 'sbadsafRpB5euNL52PZPTSqrE9gvuFwTC';
|
||||
var hash = 'e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778';
|
||||
|
||||
assert.throws(function(){
|
||||
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(){
|
||||
it('should throw an error if the parameters are reversed', function() {
|
||||
|
||||
var secret_string = 'safRpB5euNL52PZPTSqrE9gvuFwTC';
|
||||
var hash = 'e865bcc63a86ef21585ac8340a7cc8590ed85175a2a718c6fb2bfb2715d13778';
|
||||
|
||||
assert.throws(function(){
|
||||
assert.throws(function() {
|
||||
Message.signHash(secret_string, hash);
|
||||
}, Error);
|
||||
|
||||
assert.throws(function(){
|
||||
assert.throws(function() {
|
||||
Message.signHash(secret_string, sjcl.codec.hex.toBits(hash));
|
||||
}, Error);
|
||||
|
||||
assert.throws(function(){
|
||||
assert.throws(function() {
|
||||
Message.signHash(Seed.from_json(secret_string).get_key()._secret, hash);
|
||||
}, Error);
|
||||
|
||||
assert.throws(function(){
|
||||
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(){
|
||||
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){
|
||||
sjcl.random.randomWords = function(num_words) {
|
||||
var words = [];
|
||||
for (var w = 0; w < num_words; w++) {
|
||||
words.push(sjcl.codec.hex.toBits('00000000'));
|
||||
@@ -150,9 +152,9 @@ describe('Message', function(){
|
||||
|
||||
});
|
||||
|
||||
describe('verifyMessageSignature', function(){
|
||||
describe('verifyMessageSignature', function() {
|
||||
|
||||
it('should prepend the MAGIC_BYTES, call the HASH_FUNCTION, and then call verifyHashSignature', function(){
|
||||
it('should prepend the MAGIC_BYTES, call the hashFunction, and then call verifyHashSignature', function() {
|
||||
|
||||
var normal_verifyHashSignature = Message.verifyHashSignature;
|
||||
|
||||
@@ -165,13 +167,13 @@ describe('Message', function(){
|
||||
Message.verifyHashSignature = function(vhs_data, remote, callback) {
|
||||
verifyHashSignature_called = true;
|
||||
|
||||
assert.deepEqual(vhs_data.hash, Message.HASH_FUNCTION(Message.MAGIC_BYTES + data.message));
|
||||
assert.deepEqual(vhs_data.hash, Message.hashFunction(Message.MAGIC_BYTES + data.message));
|
||||
assert.strictEqual(vhs_data.signature, data.signature);
|
||||
callback();
|
||||
|
||||
};
|
||||
|
||||
Message.verifyMessageSignature(data, {}, function(err){
|
||||
Message.verifyMessageSignature(data, {}, function(err) {
|
||||
assert(!err);
|
||||
});
|
||||
assert(verifyHashSignature_called);
|
||||
@@ -182,9 +184,9 @@ describe('Message', function(){
|
||||
|
||||
});
|
||||
|
||||
describe('verifyHashSignature', function(){
|
||||
describe('verifyHashSignature', function() {
|
||||
|
||||
it('should throw an error if a callback function is not supplied', function(){
|
||||
it('should throw an error if a callback function is not supplied', function() {
|
||||
|
||||
var data = {
|
||||
message: 'Hello world!',
|
||||
@@ -193,15 +195,12 @@ describe('Message', function(){
|
||||
account: 'rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz'
|
||||
};
|
||||
|
||||
//Remote.prototype.addServer = function(){};
|
||||
var test_remote = new Remote();
|
||||
|
||||
assert.throws(function(){
|
||||
assert.throws(function() {
|
||||
Message.verifyHashSignature(data);
|
||||
}, /(?=.*callback\ function).*/);
|
||||
});
|
||||
|
||||
it('should respond with an error if the hash is missing or invalid', function(done){
|
||||
it('should respond with an error if the hash is missing or invalid', function(done) {
|
||||
|
||||
var data = {
|
||||
message: 'Hello world!',
|
||||
@@ -209,18 +208,17 @@ describe('Message', function(){
|
||||
account: 'rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz'
|
||||
};
|
||||
|
||||
//Remote.prototype.addServer = function(){};
|
||||
var test_remote = new Remote();
|
||||
test_remote.state = 'online';
|
||||
|
||||
Message.verifyHashSignature(data, test_remote, function(err, valid){
|
||||
Message.verifyHashSignature(data, test_remote, function(err) {
|
||||
assert(/hash/i.test(err.message));
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should respond with an error if the account is missing or invalid', function(done){
|
||||
it('should respond with an error if the account is missing or invalid', function(done) {
|
||||
|
||||
var data = {
|
||||
message: 'Hello world!',
|
||||
@@ -228,18 +226,17 @@ describe('Message', function(){
|
||||
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){
|
||||
Message.verifyHashSignature(data, test_remote, function(err) {
|
||||
assert(/account|address/i.test(err.message));
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should respond with an error if the signature is missing or invalid', function(done){
|
||||
it('should respond with an error if the signature is missing or invalid', function(done) {
|
||||
|
||||
var data = {
|
||||
message: 'Hello world!',
|
||||
@@ -247,18 +244,17 @@ describe('Message', function(){
|
||||
account: 'rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz'
|
||||
};
|
||||
|
||||
//Remote.prototype.addServer = function(){};
|
||||
var test_remote = new Remote();
|
||||
test_remote.state = 'online';
|
||||
|
||||
Message.verifyHashSignature(data, test_remote, function(err, valid){
|
||||
Message.verifyHashSignature(data, test_remote, function(err) {
|
||||
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){
|
||||
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!',
|
||||
@@ -267,18 +263,17 @@ describe('Message', function(){
|
||||
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"
|
||||
'account_data': {
|
||||
'Account': 'rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz',
|
||||
'Flags': 1114112,
|
||||
'LedgerEntryType': 'AccountRoot',
|
||||
'RegularKey': 'rHq2wyUtLkAad3vURUk33q9gozd97skhSf'
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -286,7 +281,7 @@ describe('Message', function(){
|
||||
}
|
||||
};
|
||||
|
||||
Message.verifyHashSignature(data, test_remote, function(err, valid){
|
||||
Message.verifyHashSignature(data, test_remote, function(err, valid) {
|
||||
assert(!err);
|
||||
assert(valid);
|
||||
done();
|
||||
@@ -294,7 +289,7 @@ describe('Message', function(){
|
||||
|
||||
});
|
||||
|
||||
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){
|
||||
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 = {
|
||||
@@ -304,18 +299,17 @@ describe('Message', function(){
|
||||
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"
|
||||
'account_data': {
|
||||
'Account': 'rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz',
|
||||
'Flags': 1114112,
|
||||
'LedgerEntryType': 'AccountRoot',
|
||||
'RegularKey': 'rHq2wyUtLkAad3vURUk33q9gozd97skhSf'
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -323,7 +317,7 @@ describe('Message', function(){
|
||||
}
|
||||
};
|
||||
|
||||
Message.verifyHashSignature(data, test_remote, function(err, valid){
|
||||
Message.verifyHashSignature(data, test_remote, function(err, valid) {
|
||||
assert(!err);
|
||||
assert(!valid);
|
||||
done();
|
||||
|
||||
Reference in New Issue
Block a user