mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-26 08:55:56 +01:00
storage encryption
This commit is contained in:
parent
e8f8d62c1d
commit
809f9cae60
7 changed files with 196 additions and 58 deletions
9
App.js
9
App.js
|
@ -5,6 +5,7 @@ import { Text, ScrollView, StyleSheet } from 'react-native';
|
|||
import { DrawerNavigator, SafeAreaView } from 'react-navigation';
|
||||
import MainBottomTabs from './MainBottomTabs';
|
||||
import Selftest from './screen/selftest';
|
||||
import About from './screen/about';
|
||||
|
||||
require('./BlueApp');
|
||||
|
||||
|
@ -53,9 +54,6 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
/* import scanQrWifLegacyAddress from './screen/wallets/scanQrWifLegacyAddress'
|
||||
import scanQrWifSegwitP2SHAddress from './screen/wallets/scanQrWifSegwitP2SHAddress' */
|
||||
|
||||
const TabsInDrawer = DrawerNavigator(
|
||||
{
|
||||
MainBottomTabs: {
|
||||
|
@ -66,11 +64,14 @@ const TabsInDrawer = DrawerNavigator(
|
|||
}),
|
||||
},
|
||||
},
|
||||
|
||||
Selftest: {
|
||||
screen: Selftest,
|
||||
navigationOptions: {},
|
||||
},
|
||||
About: {
|
||||
screen: About,
|
||||
navigationOptions: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
contentComponent: CustomDrawerContentComponent,
|
||||
|
|
11
BlueApp.js
11
BlueApp.js
|
@ -1,4 +1,3 @@
|
|||
/* global alert */
|
||||
/**
|
||||
* @exports {AppStorage}
|
||||
*/
|
||||
|
@ -9,11 +8,11 @@ let EV = require('./events');
|
|||
/** @type {AppStorage} */
|
||||
let BlueApp = new AppStorage();
|
||||
|
||||
(async () => {
|
||||
async function startAndDecrypt(retry) {
|
||||
let password = false;
|
||||
if (await BlueApp.storageIsEncrypted()) {
|
||||
password = await prompt(
|
||||
'Enter password',
|
||||
(retry && 'Bad pasword, try again') || 'Enter password',
|
||||
'Your storage is encrypted. Password is required to decrypt it',
|
||||
);
|
||||
}
|
||||
|
@ -26,8 +25,10 @@ let BlueApp = new AppStorage();
|
|||
|
||||
if (!success && password) {
|
||||
// we had password and yet could not load/decrypt
|
||||
alert('Could not decrypt. Bad password.');
|
||||
await startAndDecrypt(true);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
startAndDecrypt();
|
||||
|
||||
module.exports = BlueApp;
|
||||
|
|
|
@ -78,8 +78,11 @@ export class AppStorage {
|
|||
try {
|
||||
let data = await AsyncStorage.getItem('data');
|
||||
if (password) {
|
||||
this.cachedPassword = password;
|
||||
data = this.decryptData(data, password);
|
||||
if (data) {
|
||||
// password is good, cache it
|
||||
this.cachedPassword = password;
|
||||
}
|
||||
}
|
||||
if (data !== null) {
|
||||
data = JSON.parse(data);
|
||||
|
@ -167,9 +170,12 @@ export class AppStorage {
|
|||
newData.push(
|
||||
encryption.encrypt(JSON.stringify(data), this.cachedPassword),
|
||||
);
|
||||
await AsyncStorage.setItem(AppStorage.FLAG_ENCRYPTED, '1');
|
||||
}
|
||||
}
|
||||
data = newData;
|
||||
} else {
|
||||
await AsyncStorage.setItem(AppStorage.FLAG_ENCRYPTED, ''); // drop the flag
|
||||
}
|
||||
|
||||
return AsyncStorage.setItem('data', JSON.stringify(data));
|
||||
|
|
|
@ -6,14 +6,6 @@ module.exports = function(title, text) {
|
|||
title,
|
||||
text,
|
||||
[
|
||||
{
|
||||
text: 'Cancel',
|
||||
onPress: () => {
|
||||
console.log('Cancel Pressed');
|
||||
reject(new Error('Cancel Pressed'));
|
||||
},
|
||||
style: 'cancel',
|
||||
},
|
||||
{
|
||||
text: 'OK',
|
||||
onPress: password => {
|
||||
|
|
128
screen/about.js
Normal file
128
screen/about.js
Normal file
|
@ -0,0 +1,128 @@
|
|||
import React, { Component } from 'react';
|
||||
import { ScrollView, Linking } from 'react-native';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import {
|
||||
BlueLoading,
|
||||
BlueSpacing20,
|
||||
BlueButton,
|
||||
SafeBlueArea,
|
||||
BlueCard,
|
||||
BlueText,
|
||||
BlueHeader,
|
||||
} from '../BlueComponents';
|
||||
import PropTypes from 'prop-types';
|
||||
/** @type {AppStorage} */
|
||||
let BlueApp = require('../BlueApp');
|
||||
|
||||
export default class About extends Component {
|
||||
static navigationOptions = {
|
||||
tabBarLabel: 'About',
|
||||
tabBarIcon: ({ tintColor, focused }) => (
|
||||
<Ionicons
|
||||
name={focused ? 'ios-settings' : 'ios-settings-outline'}
|
||||
size={26}
|
||||
style={{ color: tintColor }}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.isLoading) {
|
||||
return <BlueLoading />;
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
|
||||
<BlueHeader
|
||||
backgroundColor={BlueApp.settings.brandingColor}
|
||||
leftComponent={
|
||||
<Icon
|
||||
name="menu"
|
||||
color="#fff"
|
||||
onPress={() => this.props.navigation.navigate('DrawerToggle')}
|
||||
/>
|
||||
}
|
||||
centerComponent={{
|
||||
text: 'About',
|
||||
style: { color: '#fff', fontSize: 25 },
|
||||
}}
|
||||
/>
|
||||
|
||||
<BlueCard>
|
||||
<ScrollView maxHeight={450}>
|
||||
<BlueText h1>About</BlueText>
|
||||
<BlueSpacing20 />
|
||||
|
||||
<BlueText h4>
|
||||
Blue Wallet is free and opensource Bitcoin wallet
|
||||
</BlueText>
|
||||
<BlueText>
|
||||
Warning: Alpha version, don't use to store large amouts!
|
||||
</BlueText>
|
||||
<BlueButton
|
||||
icon={{ name: 'octoface', type: 'octicon' }}
|
||||
onPress={() => {
|
||||
Linking.openURL('https://github.com/Overtorment/BlueWallet');
|
||||
}}
|
||||
title="github.com/Overtorment/BlueWallet"
|
||||
/>
|
||||
|
||||
<BlueSpacing20 />
|
||||
<BlueText h4>Licensed MIT</BlueText>
|
||||
<BlueSpacing20 />
|
||||
|
||||
<BlueText h3>Built with awesome:</BlueText>
|
||||
<BlueSpacing20 />
|
||||
<BlueText h4>* React Native</BlueText>
|
||||
<BlueText h4>* Bitcoinjs-lib</BlueText>
|
||||
<BlueText h4>* blockcypher.com API</BlueText>
|
||||
<BlueText h4>* Nodejs</BlueText>
|
||||
<BlueText h4>* Expo</BlueText>
|
||||
<BlueText h4>* react-native-elements</BlueText>
|
||||
<BlueText h4>* rn-nodeify</BlueText>
|
||||
<BlueText h4>* bignumber.js</BlueText>
|
||||
<BlueText h4>* https://github.com/StefanoBalocco/isaac.js</BlueText>
|
||||
<BlueText h4>
|
||||
* Design by https://dribbble.com/chrometaphore
|
||||
</BlueText>
|
||||
|
||||
<BlueButton
|
||||
onPress={() => {
|
||||
this.props.navigation.navigate('Selftest');
|
||||
}}
|
||||
title="Run self test"
|
||||
/>
|
||||
<BlueButton
|
||||
icon={{ name: 'arrow-left', type: 'octicon' }}
|
||||
title="Go Back"
|
||||
onPress={() => {
|
||||
this.props.navigation.goBack();
|
||||
}}
|
||||
/>
|
||||
</ScrollView>
|
||||
</BlueCard>
|
||||
</SafeBlueArea>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
About.propTypes = {
|
||||
navigation: PropTypes.shape({
|
||||
navigate: PropTypes.func,
|
||||
goBack: PropTypes.func,
|
||||
}),
|
||||
};
|
|
@ -1,7 +1,8 @@
|
|||
/* global alert */
|
||||
import React, { Component } from 'react';
|
||||
import { ScrollView, Linking } from 'react-native';
|
||||
import { ScrollView, View } from 'react-native';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import { Icon, FormValidationMessage } from 'react-native-elements';
|
||||
import {
|
||||
BlueLoading,
|
||||
BlueSpacing20,
|
||||
|
@ -12,7 +13,9 @@ import {
|
|||
BlueHeader,
|
||||
} from '../BlueComponents';
|
||||
import PropTypes from 'prop-types';
|
||||
/** @type {AppStorage} */
|
||||
let BlueApp = require('../BlueApp');
|
||||
let prompt = require('../prompt');
|
||||
|
||||
export default class Settings extends Component {
|
||||
static navigationOptions = {
|
||||
|
@ -36,6 +39,7 @@ export default class Settings extends Component {
|
|||
async componentDidMount() {
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
storageIsEncrypted: await BlueApp.storageIsEncrypted(),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -63,47 +67,54 @@ export default class Settings extends Component {
|
|||
|
||||
<BlueCard>
|
||||
<ScrollView maxHeight={450}>
|
||||
<BlueText h1>About</BlueText>
|
||||
<BlueSpacing20 />
|
||||
|
||||
<BlueText h4>
|
||||
Blue Wallet is free and opensource Bitcoin wallet
|
||||
</BlueText>
|
||||
<BlueText>
|
||||
Warning: Alpha version, don't use to store large amouts!
|
||||
</BlueText>
|
||||
<BlueButton
|
||||
icon={{ name: 'octoface', type: 'octicon' }}
|
||||
onPress={() => {
|
||||
Linking.openURL('https://github.com/Overtorment/BlueWallet');
|
||||
}}
|
||||
title="github.com/Overtorment/BlueWallet"
|
||||
/>
|
||||
|
||||
<BlueSpacing20 />
|
||||
<BlueText h4>Licensed MIT</BlueText>
|
||||
<BlueSpacing20 />
|
||||
|
||||
<BlueText h3>Built with awesome:</BlueText>
|
||||
<BlueSpacing20 />
|
||||
<BlueText h4>* React Native</BlueText>
|
||||
<BlueText h4>* Bitcoinjs-lib</BlueText>
|
||||
<BlueText h4>* blockcypher.com API</BlueText>
|
||||
<BlueText h4>* Nodejs</BlueText>
|
||||
<BlueText h4>* Expo</BlueText>
|
||||
<BlueText h4>* react-native-elements</BlueText>
|
||||
<BlueText h4>* rn-nodeify</BlueText>
|
||||
<BlueText h4>* bignumber.js</BlueText>
|
||||
<BlueText h4>* https://github.com/StefanoBalocco/isaac.js</BlueText>
|
||||
<BlueText h4>
|
||||
* Design by https://dribbble.com/chrometaphore
|
||||
</BlueText>
|
||||
{(() => {
|
||||
if (this.state.storageIsEncrypted) {
|
||||
return (
|
||||
<View>
|
||||
<BlueText>Storage: encrypted</BlueText>
|
||||
</View>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<View>
|
||||
<FormValidationMessage>
|
||||
Storage: not encrypted
|
||||
</FormValidationMessage>
|
||||
<BlueButton
|
||||
icon={{ name: 'stop', type: 'octicon' }}
|
||||
onPress={async () => {
|
||||
this.setState({ isLoading: true });
|
||||
let p1 = await prompt(
|
||||
'Password',
|
||||
'Create the password you will use to decrypt the storage',
|
||||
);
|
||||
let p2 = await prompt(
|
||||
'Password',
|
||||
'Re-type the password',
|
||||
);
|
||||
if (p1 === p2) {
|
||||
await BlueApp.encryptStorage(p1);
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
storageIsEncrypted: await BlueApp.storageIsEncrypted(),
|
||||
});
|
||||
} else {
|
||||
this.setState({ isLoading: false });
|
||||
alert('Passwords do not match. Please try again');
|
||||
}
|
||||
}}
|
||||
title="Encrypt storage"
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
})()}
|
||||
|
||||
<BlueButton
|
||||
onPress={() => {
|
||||
this.props.navigation.navigate('Selftest');
|
||||
}}
|
||||
title="Run self test"
|
||||
onPress={() => this.props.navigation.navigate('About')}
|
||||
title="About"
|
||||
/>
|
||||
</ScrollView>
|
||||
</BlueCard>
|
||||
|
|
|
@ -40,7 +40,6 @@ export default class WalletsList extends Component {
|
|||
}
|
||||
|
||||
async componentDidMount() {
|
||||
console.log('wallets/list - componentDidMount');
|
||||
this.refreshFunction();
|
||||
} // end of componendDidMount
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue