Browse Source

storage encryption

localNotifications
Overtorment 7 years ago
parent
commit
809f9cae60
  1. 9
      App.js
  2. 11
      BlueApp.js
  3. 8
      class/app-storage.js
  4. 8
      prompt.js
  5. 128
      screen/about.js
  6. 89
      screen/settings.js
  7. 1
      screen/wallets/list.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

@ -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;

8
class/app-storage.js

@ -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));

8
prompt.js

@ -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

@ -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,
}),
};

89
screen/settings.js

@ -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>

1
screen/wallets/list.js

@ -40,7 +40,6 @@ export default class WalletsList extends Component {
}
async componentDidMount() {
console.log('wallets/list - componentDidMount');
this.refreshFunction();
} // end of componendDidMount

Loading…
Cancel
Save