← Quay lại blog

Tính ngẫu nhiên mật mã học trong trình duyệt: Math.random so với crypto.getRandomValues

PetexSpace

Tạo số ngẫu nhiên là nền tảng cốt lõi của bảo mật web hiện đại, làm cơ sở cho định danh phiên làm việc (session identifier), tạo token, nonce, salt cho băm mật khẩu và dẫn xuất khóa đối xứng. Trong các môi trường thực thi JavaScript hiện đại, lập trình viên thường bắt gặp hai giao diện riêng biệt để tạo các giá trị giả ngẫu nhiên: hàm thư viện chuẩn quen thuộc Math.random() và phương thức Web Cryptography API hiện đại crypto.getRandomValues().

Dù cả hai hàm đều trả về các chuỗi số có vẻ không thể đoán trước về mặt thống kê đối với người quan sát thông thường, nhưng mô hình toán học bên dưới, quy trình xử lý entropy theo kiến trúc và mức độ đảm bảo bảo mật của chúng lại hoàn toàn khác biệt. Việc nhầm lẫn giữa hai giao diện này là một trong những nguyên nhân phổ biến nhất dẫn đến các lỗ hổng bảo mật nghiêm trọng trong phần mềm web.

Khi các lập trình viên xây dựng những công cụ web bảo vệ quyền riêng tư như công cụ chọn ngẫu nhiên mật mã học tương tác hay vòng quay ngẫu nhiên dựa trên entropy, việc đảm bảo tính công bằng tuyệt đối cùng khả năng không thể dự đoán về mặt mật mã đòi hỏi phải nắm vững cơ chế hoạt động của các bộ tạo số giả ngẫu nhiên (PRNG) và các bộ tạo số giả ngẫu nhiên an toàn về mặt mật mã (CSPRNG).

1. Kiến trúc thuật toán: PRNG so với CSPRNG

