Использование секретного ключа с sqlcipher

Я использую sqlcipher для хранения данных из своего приложения, и у меня возникают проблемы, во-первых, с созданием секретного ключа и, во-вторых, с сохранением в хранилище ключей.

Кстати, должно быть без взаимодействия с пользователем, как описано в документах Android

Вот как я пытаюсь сгенерировать секрет,

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey key = keyGen.generateKey();

Здесь я настраиваю базу данных sqldatabase.

SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(databaseFile, "password_string", null);

Итак, вопрос, как мне использовать секрет в строке пароля? На данный момент я могу получить секрет только в виде массива байтов.


person Kaigo    schedule 28.03.2018    source источник


Ответы (2)


Ниже приведены утилиты для использования AES для шифрования/дешифрования. Вы можете использовать секретный ключ для шифрования/дешифрования вашего пароля. Тем не менее, я не буду рекомендовать это, так как вам также нужно хранить свой секретный ключ, и проблема все еще существует, как вы можете безопасно сохранить свой секретный ключ? В этом случае обычной практикой является использование хэш-функции: SHA-256, MD5... для хэширования вашего пароля и его сохранения. Позже, когда вы захотите проверить, вводят ли пользователи правильный пароль, просто хешируйте все, что они вводят, и сравните со значением, которое вы сохранили.

private static int BLOCKS = 128;

  public static byte[] encryptAES(String seed, String cleartext)
      throws Exception {
    byte[] rawKey = getRawKey(seed.getBytes("UTF8"));
    SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    return cipher.doFinal(cleartext.getBytes("UTF8"));
  }

  public static byte[] decryptAES(String seed, byte[] data) throws Exception {
    byte[] rawKey = getRawKey(seed.getBytes("UTF8"));
    SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    return cipher.doFinal(data);
  }

  private static byte[] getRawKey(byte[] seed) throws Exception {
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    sr.setSeed(seed);
    kgen.init(BLOCKS, sr); // 192 and 256 bits may not be available
    SecretKey skey = kgen.generateKey();
    byte[] raw = skey.getEncoded();
    return raw;
  }
person Victor Cao    schedule 28.03.2018
comment
Забыл упомянуть, я храню в хранилище ключей. Таким образом, я могу использовать byte[] raw = skey.getEncoded();, чтобы получить необработанный секрет и передать его в sqlcipher. Спасибо - person Kaigo; 28.03.2018

Это мой способ генерировать случайный и квазибезопасный пароль:

fun generatePassword(): String{
     val androidId = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)

     val passPassphraseBase = "${BuildConfig.APPLICATION_ID}_$androidId:"

     val random = SecureRandom()
     val salt = ByteArray(32)
     random.nextBytes(salt)

     val passPhrase = passPassphraseBase.toByteArray() + salt

     val pass = Base64.encodeToString(passPhrase, Base64.NO_WRAP)

     return pass
} 

Вы можете спросить, зачем мне нужен Application ID и Android ID. Просто чтобы увеличить энтропию (и, возможно, длину) нашего пароля.

Затем я храню этот пароль в зашифрованном виде в общих настройках. Я шифрую все общие ключи и значения настроек с помощью алгоритма RSA хранилища ключей.

В конце концов, мы получаем сгенерированный пароль с симметричным шифрованием, зашифрованный с помощью асимметричного алгоритма.

Все это просто криптография белого ящика, в которой наш ключ и зашифрованные данные хранятся в одном месте.

Мы можем повысить безопасность, если добавим какой-то внешний источник хотя бы для части нашего пароля. Для этого мы можем использовать:

  • что-то из нашего бэкэнда
  • пользовательский ввод или биометрический
person Artur Latoszewski    schedule 27.05.2020