Android improvements.
[UPDATED] Opal API [ADDED] Scrypt native binaries for more archs. [IMPROVED] Android activity secure. [FIXED] White background on buttons for some devices. [IMPROVED] Android layout. [WIP] Remember password on Android.
This commit is contained in:
parent
ca5d83d40c
commit
a6e7a749bf
@ -24,12 +24,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.lyndir.lhunath.opal</groupId>
|
<groupId>com.lyndir.lhunath.opal</groupId>
|
||||||
<artifactId>opal-system</artifactId>
|
<artifactId>opal-system</artifactId>
|
||||||
<version>1.6-p6</version>
|
<version>1.6-p7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.lyndir.lhunath.opal</groupId>
|
<groupId>com.lyndir.lhunath.opal</groupId>
|
||||||
<artifactId>opal-crypto</artifactId>
|
<artifactId>opal-crypto</artifactId>
|
||||||
<version>1.6-p6</version>
|
<version>1.6-p7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- EXTERNAL DEPENDENCIES -->
|
<!-- EXTERNAL DEPENDENCIES -->
|
||||||
|
@ -77,15 +77,6 @@ public class MasterKey {
|
|||||||
return idForBytes( masterKey );
|
return idForBytes( masterKey );
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getSubKey(final int subkeyLength) {
|
|
||||||
|
|
||||||
Preconditions.checkState( valid );
|
|
||||||
byte[] subkey = new byte[Math.min( subkeyLength, masterKey.length )];
|
|
||||||
System.arraycopy( masterKey, 0, subkey, 0, subkey.length );
|
|
||||||
|
|
||||||
return subkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String encode(final String siteName, final MPSiteType siteType, int siteCounter, final MPSiteVariant siteVariant,
|
public String encode(final String siteName, final MPSiteType siteType, int siteCounter, final MPSiteVariant siteVariant,
|
||||||
@Nullable final String siteContext) {
|
@Nullable final String siteContext) {
|
||||||
Preconditions.checkState( valid );
|
Preconditions.checkState( valid );
|
||||||
|
@ -114,11 +114,10 @@
|
|||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.lambdaworks</groupId>
|
<groupId>com.lambdaworks</groupId>
|
||||||
<artifactId>libscrypt</artifactId>
|
<artifactId>scrypt</artifactId>
|
||||||
<version>1.4.0</version>
|
<version>1.4.0-android</version>
|
||||||
<type>so</type>
|
<type>jar</type>
|
||||||
<classifier>android</classifier>
|
<classifier>native</classifier>
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -12,64 +12,61 @@
|
|||||||
android:gravity="center">
|
android:gravity="center">
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="0dp"
|
android:layout_width="1dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1" />
|
android:layout_weight="1" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progressView"
|
android:id="@+id/progressView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="300dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="20dp"
|
||||||
android:indeterminate="true" />
|
android:indeterminate="true" />
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/userNameField"
|
android:id="@+id/userNameField"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="300dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="text|textCapWords|textPersonName"
|
android:inputType="text|textCapWords|textPersonName"
|
||||||
android:hint="@string/userName.hint"
|
android:hint="@string/userName_hint"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textColor="#FFFFFF"
|
android:textColor="#FFFFFF"
|
||||||
android:textSize="26sp" />
|
android:textSize="26sp" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/masterPasswordField"
|
android:id="@+id/masterPasswordField"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="300dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="text|textPassword"
|
android:inputType="text|textPassword"
|
||||||
android:hint="@string/masterPassword.hint"
|
android:hint="@string/masterPassword_hint"
|
||||||
android:password="true"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textColor="#FFFFFF"
|
android:textColor="#FFFFFF"
|
||||||
android:textSize="18sp" />
|
android:textSize="18sp" />
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:src="@drawable/double_"
|
|
||||||
android:contentDescription="@string/empty" />
|
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/siteNameField"
|
android:id="@+id/siteNameField"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="300dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="text|textNoSuggestions|textUri"
|
android:inputType="text|textNoSuggestions|textUri"
|
||||||
android:hint="@string/siteName.hint"
|
android:hint="@string/siteName_hint"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textColor="#FFFFFF"
|
android:textColor="#FFFFFF"
|
||||||
android:textSize="26sp" />
|
android:textSize="26sp" />
|
||||||
|
|
||||||
<Button
|
<ImageView
|
||||||
|
android:layout_width="300dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginBottom="30dp"
|
||||||
|
android:src="@drawable/double_"
|
||||||
|
android:contentDescription="@string/empty" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
android:id="@+id/sitePasswordField"
|
android:id="@+id/sitePasswordField"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="300dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:background="@null"
|
android:background="@android:color/transparent"
|
||||||
android:textColor="#FFFFFF"
|
android:textColor="#FFFFFF"
|
||||||
android:textSize="32sp"
|
android:textSize="32sp"
|
||||||
android:text="LuxdZozvDuma4["
|
android:text="LuxdZozvDuma4["
|
||||||
@ -77,13 +74,30 @@
|
|||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:id="@+id/typeField"
|
android:id="@+id/typeField"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="300dp"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center" />
|
||||||
|
|
||||||
<NumberPicker
|
<EditText
|
||||||
android:id="@+id/counterField"
|
android:id="@+id/counterField"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="300dp"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:inputType="text|textNoSuggestions"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="26sp"
|
||||||
|
android:text="1" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/rememberPasswordField"
|
||||||
|
android:layout_width="300dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/remember" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -2,8 +2,9 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Master Password</string>
|
<string name="app_name">Master Password</string>
|
||||||
<string name="avatar">User Avatar</string>
|
<string name="avatar">User Avatar</string>
|
||||||
<string name="siteName.hint">Site Name</string>
|
<string name="remember">Remember Password</string>
|
||||||
<string name="userName.hint">Your Name</string>
|
<string name="siteName_hint">Site Name</string>
|
||||||
<string name="masterPassword.hint">Your Master Password</string>
|
<string name="userName_hint">Your Name</string>
|
||||||
|
<string name="masterPassword_hint">Your Master Password</string>
|
||||||
<string name="empty" />
|
<string name="empty" />
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -9,12 +9,14 @@ import android.os.Bundle;
|
|||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.WindowManager;
|
||||||
import android.widget.*;
|
import android.widget.*;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import butterknife.InjectView;
|
import butterknife.InjectView;
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.util.concurrent.*;
|
import com.google.common.util.concurrent.*;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
|
import com.lyndir.lhunath.opal.system.util.ConversionUtils;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
|
||||||
@ -55,11 +57,14 @@ public class EmergencyActivity extends Activity {
|
|||||||
Spinner typeField;
|
Spinner typeField;
|
||||||
|
|
||||||
@InjectView(R.id.counterField)
|
@InjectView(R.id.counterField)
|
||||||
NumberPicker counterField;
|
EditText counterField;
|
||||||
|
|
||||||
@InjectView(R.id.sitePasswordField)
|
@InjectView(R.id.sitePasswordField)
|
||||||
TextView sitePasswordField;
|
TextView sitePasswordField;
|
||||||
|
|
||||||
|
@InjectView(R.id.rememberPasswordField)
|
||||||
|
CheckBox rememberPasswordField;
|
||||||
|
|
||||||
private int hc_userName;
|
private int hc_userName;
|
||||||
private int hc_masterPassword;
|
private int hc_masterPassword;
|
||||||
|
|
||||||
@ -68,6 +73,7 @@ public class EmergencyActivity extends Activity {
|
|||||||
super.onCreate( savedInstanceState );
|
super.onCreate( savedInstanceState );
|
||||||
Res.init( getResources() );
|
Res.init( getResources() );
|
||||||
|
|
||||||
|
getWindow().setFlags( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE );
|
||||||
setContentView( R.layout.activity_emergency );
|
setContentView( R.layout.activity_emergency );
|
||||||
ButterKnife.inject( this );
|
ButterKnife.inject( this );
|
||||||
|
|
||||||
@ -75,23 +81,26 @@ public class EmergencyActivity extends Activity {
|
|||||||
masterPasswordField.setOnFocusChangeListener( updateMasterKey );
|
masterPasswordField.setOnFocusChangeListener( updateMasterKey );
|
||||||
siteNameField.addTextChangedListener( updateSitePassword );
|
siteNameField.addTextChangedListener( updateSitePassword );
|
||||||
typeField.setOnItemSelectedListener( updateSitePassword );
|
typeField.setOnItemSelectedListener( updateSitePassword );
|
||||||
counterField.setOnValueChangedListener( updateSitePassword );
|
counterField.addTextChangedListener( updateSitePassword );
|
||||||
|
|
||||||
userNameField.setTypeface( Res.exo_Thin );
|
userNameField.setTypeface( Res.exo_Thin );
|
||||||
userNameField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
userNameField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||||
masterPasswordField.setTypeface( Res.sourceCodePro_ExtraLight );
|
masterPasswordField.setTypeface( Res.sourceCodePro_ExtraLight );
|
||||||
masterPasswordField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
masterPasswordField.setPaintFlags( masterPasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||||
siteNameField.setTypeface( Res.exo_Regular );
|
siteNameField.setTypeface( Res.exo_Regular );
|
||||||
siteNameField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
siteNameField.setPaintFlags( siteNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||||
sitePasswordField.setTypeface( Res.sourceCodePro_Black );
|
sitePasswordField.setTypeface( Res.sourceCodePro_Black );
|
||||||
sitePasswordField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
sitePasswordField.setPaintFlags( sitePasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||||
|
|
||||||
typeField.setAdapter( new ArrayAdapter<>( this, R.layout.type_item, MPSiteType.forClass( MPSiteTypeClass.Generated ) ) );
|
typeField.setAdapter( new ArrayAdapter<>( this, R.layout.type_item, MPSiteType.forClass( MPSiteTypeClass.Generated ) ) );
|
||||||
typeField.setSelection( MPSiteType.GeneratedLong.ordinal() );
|
typeField.setSelection( MPSiteType.GeneratedLong.ordinal() );
|
||||||
|
|
||||||
counterField.setMinValue( 1 );
|
rememberPasswordField.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() {
|
||||||
counterField.setMaxValue( Integer.MAX_VALUE );
|
@Override
|
||||||
counterField.setWrapSelectorWheel( false );
|
public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
|
||||||
|
getPreferences( MODE_PRIVATE ).edit().putBoolean( "rememberPassword", isChecked ).apply();
|
||||||
|
}
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -99,25 +108,32 @@ public class EmergencyActivity extends Activity {
|
|||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
userNameField.setText( getPreferences( MODE_PRIVATE ).getString( "userName", "" ) );
|
userNameField.setText( getPreferences( MODE_PRIVATE ).getString( "userName", "" ) );
|
||||||
|
rememberPasswordField.setSelected( isRememberPasswordEnabled() );
|
||||||
masterPasswordField.requestFocus();
|
masterPasswordField.requestFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
|
if (!isRememberPasswordEnabled()) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
hc_userName = hc_masterPassword = 0;
|
hc_userName = hc_masterPassword = 0;
|
||||||
if (masterKeyFuture != null) {
|
if (masterKeyFuture != null) {
|
||||||
masterKeyFuture.cancel( true );
|
masterKeyFuture.cancel( true );
|
||||||
masterKeyFuture = null;
|
masterKeyFuture = null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sitePasswordField.setText( "" );
|
sitePasswordField.setText( "" );
|
||||||
progressView.setVisibility( View.INVISIBLE );
|
progressView.setVisibility( View.INVISIBLE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isRememberPasswordEnabled() {
|
||||||
|
return getPreferences( MODE_PRIVATE ).getBoolean( "rememberPassword", false );
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void updateMasterKey() {
|
private synchronized void updateMasterKey() {
|
||||||
final String userName = userNameField.getText().toString();
|
final String userName = userNameField.getText().toString();
|
||||||
final String masterPassword = masterPasswordField.getText().toString();
|
final String masterPassword = masterPasswordField.getText().toString();
|
||||||
@ -126,9 +142,7 @@ public class EmergencyActivity extends Activity {
|
|||||||
hc_userName = userName.hashCode();
|
hc_userName = userName.hashCode();
|
||||||
hc_masterPassword = masterPassword.hashCode();
|
hc_masterPassword = masterPassword.hashCode();
|
||||||
|
|
||||||
SharedPreferences.Editor pref = getPreferences( MODE_PRIVATE ).edit();
|
getPreferences( MODE_PRIVATE ).edit().putString( "userName", userName ).apply();
|
||||||
pref.putString( "userName", userName );
|
|
||||||
pref.apply();
|
|
||||||
|
|
||||||
if (masterKeyFuture != null)
|
if (masterKeyFuture != null)
|
||||||
masterKeyFuture.cancel( true );
|
masterKeyFuture.cancel( true );
|
||||||
@ -170,7 +184,7 @@ public class EmergencyActivity extends Activity {
|
|||||||
private void updateSitePassword() {
|
private void updateSitePassword() {
|
||||||
final String siteName = siteNameField.getText().toString();
|
final String siteName = siteNameField.getText().toString();
|
||||||
final MPSiteType type = (MPSiteType) typeField.getSelectedItem();
|
final MPSiteType type = (MPSiteType) typeField.getSelectedItem();
|
||||||
final int counter = counterField.getValue();
|
final int counter = ConversionUtils.toIntegerNN( counterField.getText() );
|
||||||
|
|
||||||
if (masterKeyFuture == null || siteName.isEmpty() || type == null) {
|
if (masterKeyFuture == null || siteName.isEmpty() || type == null) {
|
||||||
sitePasswordField.setText( "" );
|
sitePasswordField.setText( "" );
|
||||||
@ -220,13 +234,13 @@ public class EmergencyActivity extends Activity {
|
|||||||
|
|
||||||
ClipDescription description = new ClipDescription( strf( "Password for %s", siteNameField.getText() ),
|
ClipDescription description = new ClipDescription( strf( "Password for %s", siteNameField.getText() ),
|
||||||
new String[]{ ClipDescription.MIMETYPE_TEXT_PLAIN } );
|
new String[]{ ClipDescription.MIMETYPE_TEXT_PLAIN } );
|
||||||
((ClipboardManager) getSystemService( CLIPBOARD_SERVICE )).setPrimaryClip(
|
ClipData clipData = new ClipData( description, new ClipData.Item( sitePassword ) );
|
||||||
new ClipData( description, new ClipData.Item( sitePassword ) ) );
|
((ClipboardManager) getSystemService( CLIPBOARD_SERVICE )).setPrimaryClip( clipData );
|
||||||
|
|
||||||
Intent startMain = new Intent(Intent.ACTION_MAIN);
|
Intent startMain = new Intent( Intent.ACTION_MAIN );
|
||||||
startMain.addCategory(Intent.CATEGORY_HOME);
|
startMain.addCategory( Intent.CATEGORY_HOME );
|
||||||
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
startMain.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
|
||||||
startActivity(startMain);
|
startActivity( startMain );
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class ValueChangedListener
|
private abstract class ValueChangedListener
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.lyndir.lhunath</groupId>
|
<groupId>com.lyndir.lhunath</groupId>
|
||||||
<artifactId>lyndir</artifactId>
|
<artifactId>lyndir</artifactId>
|
||||||
<version>1.18</version>
|
<version>1.20</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<name>Master Password</name>
|
<name>Master Password</name>
|
||||||
|
Loading…
Reference in New Issue
Block a user