Как зашифровать данные перед отправкой в ​​базу данных Firebase? - PullRequest
0 голосов
/ 10 октября 2018

Я создаю чат-приложение, используя базу данных 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 ]

0 голосов
/ 10 октября 2018

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

0 голосов
/ 11 октября 2018

Цезарь-шифр на самом деле не является ни «шифром», ни шифрованием в любом использовании этого слова.На самом деле это набор из 25 различных кодировок.Кодировка по определению не является шифрованием и не является безопасной.Если вы ищете решение для использования в производстве, Цезарь Шифр ​​определенно не так.Взломать тривиально и не обеспечивает никакой безопасности.

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

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

Вот некоторый 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);
}

}

0 голосов
/ 10 октября 2018

Вы можете использовать шифрование Цезаря, но для расшифровки сообщения на стороне получателя вы также должны сохранить 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);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...