Skip to content

Commit 2a498b6

Browse files
authored
Merge pull request #66 from Sword-Smith/master
Fix broken unit tests
2 parents 981b7b3 + bfb2e7c commit 2a498b6

File tree

6 files changed

+135
-31
lines changed

6 files changed

+135
-31
lines changed

app/admin.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ const validateKey = function(key, type) {
208208
if (process.config.verificationPub) {
209209

210210
if (!key.signature) {
211-
console.log(`Key ${key.pub} requires a signature and does not have one.`);
211+
console.log(`Key ${key.pub} has a verification public key but no signature.`);
212212
return false;
213213
}
214214

app/sign.js

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ const confirmRecovery = function(backupKey, outputs, customMessage, skipConfirm)
7878
}
7979
};
8080

81+
/**
82+
* Verifies that input is a valid HD key and parses it into HDNode object.
83+
* @param xprv Base58 representation of extended private key
84+
* @param expectedXpub The corresponding extended public key
85+
* @returns The HDNode object representing the extended private key
86+
*/
8187
const getHDNodeAndVerify = function(xprv, expectedXpub) {
8288
let node;
8389

@@ -99,7 +105,7 @@ const getHDNodeAndVerify = function(xprv, expectedXpub) {
99105
};
100106

101107
/**
102-
* Prints the recovery transaction information and prompt for the confirmation as well as the key, if needed to.
108+
* Prints the recovery transaction information and prompt the user for the confirmation as well as the key, if needed to.
103109
* @param recoveryRequest The recovery transansaction request object.
104110
* @param outputs The outputs of the transaction.
105111
* @param skipConfirm The boolean value that indicates to whether or not to prompt the user to confirm the transaction.
@@ -120,14 +126,14 @@ const promptForConfirmationAndKey = function(recoveryRequest, outputs, skipConfi
120126

121127
/**
122128
* Gets the backup private key that can be used to sign the transaction.
123-
* @param key The provided private key.
129+
* @param xprv The provided extended private key (BIP32).
124130
* @param expectedXpub The public key specified with the request.
125131
* @returns The private key to sign the transaction.
126132
*/
127-
const getBackupSigningKey = function(key, expectedXpub) {
128-
const backupKeyNode = getHDNodeAndVerify(key, expectedXpub);
133+
const getBackupSigningKey = function(xprv, expectedXpub) {
134+
const backupKeyNode = getHDNodeAndVerify(xprv, expectedXpub);
129135

130-
return backupKeyNode.keyPair.getPrivateKeyBuffer;
136+
return backupKeyNode.keyPair.getPrivateKeyBuffer();
131137
}
132138

133139
const handleSignUtxo = function(recoveryRequest, key, skipConfirm) {
@@ -219,6 +225,7 @@ const handleSignEthereum = function(recoveryRequest, key, skipConfirm) {
219225
*/
220226
const signEthTx = function(recoveryRequest, key, skipConfirm, isToken) {
221227
const EthTx = require('ethereumjs-tx');
228+
const EthUtil = require('ethereumjs-util');
222229

223230
const txHex = getTransactionHexFromRequest(recoveryRequest);
224231
const transaction = new EthTx(txHex);
@@ -236,9 +243,20 @@ const signEthTx = function(recoveryRequest, key, skipConfirm, isToken) {
236243
outputs[0].amount = outputs[0].amount.div(TEN.pow(decimals));
237244
}
238245

239-
key = promptForConfirmationAndKey(recoveryRequest, outputs, skipConfirm, key);
246+
// When generating signatures, we don't currently use EIP155 but this could
247+
// be activated if we wanted to. This would protect against replay attacks on other
248+
// blockchains, such as Ethereum Classic. To activate the EIP155, we would have to
249+
// know the chain ID of the Ethereum blockchains we are using as this value goes
250+
// into the V field when using EIP155.
251+
// cf. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
252+
const useEip155 = false;
240253

241-
transaction.sign(getBackupSigningKey(key, recoveryRequest.backupKey));
254+
key = promptForConfirmationAndKey(recoveryRequest, outputs, skipConfirm, key);
255+
const signingKey = Buffer.from(getBackupSigningKey(key, recoveryRequest.backupKey), "hex");
256+
const signature = EthUtil.ecsign(transaction.hash(useEip155), signingKey, transaction.chainId);
257+
transaction.v = signature.v; // Change this if activating EIP155
258+
transaction.r = signature.r;
259+
transaction.s = signature.s;
242260

243261
return transaction.serialize().toString('hex');
244262
};
@@ -258,8 +276,9 @@ const handleSignTrx = function(recoveryRequest, key, skipConfirm) {
258276
});
259277

260278
key = promptForConfirmationAndKey(recoveryRequest, outputs, skipConfirm, key);
279+
const signingKey = getBackupSigningKey(key, recoveryRequest.backupKey);
261280

262-
builder.sign({ key: getBackupSigningKey(key, recoveryRequest.backupKey) });
281+
builder.sign({ key: signingKey });
263282
return JSON.stringify(builder.build().toJson());
264283
};
265284

app/utils.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ exports.sendMailQ = function(toEmail, subject, template, templateParams, attachm
8787
return sendMail(mailOptions);
8888
};
8989

90+
/*
91+
* Check if input is a valid seed input formatted as a hex string.
92+
* Cf. the BIP32 specification, a valid seed is between 128 bits and 512 bits (both included),
93+
* i.e. between 16 and 64 bytes.
94+
* https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#master-key-generation
95+
*/
96+
function IsValidBip32Seed(input) {
97+
return input.match(/^(([0-9a-f]{2}){16,64})$/);
98+
}
99+
90100
/** deriveChildKey
91101
*
92102
* returns the derived key as a string
@@ -107,6 +117,12 @@ exports.deriveChildKey = function(master, derivationPath, type, neuter) {
107117

108118
return childKey.toBase58();
109119
} else if (type === 'xlm') {
120+
121+
// Verify that input is a valid seed, cf. SEP05 (Stellar Ecosystem Proposals 5) which follows BIP39
122+
// which is based on BIP32:
123+
// https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md
124+
if (!IsValidBip32Seed(master)) { throw new Error(`Invalid seed. Got: ${master}`); }
125+
110126
const masterNode = stellarHd.fromSeed(master);
111127
const childKey = stellar.Keypair.fromRawEd25519Seed(masterNode.derive(derivationPath));
112128

package-lock.json

Lines changed: 88 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"eosjs": "^16.0.9",
2828
"eosjs-ecc": "^4.0.4",
2929
"ethereumjs-tx": "^1.3.7",
30+
"ethereumjs-util": "6.2.0",
3031
"express": "^4.16.3",
3132
"jsrender": "^0.9.90",
3233
"lodash": "^4.17.11",

test/sign.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)