Add encryption in firebase group chat
Brief summary of this post:
1. The user enters a passphrase which is unique to the group chat and has to be shared to the user for granting him access.
2. The passphrase is saved in SharedPreferences.
3. A master key is generated using the passphrase.
4. While sending message, a secret key is generated using the master key and message ID. The message is encrypted using this secret key.
5. On retrieving message, it is decrypted using a secret key generated using master key and message ID.
Steps:
1. In Button to enter the group chat page, add a dialog box (dialog2) with EditText (dialog_text1) where user can enter the passphrase. On entering the passphrase it is saved in SharedPreferences (sp:sp) and user moves to group chat activity using intent component.
Code to add an EditText to Dialog component:
final EditText dialog_text1 = new EditText(AdminpageActivity.this);
dialog_text1.setLayoutParams(linear2.getLayoutParams());
dialog2.setView(dialog_text1);
Code to get text from EditText:
dialog_text1.getText().toString()
2. Add another button which can be used to reenter passphrase, in case user has entered the wrong passphrase.
3. In local library manager, add the following library and select it:
androidx.security:security-crypto:1.1.0-alpha06
4. In Java/Kotlin manager, add a new Java class file EncryptionHelper.java and put following codes in it. Make sure to keep your own package name at the top.
package com.my.dmchat;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.util.Base64;
import java.util.Arrays;
import android.content.SharedPreferences;
import android.content.Context;
import androidx.security.crypto.MasterKey;
import androidx.security.crypto.EncryptedFile;
import androidx.security.crypto.EncryptedSharedPreferences;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.KeyStore;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.Mac;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.spec.KeySpec;
import javax.crypto.spec.SecretKeySpec;
public class EncryptionHelper {
/**
* Derives a Master Key from a given passphrase using PBKDF2.
* @param passphrase The user's passphrase.
* @return SecretKey The derived master key.
* @throws Exception if key derivation fails.
*/
public static SecretKey deriveMasterKey(String passphrase) throws Exception {
byte[] salt = "SomeFixedSaltValue".getBytes(StandardCharsets.UTF_8); // Can be static or unique per chat
int iterations = 100000;
int keyLength = 256;
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), salt, iterations, keyLength);
SecretKey tmpKey = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
return tmpKey;
}
/**
* Derives a unique chat-specific encryption key from the master key using HMAC.
* @param masterKey The master key.
* @param chatID The chat identifier.
* @return SecretKey The derived chat key.
* @throws Exception if key derivation fails.
*/
public static SecretKey deriveChatKey(SecretKey masterKey, String chatID) throws Exception {
Mac hmac = Mac.getInstance("HmacSHA256");
hmac.init(masterKey);
byte[] secretKeyBytes = hmac.doFinal(chatID.getBytes(StandardCharsets.UTF_8));
return new SecretKeySpec(Arrays.copyOf(secretKeyBytes, 16), "AES"); // 128-bit AES key
}
/**
* Encrypts a message using AES-GCM encryption.
* @param chatKey The AES key used for encryption.
* @param plaintext The message to be encrypted.
* @return Encrypted message as a Base64 string.
* @throws Exception if encryption fails.
*/
public static String encryptMessage(SecretKey chatKey, String plaintext) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, chatKey);
byte[] iv = cipher.getIV();
byte[] encryptedData = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
byte[] combined = new byte[iv.length + encryptedData.length];
System.arraycopy(iv, 0, combined, 0, iv.length);
System.arraycopy(encryptedData, 0, combined, iv.length, encryptedData.length);
return Base64.encodeToString(combined, Base64.DEFAULT);
}
/**
* Decrypts an AES-GCM encrypted message.
* @param chatKey The AES key used for decryption.
* @param encryptedData The Base64 encoded encrypted message.
* @return Decrypted plaintext message.
* @throws Exception if decryption fails.
*/
public static String decryptMessage(SecretKey chatKey, String encryptedData) throws Exception {
byte[] decodedData = Base64.decode(encryptedData, Base64.DEFAULT);
byte[] iv = new byte[12]; // GCM IV length is 12 bytes
System.arraycopy(decodedData, 0, iv, 0, iv.length);
byte[] encryptedBytes = new byte[decodedData.length - iv.length];
System.arraycopy(decodedData, iv.length, encryptedBytes, 0, encryptedBytes.length);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.DECRYPT_MODE, chatKey, spec);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
}
5. In groupchat.xml add a ListView listview1, an EditText edittext1 and a Button send.
6. Create a Custom View groupchat_item.xml and add items as shown in image below. Select it as Custom View of listview1.
7. In GroupchatActivity, add following components:
FirebaseDb component group_chat:groupchat, Calendar component cal, Dialog components dialog and dialog2, SharedPreferences component sp:sp, and FirebaseAuth component fauth.
8. Add following variables:
- String variables message_id, message, encrypted_message, date, passphrase, uid and username.
- Map variable map.
- List Map variable maplist.
9. Add import event and put following imports:
import javax.crypto.SecretKey;
10. Create a more block Declared and put codes to declare masterkey in it:
}
SecretKey masterkey;
{
11. In onCreate, get passphrase from shared preferences and use it to generate masterkey as shown in image below:
The code to generate masterkey is:
try {
masterkey = EncryptionHelper.deriveMasterKey(passphrase);
} catch (Exception e){
showMessage(e.toString());
}
12. Create a more block addUsername(username) fromMap(Map:map) toList (List Map:maplist) and put blocks as shown below.
13. In group_chat onChildAdded event put blocks as shown in image below.
Here the code to get username from uid isDatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("users").child(uid);
usersRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.exists()) {
username= snapshot.child("username").getValue(String.class);
// Put more block to add Username to maplist and refresh ListView.
}
}
@Override
public void onCancelled(DatabaseError error) {
username = uid;
// Put more block to add Username to maplist and refresh ListView.
}
});
try {
SecretKey messageKey = EncryptionHelper.deriveChatKey(masterkey, message_id);
encrypted_message = EncryptionHelper.encryptMessage(messageKey, message);
} catch (Exception e){
showMessage(e.toString());
}
try {
SecretKey messageKey = EncryptionHelper.deriveChatKey(masterkey, message_id);
message = EncryptionHelper.decryptMessage(messageKey, encrypted_message);
} catch (Exception e){
showMessage(e.toString());
}
Good project
ReplyDeletetop AI companies Australia
ReplyDeleteExplore the top AI companies in Australia known for delivering cutting-edge artificial intelligence solutions across industries. This list features leading AI development firms specializing in machine learning, automation, and data-driven innovations. Whether you're a startup or enterprise, discover trusted technology partners in Australia to accelerate your digital transformation with expert AI services and custom development capabilities tailored to your business needs.
ChatGPT app development cost
ReplyDeleteDiscover the real ChatGPT app development cost in this in-depth guide that outlines the essential components involved in building a high-functioning AI chatbot. From NLP integration and cloud infrastructure to UI/UX and post-launch support, understand how these factors influence overall AI chatbot app pricing.