Skip to content

Commit

Permalink
Store seed instead of private key (#110)
Browse files Browse the repository at this point in the history
* Store seed instead of private key

* replace pk with seed

* Fix seed key

* fix legacy 118 terra wallets

* cleanup fix imports

* cleanup

---------

Co-authored-by: plubber <[email protected]>
Co-authored-by: plubber <[email protected]>
  • Loading branch information
3 people authored Apr 11, 2023
1 parent c41d73f commit e82091b
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 97 deletions.
30 changes: 15 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"@ledgerhq/hw-transport-web-ble": "^6.27.1",
"@mui/icons-material": "^5.8.0",
"@mui/material": "^5.9.1",
"@terra-money/feather.js": "^1.0.0-beta.11",
"@terra-money/feather.js": "^1.0.0-beta.15",
"@terra-money/ledger-station-js": "^1.3.7",
"@terra-money/log-finder-ruleset": "^3.0.0",
"@terra-money/msg-reader": "^3.0.1",
Expand Down
13 changes: 12 additions & 1 deletion src/auth/auth.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ type StoredWallet =
| StoredWalletLegacy
| MultisigWallet
| LedgerWallet
type ResultStoredWallet = LegacyStoredWallet | MultisigWallet | StoredWallet
| SeedStoredWallet
type ResultStoredWallet =
| LegacyStoredWallet
| MultisigWallet
| StoredWallet
| SeedStoredWallet

// interchain types
interface SingleWallet {
Expand Down Expand Up @@ -51,6 +56,12 @@ interface InterchainStoredWallet extends SingleWallet {
}
}

interface SeedStoredWallet extends SingleWallet {
encryptedSeed: string
index: number
legacy: boolean
}

// legacy types (pre-interchain)
interface LegacySingleWallet {
address: string
Expand Down
119 changes: 89 additions & 30 deletions src/auth/hooks/useAuth.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { useCallback, useMemo } from "react"
import { atom, useRecoilState } from "recoil"
import { encode } from "js-base64"
import { CreateTxOptions, Tx, isTxError } from "@terra-money/feather.js"
import {
CreateTxOptions,
Tx,
isTxError,
SeedKey,
} from "@terra-money/feather.js"
import { AccAddress, SignDoc } from "@terra-money/feather.js"
import { RawKey, SignatureV2 } from "@terra-money/feather.js"
import { LedgerKey } from "@terra-money/ledger-station-js"
Expand Down Expand Up @@ -127,6 +132,9 @@ const useAuth = () => {
const { name, words } = getConnectedWallet()
const key = getKey(password)
if (!key) throw new PasswordError("Key do not exist")
// TODO: update key export
if ("seed" in key) throw new PasswordError("This key cannot be exported")

const data = {
name,
address: addressFromWords(words["330"], "terra"),
Expand Down Expand Up @@ -181,12 +189,23 @@ const useAuth = () => {
return await key.createSignatureAmino(doc)
} else {
const pk = getKey(password)
if (!pk || !pk[networks[chainID].coinType])
throw new PasswordError("Incorrect password")
const key = new RawKey(
Buffer.from(pk[networks[chainID].coinType] ?? "", "hex")
)
return await key.createSignatureAmino(doc)
if (!pk) throw new PasswordError("Incorrect password")

if ("seed" in pk) {
const key = new SeedKey({
seed: Buffer.from(pk.seed, "hex"),
coinType: pk.legacy ? 118 : parseInt(networks[chainID].coinType),
index: pk.index || 0,
})
return await key.createSignatureAmino(doc)
} else {
if (!pk[networks[chainID].coinType])
throw new PasswordError("Incorrect password")
const key = new RawKey(
Buffer.from(pk[networks[chainID].coinType] ?? "", "hex")
)
return await key.createSignatureAmino(doc)
}
}
}

Expand All @@ -195,13 +214,26 @@ const useAuth = () => {

if (is.ledger(wallet)) {
const key = await getLedgerKey(coinType)
return await key.publicKey
// @ts-expect-error
return key.publicKey.key
} else {
const pk = getKey(password)
if (!pk || !pk[coinType]) throw new PasswordError("Incorrect password")
const key = new RawKey(Buffer.from(pk[coinType] ?? "", "hex"))
// @ts-expect-error
return await key.publicKey.key
if (!pk) throw new PasswordError("Incorrect password")

if ("seed" in pk) {
const key = new SeedKey({
seed: Buffer.from(pk.seed, "hex"),
coinType: pk.legacy ? 118 : parseInt(coinType),
index: pk.index || 0,
})
// @ts-expect-error
return key.publicKey.key
} else {
if (!pk[coinType]) throw new PasswordError("Incorrect password")
const key = new RawKey(Buffer.from(pk[coinType] ?? "", "hex"))
// @ts-expect-error
return key.publicKey.key
}
}
}

Expand All @@ -216,18 +248,29 @@ const useAuth = () => {
...txOptions,
signMode,
})
} /*else if (is.preconfigured(wallet)) {
const key = new MnemonicKey({ mnemonic: wallet.mnemonic })
return await lcd.wallet(key).createAndSignTx(txOptions)
}*/ else {
} else {
const pk = getKey(password)
if (!pk || !pk[networks[txOptions.chainID].coinType])
throw new PasswordError("Incorrect password")
const key = new RawKey(
Buffer.from(pk[networks[txOptions.chainID].coinType] ?? "", "hex")
)
const wallet = lcd.wallet(key)
return await wallet.createAndSignTx(txOptions)
if (!pk) throw new PasswordError("Incorrect password")

if ("seed" in pk) {
const key = new SeedKey({
seed: Buffer.from(pk.seed, "hex"),
coinType: pk.legacy
? 118
: parseInt(networks[txOptions.chainID].coinType),
index: pk.index || 0,
})
const w = lcd.wallet(key)
return await w.createAndSignTx(txOptions)
} else {
if (!pk[networks[txOptions.chainID].coinType])
throw new PasswordError("Incorrect password")
const key = new RawKey(
Buffer.from(pk[networks[txOptions.chainID].coinType] ?? "", "hex")
)
const w = lcd.wallet(key)
return await w.createAndSignTx(txOptions)
}
}
}