Để hiểu rõ ranh giới bảo mật giữa Math.random() và crypto.getRandomValues(), chúng ta cần xem xét cách phân loại trên phương diện lý thuyết của các bộ tạo chuỗi ngẫu nhiên.

   DETERMINISTIC PSEUDO-RANDOM NUMBER GENERATOR (PRNG)
   +-------------+       +-------------------+       +-----------------------+
   | Fixed Seed  | ----> | Transition State  | ----> | Statistical Stream    |
   | (e.g. 64-bit|       | s_{n+1} = f(s_n)  |       | Predictable from past |
   +-------------+       +-------------------+       +-----------------------+

   CRYPTOGRAPHICALLY SECURE PSEUDO-RANDOM NUMBER GENERATOR (CSPRNG)
   +-------------+       +-------------------+       +-----------------------+
   | OS Entropy  | ----> | Non-Linear Cipher | ----> | Cryptographic Stream  |
   | Irreversible|       | Forward Secrecy   |       | Indistinguishable from|
   | Pool (TRNG) |       | State Inversion   |       | True White Noise      |
   +-------------+       +-------------------+       +-----------------------+

Bộ tạo số giả ngẫu nhiên (PRNG)

Một PRNG thông thường là một máy trạng thái hoàn toàn đơn định (deterministic state machine), được khởi tạo bằng một giá trị số ban đầu gọi là hạt giống (SS). Bộ tạo này vận hành thông qua hai thuật toán đơn định:

  1. Hàm chuyển đổi trạng thái: sn+1=f(sn)s_{n+1} = f(s_n)
  2. Hàm phóng chiếu đầu ra: on=g(sn)o_n = g(s_n)

Khi được cung cấp các giá trị hạt giống giống nhau, PRNG sẽ tạo ra các chuỗi hoàn toàn trùng khớp qua mỗi lần chạy. Các thuật toán PRNG (như Mersenne Twister, PCG hay Xorshift) được tối ưu hóa cho ba mục tiêu kỹ thuật cụ thể:

  • Thông lượng cực cao (sản sinh hàng triệu mẫu mỗi giây bằng các phép toán cấp độ chu kỳ xung nhịp đơn).
  • Chu kỳ tuần hoàn dài (đảm bảo rằng chuỗi không lặp lại cho đến khi trải qua 21282^{128} hoặc 219937−12^{19937}-1 lần lặp).
  • Phân phối thống kê đồng đều (vượt qua các bộ kiểm thử thực nghiệm như Dieharder hoặc TestU01).

Điều quan trọng là các PRNG tiêu chuẩn không được thiết kế để chống lại sự can thiệp từ đối thủ tấn công. Vượt qua các bài kiểm tra thống kê về tính đồng đều không đồng nghĩa với việc không thể dự đoán được.

Bộ tạo số giả ngẫu nhiên an toàn về mặt mật mã (CSPRNG)

Một CSPRNG phải thỏa mãn hai tiêu chuẩn lý thuyết thông tin hình thức mà các PRNG tiêu chuẩn cố tình bỏ qua:

  1. Kiểm thử bit tiếp theo (Tính không thể dự đoán đa thức - Next-Bit Test): Khi biết trước kk bit đầu tiên của một chuỗi đầu ra do CSPRNG tạo ra, không một thuật toán thời gian đa thức nào có thể dự đoán bit thứ (k+1)(k+1) với xác suất thành công lớn hơn 0.5 một cách đáng kể (tương đương với việc đoán ngẫu nhiên thuần túy).
  2. Khả năng chống xâm phạm trạng thái (Tính bảo mật tiến và lùi - Forward and Backward Secrecy): Nếu kẻ tấn công có được quyền truy cập vào trạng thái nội bộ của bộ tạo tại bước thời gian tt, họ không thể suy ra bất kỳ đầu ra nào đã được tạo ra trước đó tại t−1,t−2,…t - 1, t - 2, \dots (tính bảo mật lùi), đồng thời cũng không thể dự đoán các đầu ra tương lai tại t+1,t+2,…t + 1, t + 2, \dots sau khi bộ tạo được cấp hạt giống mới từ nguồn entropy bên ngoài (tính bảo mật tiến).

2. Giải phẫu Math.random() trong các JavaScript Engine hiện đại

Đặc tả ngôn ngữ ECMAScript (ECMA-262) chủ đích không quy định một tiêu chuẩn mật mã học bắt buộc cho Math.random(). Đặc tả chỉ yêu cầu hàm này trả về một số dấu phẩy động có phân phối xấp xỉ đồng đều trong khoảng [0,1)[0, 1), nêu rõ:

"Mỗi hàm Math.random trả về một giá trị Number mang dấu dương, lớn hơn hoặc bằng 0 nhưng nhỏ hơn 1 một cách tuyệt đối, được chọn ngẫu nhiên hoặc giả ngẫu nhiên với phân phối xấp xỉ đồng đều trên khoảng đó, sử dụng một thuật toán hoặc chiến lược tùy thuộc vào bản hiện thực (implementation-dependent)."

Sự tiến hóa trong việc hiện thực hóa của các Engine

Trong những thập kỷ đầu của web, các browser engine đã sử dụng Linear Congruential Generator (LCG) sơ khai để hiện thực Math.random(). LCG hoạt động dựa trên hệ thức truy đệ:

Xn+1=(aXn+c)(modm)X_{n+1} = (a X_n + c) \pmod m

LCG chịu ảnh hưởng bởi hiện tượng căn chỉnh siêu phẳng (hyper-plane alignment) nghiêm trọng, độ lệch thống kê lớn và chu kỳ ngắn (2322^{32}). Vào năm 2015, sau các nghiên cứu bảo mật công khai chỉ ra khả năng dự đoán token giữa các tab, các nhà phát triển trình duyệt lớn (bao gồm Google V8 trên Chrome 49, Mozilla Firefox và Apple Safari) đã chuyển sang một họ bộ tạo phi mật mã học hiện đại: xorshift128+.

Cơ chế toán học của xorshift128+

Thuật toán xorshift128+ hoạt động dựa trên một trạng thái nội bộ gồm hai số nguyên không dấu 64-bit: s0s_0 và s1s_1, tạo ra không gian trạng thái 128-bit. Quá trình chuyển đổi trạng thái và tạo đầu ra được thực hiện hoàn toàn qua các phép dịch bit, XOR và phép cộng 64-bit:

// V8 xorshift128+ internal step logic
uint64_t state0 = state[0];
uint64_t state1 = state[1];
uint64_t result = state0 + state1; // Output before state rotation

state1 ^= state1 << 23;
state[1] = state1 ^ state0 ^ (state1 >> 17) ^ (state0 >> 26);
state[0] = state1;

Để biến đổi số nguyên 64-bit result thành số dấu phẩy động độ chính xác kép trong khoảng [0,1)[0, 1), V8 áp mặt nạ cho 52 bit thấp để khớp vào phần định trị (mantissa) chuẩn IEEE 754, đặt số mũ thành 1023 (đại diện cho 202^0), và trừ đi 1.0:

double random_float = (double)(result & 0xFFFFFFFFFFFFF) / (double)(1ULL << 52);

Các cuộc tấn công tái tạo trạng thái thông qua Z3 Theorem Prover

Vì xorshift128+ hoàn toàn sử dụng các phép toán tuyến tính trên trường Galois GF(2)GF(2) (phép dịch bit và XOR) kết hợp với một phép cộng phi tuyến duy nhất theo modulo 2642^{64}, không gian trạng thái của nó rất mỏng manh về mặt toán học.

Khi một ứng dụng web gọi Math.random(), nó để lộ 52 bit của tổng 64-bit nội bộ (state0+state1state_0 + state_1). Bằng cách thu thập từ hai đến ba giá trị dấu phẩy động liên tiếp được tạo bởi Math.random(), kẻ tấn công có thể thiết lập một hệ phương trình ràng buộc tuyến tính trên GF(2)GF(2).

Sử dụng các bộ giải Satisfiability Modulo Theories (SMT) hiện đại như Z3 của Microsoft Research, kẻ tấn công có thể khôi phục chính xác ma trận trạng thái 128-bit (s0,s1s_0, s_1) trong thời gian thực thi chưa đầy 10 mili giây. Khi trạng thái đã được phục hồi, kẻ tấn công có thể dự đoán mọi số tiếp theo cũng như các số trước đó được sinh ra bởi ngữ cảnh JavaScript đó.

   OBSERVED SEQUENCE FROM Math.random()
   Output 1: 0.8472918392019482  --> Reveals 52 bits of (s0 + s1)
   Output 2: 0.1948201938501239  --> Reveals 52 bits of (s0' + s1')
   Output 3: 0.6391029482019481  --> Reveals 52 bits of (s0'' + s1'')
                     |
                     v
   +----------------------------------------------------+
   | SMT SOLVER (Z3 Theorem Prover)                      |
   | Formulates system of equations over GF(2)           |
   | Solves for unknown 128-bit seed state in < 10 ms    |
   +----------------------------------------------------+
                     |
                     v
   Complete Compromise: Attacker predicts all session tokens,
   reset links, random choices, and game outcomes indefinitely.

Nếu lập trình viên sử dụng Math.random() để tạo token đặt lại mật khẩu, định danh phiên làm việc hoặc nonce CSRF, kẻ tấn công bên ngoài có thể thu thập các số từ các trang web công khai, đảo ngược trạng thái bộ tạo và giả mạo các token quản trị hợp lệ.

3. Web Cryptography API và crypto.getRandomValues()

Để cung cấp cho các ứng dụng web những đảm bảo mật mã học thực sự, W3C đã chuẩn hóa Web Cryptography API. Điểm truy cập cho tính ngẫu nhiên an toàn là phương thức crypto.getRandomValues(), được cung cấp trên các phạm vi window chuẩn của trình duyệt và Web Worker.

Khác với các phép tính số học ở tầng user-space của Math.random(), việc gọi crypto.getRandomValues(typedArray) sẽ vượt qua ranh giới sandbox của trình duyệt để truy vấn hệ thống con entropy ở tầng nhân (kernel) của hệ điều hành máy chủ.

   +-------------------------------------------------------------+
   | USER AGENT BROWSER SANDBOX                                  |
   |                                                             |
   |   crypto.getRandomValues(new Uint8Array(32))                |
   |              |                                              |
   |              v                                              |
   |   Browser Process Inter-Process Communication (IPC)         |
   +-------------------------------------------------------------+
                                  |
                                  v
   +-------------------------------------------------------------+
   | OPERATING SYSTEM KERNEL                                     |
   |                                                             |
   |   +-----------------------------------------------------+   |
   |   | Hardware Entropy Sources:                            |   |
   |   | RDRAND / RDSEED CPU opcodes                         |   |
   |   | Keystroke jitter, network packet inter-arrival times |   |
   |   | Disk interrupt latencies, thermal noise             |   |
   |   +-----------------------------------------------------+   |
   |                              |                              |
   |                              v                              |
   |   +-----------------------------------------------------+   |
   |   | Operating System Cryptographic Entropy Pool:        |   |
   |   | Linux: getrandom(2) / /dev/urandom                  |   |
   |   | macOS / iOS: SecRandomCopyBytes / arc4random        |   |
   |   | Windows: BCryptGenRandom (CNG Cryptographic API)    |   |
   |   +-----------------------------------------------------+   |
   |                              |                              |
   |                              v                              |
   |   CSPRNG Algorithm: ChaCha20 or AES-CTR-DRBG (NIST SP800-90A|
   +-------------------------------------------------------------+

Quy trình tích hợp nhân hệ điều hành

Tùy thuộc vào hệ điều hành máy chủ bên dưới, các browser engine hiện đại tương tác với các hệ thống con mật mã học riêng biệt:

  • Linux / Android: Chromium và Gecko thực hiện lời gọi hệ thống getrandom(2), truy vấn driver CSPRNG của nhân Linux. Driver này thu thập entropy phần cứng vật lý từ thời gian ngắt thiết bị, dao động nhiệt và các bộ tạo nhiễu phần cứng, sau đó băm vùng nhớ chung (pool) bằng ChaCha20 hoặc SHA-256.
  • Apple macOS / iOS: Trình duyệt gọi SecRandomCopyBytes từ Security framework hoặc arc4random_buf, giao tiếp trực tiếp với mô-đun mật mã cốt lõi của nhân XNU.
  • Microsoft Windows: Trình duyệt thực hiện các lời gọi tới BCryptGenRandom thông qua Cryptography API: Next Generation (CNG), sử dụng bộ tạo bit ngẫu nhiên đơn định ở chế độ bộ đếm AES-256 (CTR-DRBG) tuân thủ tiêu chuẩn NIST SP 800-90A.

Giới hạn bộ đệm 65.536 byte

Đặc tả Web Cryptography API quy định một giới hạn hiệu năng nghiêm ngặt: một lệnh gọi đơn lẻ tới crypto.getRandomValues() không được phép tiếp nhận một ArrayBufferView vượt quá 65.536 byte (64 KiB).

Nếu phía gọi yêu cầu một bộ đệm lớn hơn:

// Throws a DOMException: QuotaExceededError
crypto.getRandomValues(new Uint8Array(65537));

Hạn ngạch này phục vụ hai mục đích kiến trúc:

  1. Ngăn chặn cạn kiệt entropy của nhân: Việc truy vấn các khối dữ liệu lớn từ các vùng nhớ chung của nhân hệ điều hành có thể gây ra tranh chấp khóa CPU (lock contention) trong các môi trường đa luồng.
  2. Bảo vệ giao diện người dùng trên luồng chính (Main Thread): Việc thực thi trong trình duyệt phải tránh hiện tượng chặn đồng bộ qua các kênh IPC, điều có thể gây rớt khung hình khi hiển thị.

4. Tính đồng đều thống kê và bẫy sai lệch mật mã học

Ngay cả khi lấy entropy từ crypto.getRandomValues(), lập trình viên vẫn thường xuyên đưa vào các lỗ hổng toán học nguy hiểm khi ánh xạ các byte mật mã thô thành các giá trị ở cấp độ ứng dụng (chẳng hạn như các số nguyên trong khoảng [min,max][min, max]).

Sai lầm khi giảm trừ theo Modulo (Modulo Bias)

Sai lầm phổ biến nhất khi triển khai liên quan đến việc sử dụng toán tử modulo để thu hẹp các số nguyên ngẫu nhiên về khoảng mong muốn.

Giả sử một hệ thống cần một số nguyên ngẫu nhiên từ 0 đến 9 (10 kết quả có thể xảy ra). Lập trình viên tạo một số nguyên không dấu 8-bit thô (0≤X≤2550 \le X \le 255) và tính:

Selection=X(mod10)\text{Selection} = X \pmod{10}

Vì 256256 không chia hết cho 1010 (256=25×10+6256 = 25 \times 10 + 6), nên các số 0,1,2,3,4,0, 1, 2, 3, 4, và 55 được ánh xạ từ 2626 giá trị byte nguồn khác nhau (0,10,…,2500, 10, \dots, 250). Ngược lại, các số 6,7,8,6, 7, 8, và 99 chỉ được ánh xạ từ 2525 giá trị byte nguồn.

   Source Space: 256 Discrete Bytes (0 to 255)
   +-----------------------------------------------------------------+
   | Byte: 0   1   2   3   4   5   6   7   8   9   10  11 ... 255    |
   +-----------------------------------------------------------------+
     |   |   |   |   |   |   |   |   |   |   |   |
     v   v   v   v   v   v   v   v   v   v   v   v
   [ 0   1   2   3   4   5   6   7   8   9   0   1 ...   5 ]
   
   Occurrences:
   Values 0 through 5 appear 26 times each -> P(0..5) = 26 / 256 = 10.156%
   Values 6 through 9 appear 25 times each -> P(6..9) = 25 / 256 =  9.765%
   Modulo Bias introduces a 4.0% relative statistical advantage!

Trong các môi trường quan trọng (chẳng hạn như tạo nonce mật mã học, khóa mật mã hoặc quay số trúng thưởng), độ lệch thống kê này sẽ tạo ra sự thiên vị có thể bị khai thác.

Triệt tiêu độ lệch bằng phương pháp lấy mẫu loại trừ (Rejection Sampling)

Để đảm bảo tính đồng đều toán học tuyệt đối, lập trình viên phải sử dụng phương pháp lấy mẫu loại trừ (rejection sampling). Bất kỳ byte ngẫu nhiên nào rơi vào phần dư mất cân bằng ở đuôi đều phải bị loại bỏ và tiến hành rút một mẫu mới.

/**
 * Generates a cryptographically secure, uniformly distributed integer
 * in the closed range [min, max] using rejection sampling.
 */
export function getSecureRandomInt(min: number, max: number): number {
  if (min > max) {
    throw new Error("Minimum bound cannot exceed maximum bound.");
  }
  if (!Number.isSafeInteger(min) || !Number.isSafeInteger(max)) {
    throw new Error("Bounds must be safe integers.");
  }

  const range = max - min + 1;
  if (range === 1) return min;

  // Use 32-bit words for range up to 2^32 - 1
  const maxUint32 = 0xffffffff;
  const limit = maxUint32 - (maxUint32 % range);

  const buffer = new Uint32Array(1);

  while (true) {
    window.crypto.getRandomValues(buffer);
    const candidate = buffer[0];

    // Reject candidates in the biased tail region
    if (candidate < limit) {
      return min + (candidate % range);
    }
  }
}

Dẫn xuất các số dấu phẩy động đồng đều

Nếu một ứng dụng yêu cầu giá trị dấu phẩy động trong khoảng mở [0,1)[0, 1) tương tự như Math.random() nhưng có đầy đủ tính bảo mật mật mã học, phần định trị 53-bit theo chuẩn IEEE 754 phải được lấp đầy đồng đều từ 64 bit entropy mật mã:

/**
 * Returns a cryptographically secure float in [0, 1) without mantissa bias.
 */
export function getSecureRandomFloat(): number {
  const buffer = new Uint32Array(2);
  window.crypto.getRandomValues(buffer);

  // Extract 53 random bits
  const high21 = buffer[0] & 0x1fffff; // 21 bits
  const low32 = buffer[1];             // 32 bits

  // Reassemble into exact float64 mantissa: (high * 2^32 + low) / 2^53
  const mantissa53 = high21 * 0x100000000 + low32;
  return mantissa53 / 0x20000000000000;
}

5. Hiện thực thực tế trong các ứng dụng web bảo vệ quyền riêng tư

Việc xây dựng các tiện ích lập trình mạnh mẽ đòi hỏi phải duy trì ranh giới kiến trúc nghiêm ngặt giữa các luồng thực thi và tránh phụ thuộc vào phía server. Trong các công cụ như bộ chọn /random-name của PetexSpace, việc dựa vào các API từ xa để xáo trộn danh sách sẽ gây ra độ trễ, tiêu tốn tài nguyên mạng và tiềm ẩn nguy cơ lộ dữ liệu người dùng.

Thực thi hoàn toàn trên trình duyệt cục bộ bằng crypto.getRandomValues() mang lại kết quả tức thì không độ trễ, đồng thời đảm bảo danh sách người tham gia, bảng điểm học sinh hay các nội dung bảo mật không bao giờ rời khỏi bộ nhớ cục bộ của người dùng.

                    ZERO-TELEMETRY BROWSER WORKSPACE
   +---------------------------------------------------------------+
   |                                                               |
   |   Input List: [ "Alice", "Bob", "Charlie", "Diana" ]          |
   |                               |                               |
   |                               v                               |
   |   Fisher-Yates Shuffle with Cryptographic Rejection Sampling  |
   |   +-------------------------------------------------------+   |
   |   | For i = n - 1 down to 1:                              |   |
   |   |   j = getSecureRandomInt(0, i)                        |   |
   |   |   Swap(list[i], list[j])                              |   |
   |   +-------------------------------------------------------+   |
   |                               |                               |
   |                               v                               |
   |   Unbiased Result Rendered Directly to Local Screen           |
   |                                                               |
   |   - Sourced from hardware kernel entropy                      |
   |   - Unbiased Fisher-Yates permutation                         |
   |   - Zero network transmission or server telemetry             |
   +---------------------------------------------------------------+

Danh mục kiểm tra đánh giá an toàn cho ứng dụng web

Khi thực hiện đánh giá bảo mật cho các ứng dụng TypeScript và JavaScript, đội ngũ kỹ thuật nên áp dụng các quy tắc phân tích tĩnh tự động sau:

  1. Cấm Math.random() trong các ngữ cảnh mật mã: Cấu hình ESLint với các quy tắc không cho phép sử dụng Math.random() trên các tệp xử lý token xác thực, tạo salt mật mã học, khóa lưu trữ phiên làm việc hoặc logic trò chơi.
  2. Bắt buộc dùng phương pháp lấy mẫu loại trừ an toàn: Đảm bảo tất cả các phép toán modulo trên các bộ đệm mật mã đều được bọc trong các vòng lặp loại trừ có giới hạn.
  3. Phân chia các yêu cầu lớn: Nếu ứng dụng của bạn tạo vật liệu khóa mật mã hoặc tập dữ liệu kiểm thử vượt quá 64 KiB, hãy chia nhỏ các yêu cầu thành các vòng lặp tuần tự:
export function fillLargeSecureBuffer(buffer: Uint8Array): Uint8Array {
  const CHUNK_SIZE = 65536;
  for (let offset = 0; offset < buffer.length; offset += CHUNK_SIZE) {
    const chunk = buffer.subarray(offset, Math.min(offset + CHUNK_SIZE, buffer.length));
    window.crypto.getRandomValues(chunk);
  }
  return buffer;
}

Bằng cách tuân thủ nguyên tắc mật mã học nghiêm ngặt và tận dụng Web Cryptography API, các ứng dụng web hiện đại có thể đạt được mức độ bảo mật chuẩn doanh nghiệp cùng tính công bằng thống kê tuyệt đối ngay bên trong sandbox của trình duyệt người dùng.

CryptographyXác thựcSecurity

Kiến trúc của Mật khẩu Một lần Dựa trên Thời gian: Khám phá RFC 6238 và Cơ chế Tạo HMAC

Phân tích toán học và giao thức toàn diện về Mật khẩu Một lần Dựa trên Thời gian (TOTP) theo chuẩn RFC 6238, khám phá kỹ thuật dynamic truncation, bộ đếm bước HMAC-SHA1, xử lý lệch đồng hồ và thực thi an toàn ngay trên trình duyệt.

PetexSpace
CryptographyData EncodingMã QR

Giải phẫu mã QR: Cơ chế sửa lỗi Reed-Solomon và mã hóa ma trận

Khám phá chuyên sâu về mặt toán học của mã QR chuẩn ISO/IEC 18004, phân tích chi tiết số học trường Galois GF(2^8), đa thức sinh, cơ chế sửa lỗi Reed-Solomon và kỹ thuật kết xuất ma trận ngay trên trình duyệt.

PetexSpace
CryptographyData EncodingBase32

So sánh Base32 và Base64: Khác biệt cấu trúc, quy tắc đệm và ứng dụng mật mã học

Đặc tả kỹ thuật chuyên sâu về các chuẩn mã hóa nhị phân sang văn bản theo RFC 4648, đối chiếu cơ chế đóng gói bitwise, ma trận đệm (padding), tính công thái học của bảng chữ cái và quá trình thực thi trực tiếp trên trình duyệt giữa Base32 và Base64.

PetexSpace
CryptographyXác thựcKhóa truy cập

Passkey so với TOTP: Bước chuyển dịch mật mã học từ khóa bí mật dùng chung sang chữ ký khóa công khai

Phân tích kiến trúc và bảo mật so sánh giữa Mật khẩu một lần dựa trên thời gian RFC 6238 với Passkey FIDO2/WebAuthn, đi sâu vào khả năng chống tấn công phi kỹ thuật Adversary-in-the-Middle và ràng buộc nguồn gốc.

PetexSpace