Giữ an toàn cho App Android trước khi công khai
Dù đơn giản chỉ là những app tin tức, những app không cần thiết về về tính bảo mật thì cũng nên giữ an toàn cho sản phẩm bằng cách áp dụng các phương pháp đơn giản dưới đây trước khi đưa app đến với người dùng.
1. Rút gọn, tối ưu và làm phức tạp hoá mã code với Proguard.
Sử dụng công cụ Proguard có sẵn trong Android Studio để thu nhỏ, bỏ đi những thư viện, mã code và resource không sử dụng làm giảm kích thước app, và hơn thế nữa có thể làm mã code trở nên phức tạp để app trở nên an toàn hơn, ngăn chặn được việc dịch ngược mã code.
Tuy rằng bước này không phải là bắt buộc trong quá trình lập trình Android nhưng đây là một bước không nên bỏ qua trước khi cho ứng dụng lên app store. Cách sử dụng tính năng Proguard gồm hai bước đơn giản sau:
Bước 1: Bật tuỳ chọn sự dụng tính năng proguard trong file build.gradle như sau:
1
2
3
4
5
6
7
8
9
|
buildTypes {
debug{...}
release {
minifyEnabled true //Loại bỏ những tài nguyên không cần thiết
shrinkResources true //Thu gọn size code,loại bỏ code thừa
useProguard true //Làm phức tạp hoá code
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
}
}
|
Bước 2: Cấu hình Proguard được thực hiện mặc định thông qua file cấu hình “proguard-rules.pro”.
Bạn có thể xem hướng dẫn để cấu hình trên trang Proguard hoặc các ví dụ chi tiết sample trên github. Ví dụ muốn xoá toàn bộ các tin nhắn log trong quá trình phát triển trong phiên bản release thì sẽ config như dưới đây trong file “proguard-rules.pro”
1
2
3
4
5
6
7
|
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int d(...);
public static int w(...);
public static int v(...);
public static int i(...);
}
|
Như vậy thì tất cả các dòng sinh tin nhắn log trong code của bạn sẽ được clear khi build phiên bản release. Thật tuyệt phải không? và sau khi sử dụng proguard bạn sẽ nhận thấy rằng size của app được giảm đáng kể, làm rút ngắn quá trình tải app của người dùng, cũng như tiết kiệm dung lượng memory của những máy Android đời cũ có cấu hình bộ nhớ rất eo hẹp.
Lưu ý rằng là do app đã được làm mờ(phức tạp hoá) lên trong quá trình sử dụng mà muốn theo dõi phân tích các log crash, log cảnh báo trên các công cụ phân tích của Google Play Store, hay Firebase chẳng hạn, thì chúng ta cần sử dụng đến các file mapping được sinh ra khi build app để có thể dịch ngược lại các message log.
2. An toàn và đảm bảo hơn khi sử dụng khoá ứng dụng của Google play(Google Play key store).
Khi build app cần phải sử dụng đến khoá ứng dụng keystore, hiện nay có thể create keystore đơn giản và nhanh chóng bằng chính công cụ Android Studio. Nhưng sẽ rất nguy hiểm khi bạn lưu trữ bảo vệ keystore một cách không cẩn thận, như bị mất, hoặc bị kẻ xấu đánh cắp. Do đó sử dụng Google Play key store là một phương án rất tốt để quản lý khoá ứng dụng, khoá sẽ được lưu trữ và quản lý trên app store nên sẽ không sợ bị lộ, cũng như bị mất do ổ cứng bị hỏng hay đơn giản là bạn lỡ xoá nó đi.
Nếu là lần đầu tiên đăng kí app lên store, bạn sẽ rất dễ dàng để để sử dụng dịch vụ chương trình quản lý chữ kí ứng dụng của google play. Trong phần cài đặt đưa app lên release, chỉ cần lựa chọn 有効 chương trình chữ kí ứng dụng, sau đó upload file apk được build với khoá ứng dụng bạn đã tạo lên giống như bình thường. Chương trình quản lý chữ kí của Google sẽ tạo ra cho bạn một key mới (thay thế cho khoá ứng dụng của bạn) để cài đặt vào app của bạn. Khi này bạn có thể xem được thông tin chữ kí ứng dụng mới của bạn trong mục アプリの署名 của Google play console.
Lưu ý là do app của bạn đã được thay thế sử dụng chữ kí mới của google nên khi app sử dụng dịch vụ của bên thứ ba ví dụ như Firebase mà cần phải đăng kí nhận chứng bằng mã ứng dụng(SHA-1 chẳng hạn) thì ở đây bạn cần phải thêm hoặc thay thế bằng mã SHA-1 của keystore mới của Google play(thông tin được hiển thị trong mụcアプリの署名).
3. Mã hoá các thông tin quan trọng như mật khẩu, access key với Android keystore system.
Trong quá trình phát triển app, rất đơn giản và dễ dàng để sử dụng các thuật toán mã hoá như Cipher, MesageDigest, Mac, Signature để bảo vệ các thông tin quan trọng trong app của bạn. Do đó không nên ngại gì mà thay thế việc khai báo hardcode chúng trong code của ứng dụng như thông thường chẳng hạn bằng việc sử dụng việc mã hoá dữ liệu để bảo vệ dữ liệu an toàn hơn hay đơn giản là việc xây dựng ứng dụng sẽ trở lên chuyên nghiệp hơn.
Một ví dụ về mã hoá và giải mã sử dụng Cipher
Bước 1: Đầu tiên cần Get thông tin Keystore app của bạn
1
2
3
4
5
6
7
|
private KeyStore mKeyStore
try {
mKeyStore = KeyStore.getInstance("AndroidKeyStore");
mKeyStore.load(null);
}catch (Exception e) {
Log.e(TAG, e.toString());
}
|
Bước 2: Tạo một cặp khoá mới (public key/private key) để sử dụng trong ứng dụng.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
try {
if (!keyStore.containsAlias(alias)) {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA,”AndroidKeyStore”);
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_DECRYPT)
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
.build());
keyPairGenerator.generateKeyPair();
}
} catch (Exception e) {
Log.e(TAG, e.toString());
}
|
Bước 3: Mã hoá thông tin trước khi lưu trữ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
String ALGORITHM = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
String encryptedText = null;
try {
PublicKey publicKey = keyStore.getCertificate(alias).getPublicKey();
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher);
cipherOutputStream.write(plainText.getBytes("UTF-8"));
cipherOutputStream.close();
byte [] bytes = outputStream.toByteArray();
encryptedText = Base64.encodeToString(bytes, Base64.DEFAULT);
} catch (Exception e) {
Log.e(TAG, e.toString());
}
|
Bước 4: Giải mã và lấy thông tin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
String plainText = null;
try {
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, null);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(encryptedText, Base64.DEFAULT)), cipher);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int b;
while ((b = cipherInputStream.read()) != -1) {
outputStream.write(b);
}
outputStream.close();
plainText = outputStream.toString("UTF-8");
} catch (Exception e) {
Log.e(TAG, e.toString());
}
|
Vậy là với 3 phương pháp đơn giản trên thì bạn đã làm ứng dụng trở lên an toàn hơn và chuyên nghiệp hơn rất nhiều rồi đấy. Ngoài ra còn rất nhiều các phương pháp để bảo vệ cho ứng dụng của bạn trên môi trường Android luôn được biết đến là môi trường mở không được an toàn này. Hãy tìm hiểu thêm để có thể đóng góp một phần vào việc khắc phục điểm yếu chết người này mang lại niềm tin của người sử dụng vào hệ điều hành Android nhé.
https://developer.android.com/training/articles/security-tips?hl=ja
Tham khảo:
https://developer.android.com/studio/publish/app-signing?hl=ja
https://developer.android.com/training/articles/keystore?hl=ja