Message signing

This commit is contained in:
Will O'Beirne 2018-05-04 00:26:25 -04:00
parent b9bd734cd0
commit b4d8f3617f
No known key found for this signature in database
GPG Key ID: 44C190DB5DEAF9F6
9 changed files with 75 additions and 12 deletions

View File

@ -76,6 +76,15 @@ export class LedgerWallet extends HardwareWallet implements IFullWallet {
// modeled after
// https://github.com/kvhnuke/etherwallet/blob/3f7ff809e5d02d7ea47db559adaca1c930025e24/app/scripts/controllers/signMsgCtrl.js#L53
public async signMessage(msg: string): Promise<string> {
if (process.env.BUILD_ELECTRON) {
const res = await EnclaveAPI.signMessage({
walletType: WalletTypes.LEDGER,
message: msg,
path: this.getPath()
});
return res.signedMessage;
}
const msgHex = Buffer.from(msg).toString('hex');
try {
const signed = await this.ethApp.signPersonalMessage_async(this.getPath(), msgHex);

View File

@ -1,4 +1,3 @@
import EthTx from 'ethereumjs-tx';
import { makeRequest } from './requests';
import {
EnclaveMethods,
@ -7,7 +6,9 @@ import {
GetChainCodeParams,
GetChainCodeResponse,
SignTransactionParams,
SignTransactionResponse
SignTransactionResponse,
SignMessageParams,
SignMessageResponse
} from 'shared/enclave/types';
const api = {
@ -19,8 +20,12 @@ const api = {
return makeRequest<GetChainCodeResponse>(EnclaveMethods.GET_CHAIN_CODE, params);
},
async signTransaction(params: SignTransactionParams) {
signTransaction(params: SignTransactionParams) {
return makeRequest<SignTransactionResponse>(EnclaveMethods.SIGN_TRANSACTION, params);
},
signMessage(params: SignMessageParams) {
return makeRequest<SignMessageResponse>(EnclaveMethods.SIGN_MESSAGE, params);
}
};

View File

@ -1,6 +1,7 @@
import getAddresses from './getAddresses';
import getChainCode from './getChainCode';
import signTransaction from './signTransaction';
import signMessage from './signMessage';
import { EnclaveMethods, EnclaveMethodParams, EnclaveMethodResponse } from 'shared/enclave/types';
const handlers: {
@ -10,7 +11,8 @@ const handlers: {
} = {
[EnclaveMethods.GET_ADDRESSES]: getAddresses,
[EnclaveMethods.GET_CHAIN_CODE]: getChainCode,
[EnclaveMethods.SIGN_TRANSACTION]: signTransaction
[EnclaveMethods.SIGN_TRANSACTION]: signTransaction,
[EnclaveMethods.SIGN_MESSAGE]: signMessage
};
export default handlers;

View File

@ -0,0 +1,7 @@
import { getWalletLib } from 'shared/enclave/server/wallets';
import { SignMessageParams, SignMessageResponse } from 'shared/enclave/types';
export default function(params: SignMessageParams): Promise<SignMessageResponse> {
const wallet = getWalletLib(params.walletType);
return wallet.signMessage(params.message, params.path);
}

View File

@ -1,7 +1,7 @@
import { getWalletLib } from 'shared/enclave/server/wallets';
import { SignTransactionParams, SignTransactionResponse } from 'shared/enclave/types';
export default function(params: SignTransactionParams): SignTransactionResponse {
export default function(params: SignTransactionParams): Promise<SignTransactionResponse> {
const wallet = getWalletLib(params.walletType);
return wallet.signTransaction(params.transaction, params.path);
}

View File

@ -2,7 +2,15 @@ import { WalletLib } from 'shared/enclave/types';
const KeepKey: WalletLib = {
async getChainCode() {
throw new Error('Not yet supported');
throw new Error('Not yet implemented');
},
async signTransaction() {
throw new Error('Not yet implemented');
},
async signMessage() {
throw new Error('Not yet implemented');
}
};

View File

@ -1,6 +1,6 @@
import EthTx from 'ethereumjs-tx';
import { addHexPrefix, toBuffer } from 'ethereumjs-util';
import { WalletLib, RawTransaction } from 'shared/enclave/types';
import { WalletLib } from 'shared/enclave/types';
import TransportNodeHid from '@ledgerhq/hw-transport-node-hid';
import LedgerEth from '@ledgerhq/hw-app-eth';
@ -20,7 +20,7 @@ async function getEthApp() {
}
const Ledger: WalletLib = {
async getChainCode(dpath: string) {
async getChainCode(dpath) {
const app = await getEthApp();
try {
const res = await app.getAddress(dpath, false, true);
@ -33,7 +33,7 @@ const Ledger: WalletLib = {
}
},
async signTransaction(tx: RawTransaction, path: string) {
async signTransaction(tx, path) {
const app = await getEthApp();
const ethTx = new EthTx({
...tx,
@ -52,6 +52,16 @@ const Ledger: WalletLib = {
return {
signedTransaction: signedTx.serialize().toString('hex')
};
},
async signMessage(msg: string, path: string) {
const app = await getEthApp();
const msgHex = Buffer.from(msg).toString('hex');
const signed = await app.signPersonalMessage(path, msgHex);
const combined = addHexPrefix(signed.r + signed.s + signed.v.toString(16));
return {
signedMessage: combined
};
}
};

View File

@ -18,6 +18,10 @@ const Trezor: WalletLib = {
async signTransaction() {
throw new Error('Not yet implemented');
},
async signMessage() {
throw new Error('Not yet implemented');
}
};

View File

@ -2,7 +2,8 @@
export enum EnclaveMethods {
GET_ADDRESSES = 'get-addresses',
GET_CHAIN_CODE = 'get-chain-code',
SIGN_TRANSACTION = 'sign-transaction'
SIGN_TRANSACTION = 'sign-transaction',
SIGN_MESSAGE = 'sign-message'
}
export enum WalletTypes {
@ -52,12 +53,28 @@ export interface SignTransactionResponse {
signedTransaction: string;
}
// Sign Message Request
export interface SignMessageParams {
walletType: WalletTypes;
message: string;
path: string;
}
export interface SignMessageResponse {
signedMessage: string;
}
// All Requests & Responses
export type EnclaveMethodParams = GetAddressesParams | GetChainCodeParams | SignTransactionParams;
export type EnclaveMethodParams =
| GetAddressesParams
| GetChainCodeParams
| SignTransactionParams
| SignMessageParams;
export type EnclaveMethodResponse =
| GetAddressesResponse
| GetChainCodeResponse
| SignTransactionResponse;
| SignTransactionResponse
| SignMessageResponse;
// RPC requests, responses & failures
export interface EnclaveSuccessResponse<T = EnclaveMethodResponse> {
@ -82,4 +99,5 @@ export type EnclaveResponse<T = EnclaveMethodResponse> =
export interface WalletLib {
getChainCode(dpath: string): Promise<GetChainCodeResponse>;
signTransaction(transaction: RawTransaction, path: string): Promise<SignTransactionResponse>;
signMessage(msg: string, path: string): Promise<SignMessageResponse>;
}