2017-02-20 8 views
0

私のアプリケーションでは、暗号化メディアの暗号化キーとしてユーザーパスワードを使用します。私はPBEWithMD5AndDESを使ってメディアを暗号化していますが、これは共有環境設定に保存されたパスワードでうまく動作します。今度はセキュリティのレベルを達成するために、私は共有環境設定からパスワードを削除しています。アプリケーションセッション中にのみ保持されるシングルトンを使用しています(アプリケーションが自動的にパスワードの入力を要求するのでログアウトします)。以下は私のシングルトンです:アプリがログアウトし、ユーザがログアウトされたり破壊されてしまった場合シングルトンインスタンスがnullを返す

public class Credentials { 

private static Credentials dataObject = null; 

private Credentials() { 
// left blank intentionally 
} 

public static Credentials getInstance() { 
if (dataObject == null) 
    dataObject = new Credentials(); 
return dataObject; 
} 

private char[] user_password; 

public char[] getUser_password() { 

return user_password; 
} 

public void setUser_password(char[] user_password) { 

this.user_password = user_password; 
} 
} 

パスワードがメモリからゼロにされます。しかし、時々私はパスワードを取得しようとするとnullポインタを取得しています。

char[] pswd = Credentials.getInstance().getUser_password(); 

この原因は何ですか?シングルトンを除いて使用できる他の方法はありますか?

+1

'Credentials.getInstance()'は 'null'を返すことができません。そのインスタンスで 'setUser_password'を呼び出すことはなかったので、' Credentials.getInstance()。getUser_password() 'が行います。そして、あなたが 'setUser_password'(非ヌルパラメータで)を呼び出したと思えば、シングルトンクラスはスレッドセーフではないという問題があります。 –

+0

@James Wahome:あなたの 'password'はシングルトンではありません!! – AndiGeeky

+0

シングルトンインスタンスのヌルオブジェクトとその関数による戻り値の適切なチェックを追加します。 –

答えて

-1

また、組み込みのSqliteデータベースを使用してパスワードを保存することもできますが、最大限の保護のために暗号化して保存することをお勧めします。 )

2パスワードを保存するために、エンティティオブジェクトを作成します:あなたは4つの段階でこれを行うことができます

public class Password { 
    int password_id; // will be auto-increamted 
    String password; 

    public Password(int password_id, String password) { 
     this.password_id = password_id; 
     this.password = password; 
    } 
// getter/setters ... 
} 

2)Sqliteをユーティリティー・オブジェクトを作成します。

public class SQLiteDBAdapter { 

    protected static final String DATABASE_NAME = "mydb"; 
    protected static final int DATABASE_VERSION = 1; 

    protected Context context; 
    protected static DatabaseHelper mDbHelper; 

    public static final String TABLE_PASSWORD = "tbl_password"; 
    // columns 
    public static final String PASSWORD_ID = "_id"; 
    public static final String PASSWORD = "password"; 
    // create table string 
    private static final String CREATE_TABLE_PASSWORD = 
      "CREATE TABLE if not exists " + TABLE_PASSWORD + " (" + 
        PASSWORD_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + 
        PASSWORD + " TEXT NOT NULL);"; 

    public SQLiteDBAdapter(Context context) { 
     context = context.getApplicationContext(); 
    } 

    public SQLiteDatabase openDb() { 
     if (mDbHelper == null) { 
      mDbHelper = new DatabaseHelper(mContext); 
     } 
     return mDbHelper.getWritableDatabase(); 
    } 

    protected static class DatabaseHelper extends SQLiteOpenHelper { 
     // ------------------------------------------------------------------------------------------- 
     public DatabaseHelper(Context context) { 
      super(context, DATABASE_NAME, null, DATABASE_VERSION); 
     } 
     // ------------------------------------------------------------------------------------------- 
     @Override 
     public void onCreate(SQLiteDatabase db) { 
      db.execSQL(CREATE_TABLE_PASSWORD); 
     } 
     // ------------------------------------------------------------------------------------------- 
     @Override 
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
      Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + 
        newVersion + ", which will destroy all old data"); 
      db.execSQL("DROP TABLE IF EXISTS routes"); 
      onCreate(db); 
     } 
    } 
} 

3)SQLiteにも拡張しますテーブルを操作するオブジェクト(CRUD操作):

public class PasswordDbAdapter extends SQLiteDBAdapter { 

    private SQLiteDatabase db; 

    // these are column corresponding indices 
    public static final int INDEX_PASSWORD_ID = 0; // an auto-increment 
    public static final int INDEX_PASSWORD = 1; 

    public PasswordDbAdapter(Context context) { 
     super(context); 
    } 

    public void addPassword(String password) { 
     db = openDb(); 
     ContentValues values = new ContentValues(); 
     values.put(PASSWORD, password); 
     db.insert(TABLE_PASSWORD, null, values); 
    } 

    public void updatePassword(String password) { 
     db = openDb(); 
     ContentValues values = new ContentValues(); 
     values.put(PASSWORD, password); 
     db.update(TABLE_PASSWORD, values, null); 
    } 

    public void deletePassword() { 
     db = openDb(); 
     db.delete(TABLE_PASSWORD, null, null); 
    } 

    public boolean isEmpty() { 
     db = openDb(); 
     boolean empty = true; 
     Cursor cur = db.rawQuery("SELECT COUNT(*) FROM " + TABLE_PASSWORD, null); 
     if (cur != null && cur.moveToFirst()) { 
      empty = (cur.getInt (0) == 0); 
     } 
     cur.close(); 
     return empty; 
    } 

    public Password fetchPassword() { // ok because there's only one password record 
     db = openDb(); 
     Cursor cursor = db.query(TABLE_PASSWORD, new String[]{PASSWORD_ID, PASSWORD}, 
       null, null, null, null, null, null); 
     if (cursor != null && 
      cursor.moveToFirst()) { 
      return new Password(
        cursor.getString(INDEX_PASSWORD_ID), 
        cursor.getInt(INDEX_PASSWORD)); 
     } 
     return null; 
    } 
} 

4)最後に、passworを保存/更新/取得しますdは必要に応じて:

public class MainActivity extends AppCompatActivity { 
    private PasswordDbAdapter passwordDB; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     ... 
     // initialize the password db 
     passwordDB = new PasswordDbAdapter(this); 

     // check if password record exists 
     if (passwordDB.isEmpty() { 
      // save a new copy 
      passwordDB.addPassword("the_password"); // more secure if it is saved encrypted 
     } else { 
      // update it 
      passwordDB.updatePassword("the_password"); 
     } 

    } 
    ... 
    public String fetchPassword() { 
     return passwordDB.fetchPassword(); // or first decrypt it, then return it 
    } 
} 
+0

これは間違っています....「セキュリティのレベルを達成するために、共有された設定からパスワードを削除して、アプリケーションセッション中に生きているだけのシングルトンを使用しています」という質問を読んでください。私の目的は、ディスク・ストレージの共有設定には保持されません。いずれにしても、プレーンテキストにパスワードを保存しないでください。 –

+0

Androidシングルトンは非常に問題があります。しかし、http://stackoverflow.com/questions/16517702/singleton-in-androidを参照してください。さて、Sqliteの使用については、パスワードを暗号化して保存することをお勧めします。簡単ですが、パスワードをハッシュして、代わりにハッシュを使用することもできます。 – nkmuturi