Expand All @@ -239,13 +282,29 @@ const useAuth = () => {
} else {
const pk = getKey(password)
if (!pk) throw new PasswordError("Incorrect password")
const key = new RawKey(Buffer.from(pk["330"], "hex"))
const { signature, recid } = key.ecdsaSign(bytes)
if (!signature) throw new Error("Signature is undefined")
return {
recid,
signature: Buffer.from(signature).toString("base64"),
public_key: key.publicKey?.toAmino().value as string,

if ("seed" in pk) {
const key = new SeedKey({
seed: Buffer.from(pk.seed, "hex"),
coinType: pk.legacy ? 118 : 330,
index: pk.index || 0,
})
const { signature, recid } = key.ecdsaSign(bytes)
if (!signature) throw new Error("Signature is undefined")
return {
recid,
signature: Buffer.from(signature).toString("base64"),
public_key: key.publicKey?.toAmino().value as string,
}
} else {
const key = new RawKey(Buffer.from(pk["330"], "hex"))
const { signature, recid } = key.ecdsaSign(bytes)
if (!signature) throw new Error("Signature is undefined")
return {
recid,
signature: Buffer.from(signature).toString("base64"),
public_key: key.publicKey?.toAmino().value as string,
}
}
}
}
Expand Down
31 changes: 19 additions & 12 deletions src/auth/modules/create/CreateWalletWizard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ReactNode, useEffect, useState } from "react"
import { useLocation, useNavigate } from "react-router-dom"
import { MnemonicKey } from "@terra-money/feather.js"
import { SeedKey } from "@terra-money/feather.js"
import createContext from "utils/createContext"
import { addWallet } from "../../scripts/keystore"
import CreateWalletForm from "./CreateWalletForm"
Expand Down Expand Up @@ -54,23 +54,30 @@ const CreateWalletWizard = ({ defaultMnemonic = "", beforeCreate }: Props) => {
const [createdWallet, setCreatedWallet] = useState<SingleWallet>()
const createWallet = (coinType: Bip, index = 0) => {
const { name, password, mnemonic } = values
const mk330 = new MnemonicKey({ mnemonic, coinType, index })
const mk118 = new MnemonicKey({ mnemonic, coinType: 118, index })

const seed = SeedKey.seedFromMnemonic(mnemonic)
const key330 = new SeedKey({ seed, coinType, index })
const key118 = new SeedKey({ seed, coinType: 118, index })
const words = {
"330": wordsFromAddress(mk330.accAddress("terra")),
"118": wordsFromAddress(mk118.accAddress("terra")),
"330": wordsFromAddress(key330.accAddress("terra")),
"118": wordsFromAddress(key118.accAddress("terra")),
}
const pubkey = {
// @ts-expect-error
"330": mk330.publicKey.key,
"330": key330.publicKey.key,
// @ts-expect-error
"118": mk118.publicKey.key,
}
const key = {
"330": mk330.privateKey,
"118": mk118.privateKey,
"118": key118.publicKey.key,
}
addWallet({ name, password, words, key, pubkey })

addWallet({
name,
password,
words,
seed,
pubkey,
index,
legacy: coinType === 118,
})
setCreatedWallet({ name, words, pubkey })
setStep(3)
}
Expand Down
7 changes: 4 additions & 3 deletions src/auth/modules/create/SelectAddress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useTranslation } from "react-i18next"
import { useQuery } from "react-query"
import { useForm } from "react-hook-form"
import { readAmount } from "@terra-money/terra-utils"
import { MnemonicKey, AccAddress } from "@terra-money/feather.js"
import { SeedKey, AccAddress } from "@terra-money/feather.js"
import { Coins, Delegation, UnbondingDelegation } from "@terra-money/feather.js"
import { sortCoins } from "utils/coin"
import { useInterchainLCDClient } from "data/queries/lcdClient"
Expand All @@ -23,15 +23,16 @@ const SelectAddress = () => {
const readNativeDenom = useNativeDenoms()
const { values, createWallet } = useCreateWallet()
const { mnemonic, index } = values
const seed = SeedKey.seedFromMnemonic(mnemonic)

/* query */
const { data: results } = useQuery(
// FIXME: remove mnemonic from this array
["mnemonic", mnemonic, index],
["mnemonic", seed, index],
async () => {
const results = await Promise.allSettled(
([118, 330] as const).map(async (bip) => {
const mk = new MnemonicKey({ mnemonic, coinType: bip, index })
const mk = new SeedKey({ seed, coinType: bip, index })
const address = mk.accAddress("terra")
const [balance] = await lcd.bank.balance(address)
const [delegations] = await lcd.staking.delegations(address)
Expand Down
6 changes: 6 additions & 0 deletions src/auth/scripts/is.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ const isPreconfigured = (wallet?: Wallet): wallet is PreconfiguredWallet => {
return "mnemonic" in wallet
}

const isSeed = (wallet?: Wallet): wallet is SeedStoredWallet => {
if (!isLocal(wallet)) return false
return "encryptedSeed" in wallet
}

const isSingle = (wallet?: Wallet): wallet is SingleWallet => {
if (!isLocal(wallet)) return false
return !isPreconfigured(wallet) && !isMultisig(wallet) && !isLedger(wallet)
Expand All @@ -35,6 +40,7 @@ const is = {
multisig: isMultisig,
single: isSingle,
ledger: isLedger,
seed: isSeed,
}

export default is
Loading

0 comments on commit e82091b

Please sign in to comment.