Sử dụng bảo mật 2 lớp (2FA), demo bằng ngôn ngữ Java

Post Reply
khanhlv
Posts: 8
Joined: Tue Apr 16, 2019 4:25 pm

Sử dụng bảo mật 2 lớp (2FA), demo bằng ngôn ngữ Java

Post by khanhlv »

Bài hôm trước mình có giới thiệu về bảo mật 2 lớp (2FA), hôm nay mình tiếp làm demo cơ bản về 2FA và sử dụng nó bằng ngôn ngữ Java

Như hôm trước để xác thực 2 lớp cần có
  • 1 khóa bí mật chia sẻ (shared secret - một dãy các byte).
    1 đầu vào là thời gian hiện tại.
    1 hàm mã hóa.
Các bước thực thiện
1. Thư viện common-codec
2. Khóa bí mật
3. Mã hóa
4. Chạy thử
Thư viện common-codec
Mình có dùng thư viện commons-codec, các bạn mở file pom.xml

Code: Select all

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.6</version>
</dependency>
Khóa bí mật

Khóa bí mật này tùy từng hệ thống có các tạo khóa bí mật khác nhau, 16, 32, 64, 128 … ký tự

Như mình sẽ sử dụng 32 ký tự. Các bạn có thể dùng sẵn 1 số lib của commons-codec

Code: Select all

public static String generateBase32Secret(int length) {
    StringBuilder sb = new StringBuilder(length);
    Random random = new SecureRandom();
    for (int i = 0; i < length; i++) {
        int val = random.nextInt(32);
        if (val < 26) {
            sb.append((char) ('A' + val));
        } else {
            sb.append((char) ('2' + (val - 26)));
        }
    }
    return sb.toString();
}
Hàm này mình truyền vào độ dài của khóa ký tự, bạn muốn là bao nhiêu sẽ là bấy nhiêu

Kết quả sẽ như thế này: YJC5DTNL27744YLACGZFW5HY2AOUUE6F

Tạo QR Code
Mã hóa

Khi có khóa rồi mình làm bước tiếp theo mã hõa

hmac = SHA1(secret + SHA1(secret + input))

Code: Select all

public static long generateNumber(String base32Secret, long timeMillis, long timeStepSeconds)
        throws GeneralSecurityException {
    byte[] key = new Base32().decode(base32Secret);

    byte[] data = new byte[8];
    long value = timeMillis / 1000 / timeStepSeconds;
    for (int i = 7; value > 0; i--) {
        data[i] = (byte) (value & 0xFF);
        value >>= 8;
    }

    SecretKeySpec signKey = new SecretKeySpec(key, "HmacSHA1");
    Mac mac = Mac.getInstance("HmacSHA1");
    mac.init(signKey);
    byte[] hash = mac.doFinal(data);

    // take the 4 least significant bits from the encrypted string as an offset
    int offset = hash[hash.length - 1] & 0xF;

    // We're using a long because Java hasn't got unsigned int.
    long truncatedHash = 0;
    for (int i = offset; i < offset + 4; ++i) {
        truncatedHash <<= 8;
        // get the 4 bytes at the offset
        truncatedHash |= (hash[i] & 0xFF);
    }
    // cut off the top bit
    truncatedHash &= 0x7FFFFFFF;

    // the token is then the last 6 digits in the number
    truncatedHash %= 1000000;

    return truncatedHash;
}
String base32Secret là khóa bí mật long timeMillis là thời gian hiện tại của hệ thống long timeStepSeconds là thời gian hết hạn, mặt định là 30s

Chạy thử

Code: Select all

public static void main(String[] args) throws Exception {
    long DEFAULT_TIME_STEP_SECONDS = 30;
    String base32Secret = "YJC5DTNL27744YLACGZFW5HY2AOUUE6F";

    System.out.println(new String(decodeBase32(base32Secret)));
    System.out.println("Secret = " + base32Secret);

    String keyId = "[email protected]";
    Long code = null;

    while (true) {
        long diff = DEFAULT_TIME_STEP_SECONDS - ((System.currentTimeMillis() / 1000) % DEFAULT_TIME_STEP_SECONDS);
        code = generateNumber(base32Secret, System.currentTimeMillis(), DEFAULT_TIME_STEP_SECONDS);
        System.out.println("Secret code = " + code + ", change in " + diff + " seconds");
        Thread.sleep(1000);
    }
}
Kết quả:

Code: Select all

Secret = YJC5DTNL27744YLACGZFW5HY2AOUUE6F
Secret code = 706313, change in 26 seconds
Secret code = 706313, change in 25 seconds
Secret code = 706313, change in 24 seconds
Secret code = 706313, change in 23 seconds
Secret code = 706313, change in 22 seconds
Bây giờ các bạn có thể dùng áp dụng 2 lớp cho hệ thống mình rồi.

Và có thể thay thế Google Authenticator rồi, đỡ phải cài đặt ứng dụng =)))

Tham khảo:
https://codethoi.com/posts/su-dung-bao- ... code-java/

Post Reply