Как зашифровать данные перед отправкой в ​​базу данных Firebase?

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

Я хочу остановить это, и для этого мне понадобится метод дешифрования и шифрования. Я попытался использовать шифрование Цезаря, но не смог выполнить этот процесс.

String encrypt(String talk, int key){ for(int i=0;i<talk.length;i++) //can't think of how to procceed from here 

Я хочу знать, есть ли способ реализовать шифрование Цезаря здесь, а если нет, то какое другое шифрование следует использовать?

Всего 3 ответа


Вы можете использовать шифрование Цезаря, но чтобы расшифровать сообщение на стороне получателя, вы также должны сохранить key в Firebase.

Но вы можете сделать это непонятным для себя, используя rand() для получения key и перед его хранением, выполните любую математическую операцию на нем, это также случайное.

Это выглядит тяжело, но это не так. Код шифрования и дешифрования Цезаря выглядит примерно так:

 private String encryptMessage(String talk, int k){ // make the string encrypted before sending to the database k = k % 26 + 26; StringBuilder encoded = new StringBuilder(); for (char i : talk.toCharArray()) { if (Character.isLetter(i)) { if (Character.isUpperCase(i)) { encoded.append((char) ('A' + (i - 'A' + k) % 26 )); } else { encoded.append((char) ('a' + (i - 'a' + k) % 26 )); } } else { encoded.append(i); } } return encoded.toString(); } private String decryptMessage(String m, int key){ // make string readable on the receiver's device return encryptMessage(m,26-key); } 

Вы можете сгенерировать на клиенте некоторый ключ шифрования, например, на основе учетных данных пользователя, и надежно хранить его там (например, в KeyStore или используя другие подходы в зависимости от вашей минимальной версии SDK). Затем, используя ключ шифрования и AES (или любой другой стандарт), шифруйте / дешифруйте сообщения при отправке / приеме.


Caesar Cipher на самом деле не является «шифром» и не шифрует при любом использовании слова. На самом деле это набор из 25 разных кодировок. Кодировка по определению не является шифрованием и не является безопасной. Если вы ищете решение для использования в производстве, Caesar Cipher определенно не тот. Тривиально разорвать и не обеспечивает никакой безопасности.

То, что вы должны сделать, - это четко определить модель угрозы и атаки, от которой вы защищаете себя. Отсюда вы должны проконсультироваться с тем, у кого есть реальный опыт криптографии, для разработки решения проблем, которые вы обнаружили.

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

Вот какой код Java, из моего собственного репозитория здесь , который демонстрирует безопасный способ шифрования и дешифрования строк с заданным паролем:

public class SecureCompatibleEncryptionExamples {

private final static String ALGORITHM_NAME = "AES/GCM/NoPadding";
private final static int ALGORITHM_NONCE_SIZE = 12;
private final static int ALGORITHM_TAG_SIZE = 128;
private final static int ALGORITHM_KEY_SIZE = 128;
private final static String PBKDF2_NAME = "PBKDF2WithHmacSHA256";
private final static int PBKDF2_SALT_SIZE = 16;
private final static int PBKDF2_ITERATIONS = 32767;

public static String encryptString(String plaintext, String password) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
    // Generate a 128-bit salt using a CSPRNG.
    SecureRandom rand = new SecureRandom();
    byte[] salt = new byte[PBKDF2_SALT_SIZE];
    rand.nextBytes(salt);

    // Create an instance of PBKDF2 and derive a key.
    PBEKeySpec pwSpec = new PBEKeySpec(password.toCharArray(), salt, PBKDF2_ITERATIONS, ALGORITHM_KEY_SIZE);
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(PBKDF2_NAME);
    byte[] key = keyFactory.generateSecret(pwSpec).getEncoded();

    // Encrypt and prepend salt.
    byte[] ciphertextAndNonce = encrypt(plaintext.getBytes(StandardCharsets.UTF_8), key);
    byte[] ciphertextAndNonceAndSalt = new byte[salt.length + ciphertextAndNonce.length];
    System.arraycopy(salt, 0, ciphertextAndNonceAndSalt, 0, salt.length);
    System.arraycopy(ciphertextAndNonce, 0, ciphertextAndNonceAndSalt, salt.length, ciphertextAndNonce.length);

    // Return as base64 string.
    return Base64.getEncoder().encodeToString(ciphertextAndNonceAndSalt);
}

public static String decryptString(String base64CiphertextAndNonceAndSalt, String password) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException {
    // Decode the base64.
    byte[] ciphertextAndNonceAndSalt = Base64.getDecoder().decode(base64CiphertextAndNonceAndSalt);

    // Retrieve the salt and ciphertextAndNonce.
    byte[] salt = new byte[PBKDF2_SALT_SIZE];
    byte[] ciphertextAndNonce = new byte[ciphertextAndNonceAndSalt.length - PBKDF2_SALT_SIZE];
    System.arraycopy(ciphertextAndNonceAndSalt, 0, salt, 0, salt.length);
    System.arraycopy(ciphertextAndNonceAndSalt, salt.length, ciphertextAndNonce, 0, ciphertextAndNonce.length);

    // Create an instance of PBKDF2 and derive the key.
    PBEKeySpec pwSpec = new PBEKeySpec(password.toCharArray(), salt, PBKDF2_ITERATIONS, ALGORITHM_KEY_SIZE);
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(PBKDF2_NAME);
    byte[] key = keyFactory.generateSecret(pwSpec).getEncoded();

    // Decrypt and return result.
    return new String(decrypt(ciphertextAndNonce, key), StandardCharsets.UTF_8);
}

public static byte[] encrypt(byte[] plaintext, byte[] key) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
    // Generate a 96-bit nonce using a CSPRNG.
    SecureRandom rand = new SecureRandom();
    byte[] nonce = new byte[ALGORITHM_NONCE_SIZE];
    rand.nextBytes(nonce);

    // Create the cipher instance and initialize.
    Cipher cipher = Cipher.getInstance(ALGORITHM_NAME);
    cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(ALGORITHM_TAG_SIZE, nonce));

    // Encrypt and prepend nonce.
    byte[] ciphertext = cipher.doFinal(plaintext);
    byte[] ciphertextAndNonce = new byte[nonce.length + ciphertext.length];
    System.arraycopy(nonce, 0, ciphertextAndNonce, 0, nonce.length);
    System.arraycopy(ciphertext, 0, ciphertextAndNonce, nonce.length, ciphertext.length);

    return ciphertextAndNonce;
}

public static byte[] decrypt(byte[] ciphertextAndNonce, byte[] key) throws InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
    // Retrieve the nonce and ciphertext.
    byte[] nonce = new byte[ALGORITHM_NONCE_SIZE];
    byte[] ciphertext = new byte[ciphertextAndNonce.length - ALGORITHM_NONCE_SIZE];
    System.arraycopy(ciphertextAndNonce, 0, nonce, 0, nonce.length);
    System.arraycopy(ciphertextAndNonce, nonce.length, ciphertext, 0, ciphertext.length);

    // Create the cipher instance and initialize.
    Cipher cipher = Cipher.getInstance(ALGORITHM_NAME);
    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(ALGORITHM_TAG_SIZE, nonce));

    // Decrypt and return result.
    return cipher.doFinal(ciphertext);
}

}


Есть идеи?

10000