add file necryption

This commit is contained in:
Yostra 2020-08-02 16:17:14 -07:00 committed by Gene Hoffman
parent 8ee1ebb266
commit 94e4afc652
9 changed files with 122 additions and 46 deletions

View File

@ -288,30 +288,40 @@ export const login_action = fingerprint => {
};
};
export const get_backup_info = file_path => {
export const get_backup_info = (file_path, fingerprint, words) => {
var action = walletMessage();
action.message.command = "get_backup_info";
action.message.data = {
file_path: file_path
};
if (fingerprint === null) {
action.message.data = {
file_path: file_path,
words: words
};
} else if (words === null) {
action.message.data = {
file_path: file_path,
fingerprint: fingerprint
};
}
return action;
};
export const get_backup_info_action = file_path => {
export const get_backup_info_action = (file_path, fingerprint, words) => {
return dispatch => {
dispatch(selectFilePath(file_path));
return async_api(dispatch, get_backup_info(file_path), true).then(
response => {
dispatch(closeProgress());
if (response.data.success) {
dispatch(setBackupInfo(response.data.backup_info));
dispatch(changeBackupView(presentBackupInfo));
} else {
const error = response.data.error;
dispatch(openDialog("Error", error));
}
return async_api(
dispatch,
get_backup_info(file_path, fingerprint, words),
true
).then(response => {
dispatch(closeProgress());
if (response.data.success) {
dispatch(setBackupInfo(response.data.backup_info));
dispatch(changeBackupView(presentBackupInfo));
} else {
const error = response.data.error;
dispatch(openDialog("Error", error));
}
);
});
};
};

View File

@ -45,8 +45,6 @@ const UIPart = props => {
}
function skip() {
dispatch(get_backup_info_action("/Users/yostra/Desktop/tri"));
return;
if (fingerprint !== null) {
dispatch(login_and_skip_action(fingerprint));
} else if (words !== null) {
@ -72,7 +70,11 @@ const UIPart = props => {
const file_path = e.dataTransfer.files[0].path;
debugger;
dispatch(get_backup_info_action(file_path));
if (fingerprint !== null) {
dispatch(get_backup_info_action(file_path, fingerprint, null));
} else if (words !== null) {
dispatch(get_backup_info_action(file_path, null, words));
}
};
return (

View File

@ -5,6 +5,8 @@ from pathlib import Path
from typing import List, Optional, Tuple, Dict, Callable
from blspy import PrivateKey
from src.util.byte_types import hexstr_to_bytes
from src.util.keychain import (
generate_mnemonic,
@ -439,7 +441,7 @@ class WalletRpcApi:
async def cc_get_colour(self, request):
wallet_id = int(request["wallet_id"])
wallet: CCWallet = self.service.wallet_state_manager.wallets[wallet_id]
colour: str = await wallet.get_colour()
colour: str = wallet.get_colour()
response = {"colour": colour, "wallet_id": wallet_id}
return response
@ -453,7 +455,7 @@ class WalletRpcApi:
type = wallet.wallet_info.type
if type == WalletType.COLOURED_COIN.value:
name = wallet.cc_info.my_colour_name
colour = await wallet.get_colour()
colour = wallet.get_colour()
response[wallet_id] = {
"type": type,
"balance": balance,
@ -510,7 +512,34 @@ class WalletRpcApi:
async def get_backup_info(self, request: Dict):
file_path = Path(request["file_path"])
backup_info = get_backup_info(file_path)
sk = None
if "words" in request:
mnemonic = request["words"]
passphrase = ""
try:
sk = self.service.keychain.add_private_key(
" ".join(mnemonic), passphrase
)
except KeyError as e:
return {
"success": False,
"error": f"The word '{e.args[0]}' is incorrect.'",
"word": e.args[0],
}
except ValueError as e:
return {
"success": False,
"error": e.args[0],
}
elif "fingerprint" in request:
sk, seed = await self._get_private_key(request["fingerprint"])
if sk is None:
return {
"success": False,
"error": "Unable to decrypt the backup file, no such key."
}
backup_info = get_backup_info(file_path, sk)
response = {"success": True, "backup_info": backup_info}
return response
@ -537,20 +566,26 @@ class WalletRpcApi:
response = {"success": True, "public_key_fingerprints": fingerprints}
return response
async def get_private_key(self, request):
fingerprint = request["fingerprint"]
async def _get_private_key(self, fingerprint) -> Tuple[Optional[PrivateKey], Optional[bytes]]:
for sk, seed in self.service.keychain.get_all_private_keys():
if sk.get_g1().get_fingerprint() == fingerprint:
s = bytes_to_mnemonic(seed) if seed is not None else None
return {
"success": True,
"private_key": {
"fingerprint": fingerprint,
"sk": bytes(sk).hex(),
"pk": bytes(sk.get_g1()).hex(),
"seed": s,
},
}
return sk, seed
return None, None
async def get_private_key(self, request):
fingerprint = request["fingerprint"]
sk, seed = await self._get_private_key(fingerprint)
if sk is not None:
s = bytes_to_mnemonic(seed) if seed is not None else None
return {
"success": True,
"private_key": {
"fingerprint": fingerprint,
"sk": bytes(sk).hex(),
"pk": bytes(sk.get_g1()).hex(),
"seed": s,
},
}
return {"success": False, "private_key": {"fingerprint": fingerprint}}
async def log_in(self, request):

View File

@ -228,7 +228,7 @@ class CCWallet:
self.wallet_info = new_info
await self.wallet_state_manager.user_store.update_wallet(self.wallet_info)
async def get_colour(self):
def get_colour(self):
return self.cc_info.my_colour_name
async def coin_added(
@ -516,7 +516,7 @@ class CCWallet:
our_spend = False
for coin in record.removals:
# Don't count eve spend as change
if coin.parent_coin_info.hex() == await self.get_colour():
if coin.parent_coin_info.hex() == self.get_colour():
continue
if await self.wallet_state_manager.does_coin_belong_to_wallet(
coin, self.wallet_info.id

View File

@ -5,7 +5,7 @@ from src.util.ints import uint32
# https://eips.ethereum.org/EIPS/eip-2334
# 12381 = bls spec number
# 8444 = Chia blockchain number and port number
# 0, 1, 2, 3, farmer, pool, wallet, local key numbers
# 0, 1, 2, 3, 4, farmer, pool, wallet, local, backup key numbers
def master_sk_to_farmer_sk(master: PrivateKey) -> PrivateKey:
@ -27,3 +27,7 @@ def master_sk_to_wallet_sk(master: PrivateKey, index: uint32) -> PrivateKey:
def master_sk_to_local_sk(master: PrivateKey) -> PrivateKey:
return master.derive_child(12381).derive_child(8444).derive_child(3).derive_child(0)
def master_sk_to_backup_sk(master: PrivateKey) -> PrivateKey:
return master.derive_child(12381).derive_child(8444).derive_child(4).derive_child(0)

View File

@ -1,13 +1,23 @@
import base64
import json
from cryptography.fernet import Fernet
from src.wallet.derive_keys import master_sk_to_backup_sk
from src.wallet.util.wallet_types import WalletType
def get_backup_info(file_path):
def get_backup_info(file_path, private_key):
info_dict = {}
wallets = []
backup_text = file_path.read_text()
encrypted_backup_text = file_path.read_text()
backup_pk = master_sk_to_backup_sk(private_key)
key_base_64 = base64.b64encode(bytes(backup_pk))
f = Fernet(key_base_64)
backup_text_data = f.decrypt(encrypted_backup_text.encode())
backup_text = backup_text_data.decode()
json_dict = json.loads(backup_text)
wallet_list_json = json_dict["wallet_list"]

View File

@ -1,3 +1,4 @@
import base64
import json
import time
from pathlib import Path
@ -9,6 +10,7 @@ import asyncio
import aiosqlite
from chiabip158 import PyBIP158
from blspy import PrivateKey, G1Element
from cryptography.fernet import Fernet
from src.consensus.constants import ConsensusConstants
from src.types.coin import Coin
@ -45,7 +47,7 @@ from src.types.program import Program
from src.wallet.derivation_record import DerivationRecord
from src.wallet.util.wallet_types import WalletType
from src.consensus.find_fork_point import find_fork_point_in_chain
from src.wallet.derive_keys import master_sk_to_wallet_sk
from src.wallet.derive_keys import master_sk_to_wallet_sk, master_sk_to_backup_sk
from src import __version__
@ -1331,10 +1333,23 @@ class WalletStateManager:
json_dict["version"] = __version__
json_dict["fingerprint"] = self.private_key.get_g1().get_fingerprint()
json_dict["timestamp"] = uint64(int(time.time()))
file_path.write_text(json.dumps(json_dict))
backup_pk = master_sk_to_backup_sk(self.private_key)
key_base_64 = base64.b64encode(bytes(backup_pk))
f = Fernet(key_base_64)
backup_data = json.dumps(json_dict).encode()
encrypted = f.encrypt(backup_data)
file_path.write_text(encrypted.decode())
async def import_backup_info(self, file_path):
backup_text = file_path.read_text()
encrypted_backup_text = file_path.read_text()
backup_pk = master_sk_to_backup_sk(self.private_key)
key_base_64 = base64.b64encode(bytes(backup_pk))
f = Fernet(key_base_64)
backup_text_data = f.decrypt(encrypted_backup_text.encode())
backup_text = backup_text_data.decode()
json_dict = json.loads(backup_text)
wallet_list_json = json_dict["wallet_list"]

View File

@ -180,7 +180,7 @@ class TestCCWallet:
for i in range(1, num_blocks):
await full_node_1.farm_new_block(FarmNewBlockProtocol(ph))
colour = await cc_wallet.get_colour()
colour = cc_wallet.get_colour()
assert (
await wallet_node.wallet_state_manager.get_wallet_for_colour(colour)
== cc_wallet

View File

@ -215,8 +215,8 @@ class TestCCTrades:
assert offer is not None
assert offer["chia"] == -1000
colour_2 = await cc_a_2.get_colour()
colour_3 = await cc_a_3.get_colour()
colour_2 = cc_a_2.get_colour()
colour_3 = cc_a_3.get_colour()
assert offer[colour_2] == 20
assert offer[colour_3] == 50
@ -265,7 +265,7 @@ class TestCCTrades:
await time_out_assert(15, cc_a_4.get_confirmed_balance, 100)
colour = await cc_a_4.get_colour()
colour = cc_a_4.get_colour()
cc_b_4: CCWallet = await CCWallet.create_wallet_for_cc(
wallet_node_b.wallet_state_manager, wallet_b, colour