Mã hóa dữ liệu với thuật toán AES (Advanced Encryption Standard) trong android

Để tìm hiểu và nói về thuật toán AES trong mã hóa dữ liệu thì khả năng ở một bài mình cũng khó có thể giới thiệu được hơn cũng như kiến thức của mình về mã hóa cũng không nhiều, nên mình xin phép chỉ giới thiệu sơ qua về thuật toán AES.

1. Giới thiệu đôi chút về thuật toán.

AES là thuật toán được phát triển dựa trên bản thiết kế Square bởi 2 nhà mật mã học người bỉ là Joan Daemen và Vincent Rijmen.AES là một thuật toán mã hóa khối đối xứng với độ dài khóa là 128 bít (một chữ số nhị phân có giá trị 0 hoặc 1), 192 bít và 256 bít tương ứng gọi là AES-128, AES-192 và AES-256. tùy vào độ dài của key khi sử dụng mà ta có số vòng lặp khác nhau AES-128 sử dụng 10 vòng (round), AES-192 sử dụng 12 vòng và AES-256 sử dụng 14 vòng. Các thứ tự hàm AES sẽ thực hiện :

  • Trộn từng byte (SubBytes) mỗi byte được thay thế với các byte khác,
  • trộn từng hàng (ShiftRows) : Phép biến đổi dùng trong phép mã hóa áp dụng lên trạng thái bằng cách chuyển dịch vòng ba hàng cuối của trạng thái theo số lượng byte các offset khác nhau.
  • trộn từng cột (MixColumns) : mỗi cột được chuyển đổi tuyến tính bằng cách nhân nó với một ma trận trong trường hữu hạn
  • mã hóa (AddRoundKey) : mỗi byte trong bảng trạng thái được thực hiện phép XOR với một khoá vòng, quá trình xử lý AES thu được 11 khoá vòng từ các key mã hoá được phân phát cho kỹ thuật mã hoá.

2. Áp dụng thuật toán vào trong android.

  • Thật may vì google đã cũng cấp cho chúng ta 3 gói chính để ta có thể sử dụng dễ dàng hơn cho việc mà hóa dữ liệu
  • Javax.crypto : Gói này cung cấp các lớp và giao diện cho các ứng dụng mật mã thực hiện các thuật toán để mã hóa, giải mã, hoặc thỏa thuận quan trọng. Javax.crypto
  • Javax.crypto.interfaces : Gói này cung cấp các giao diện cần thiết để thực hiện thuật toán hợp đồng chính.
  • Javax.crypto.spec : Gói này cung cấp các lớp học và giao diện cần thiết để xác định các khóa và tham số để mã hóa.
  • trong Javax.crypto có chứa class Cipher lớp này cung cấp cho chúng ta các mã hóa để giải mã và mã hóa.
  • để cho dễ nhìn mình sẽ copy đoạn code chứa mã hóa và giải mã
public class AESHelper {
    private static final String ALGORITHM = "AES";
    private final static String HEX = "0123456789ABCDEF";

    // sử dụng hàm này khi cần mã hóa dữ liệu
    public static String encrypt(String seed, String cleartext) throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] result = encrypt(rawKey, cleartext.getBytes());
        return toHex(result);
    }

    // sử dụng hàm này khi cần giải mã dữ liệu
    public static String decrypt(String seed, String encrypted) throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] enc = toByte(encrypted);
        byte[] result = decrypt(rawKey, enc);
        return new String(result);
    }

    private static byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen =
            KeyGenerator.getInstance(ALGORITHM);  // tạo ra các khóa bí mật có thể dùng lại
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); // tạo ra mã ngẫu nhiên 
        sr.setSeed(
            seed); //Reseeds this random object, using the eight bytes contained in the given long seed.
        kgen.init(128, sr); // sử dụng AES-128
        SecretKey skey = kgen.generateKey();
        byte[] raw =
            skey.getEncoded();  // return the raw key bytes as the result of a getEncoded method call.
        return raw;
    }

    private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
    }

    private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }

    public static String toHex(String txt) {
        return toHex(txt.getBytes());
    }

    public static String fromHex(String hex) {
        return new String(toByte(hex));
    }

    // chuyển đổi String thành mảng byte
    public static byte[] toByte(String hexString) {
        int len = hexString.length() / 2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++)
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
        return result;
    }

    // chuyển đổi một mảng byte trở thành String
    public static String toHex(byte[] buf) {
        if (buf == null)
            return "";
        StringBuffer result = new StringBuffer(2 * buf.length);
        for (int i = 0; i < buf.length; i++) {
            appendHex(result, buf[i]);
        }
        return result.toString();
    }

    // dịch chuyển bit vào thêm mã hex
    private static void appendHex(StringBuffer sb, byte b) {
        sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
    }
}
  • mình đã ghi chú thích vào trong code các bạn có thể nhìn và đọc code
// đoạn code mã hóa
AESHelper.encrypt(email)
AESHelper.encrypt(password)
// đoạn giải mã
String email = AESHelper.decrypt(SpManager.getInstance().getString(Constant.KEY_REQUEST_EMAIL, ""));
String password =AESHelper.decrypt(SpManager.getInstance().getString(Constant.KEY_REQUEST_PASSWORD, ""));

3. Kết Luận và tài liệu tham khảo.

Thuật toán AES là một thuật toán mã hóa khối hay nhưng cần rất nhiều thời gian nghiên cứu. https://voer.edu.vn/m/chuan-ma-nang-cao-aes/5e535262 https://en.wikipedia.org/wiki/Advanced_Encryption_Standard