Tạo UUID

Tạo ngay một UUID v4 ngẫu nhiên hoặc một UUID v7 sắp xếp theo thời gian, hoặc tới 10.000 UUID cùng lúc. Đây cũng là công cụ tạo GUID online: một GUID mới chính là cùng loại giá trị 128 bit đó. Dán bất kỳ UUID nào để giải mã phiên bản, thời điểm tạo và từng trường của nó.

RFC 9562 · crypto.getRandomValues · tạo và đọc ngay trong trình duyệt của bạn, không gửi gì đi

Chữ số tô màu là phiên bản: chữ số đầu tiên của nhóm thứ ba trong mọi UUID.

v4 · Ngẫu nhiên36 ký tự · 122 bit ngẫu nhiên
xxxxxxxx-xxxx-4xxx-Nxxx-xxxxxxxxxxxx
Cấu trúc · RFC 9562 §5.4128 bit · 32 chữ số hex · 36 ký tự
Di chuột hoặc chạm vào một trường để đọc

Tạo và đọc ngay trong trình duyệt của bạn bằng crypto.getRandomValues; không gửi gì đi.

Định dạng

UUID là gì, và UUID là viết tắt của từ gì?

UUID là viết tắt của Universally Unique Identifier (mã định danh duy nhất phổ quát): một nhãn 128 bit mà bất kỳ máy tính nào cũng tự tạo được, mà vẫn có thể tin rằng không máy nào khác tạo ra đúng nhãn đó. Nó được viết thành 32 chữ số thập lục phân chia làm năm nhóm, ví dụ 919108f7-52d1-4320-9bac-f847db4148a8.

Định dạng này được định nghĩa trong RFC 9562 (tháng 5 năm 2024), văn bản thay thế RFC 4122 và bổ sung các phiên bản 6, 7 và 8. Không có cơ quan đăng ký trung tâm nào cấp phát UUID: tính duy nhất đến từ sự ngẫu nhiên, từ dấu thời gian hoặc từ việc băm một cái tên, tùy theo phiên bản.

Cơ sở dữ liệu dùng UUID làm khóa chính, API dùng làm ID cho yêu cầu và đối tượng, hệ điều hành dùng cho ổ đĩa, phân vùng và thành phần phần mềm. GUID (Globally Unique Identifier, mã định danh duy nhất toàn cầu) là tên Microsoft đặt cho chính thứ này.

Một giá trị, bốn cách đoRFC 9562 §4

UniversallyUniqueIDentifier

  1. 128 bit
  2. 16 byte
  3. 32 chữ số hex
  4. 36 ký tự kể cả dấu gạch ngang919108f7-52d1-4320-9bac-f847db4148a8

GUIDTên Microsoft đặt cho cùng giá trị này

Ví dụ phiên bản 4 của RFC 9562, đếm theo bốn cách. Dạng văn bản thêm bốn dấu gạch ngang vào 32 chữ số hex: 36 ký tự.
Tạo UUID: một UUID v7 với dấu thời gian, phiên bản và các bit ngẫu nhiên được đánh dấu từng trường, cùng một loạt UUID v7Tạo UUID: một UUID v7 với dấu thời gian, phiên bản và các bit ngẫu nhiên được đánh dấu từng trường, cùng một loạt UUID v7Chọn phiên bảnv4 ngẫu nhiên, v7 theo thời gian, v5 dựa trên tên và các phiên bản khác, mỗi loại một màu riêng.Một cú nhấpSao chép, hoặc tạo cái mới; một loạt tới 10.000 UUID được xuất ra dạng văn bản, CSV, JSON hoặc SQL.Từng trườngCác bit mà RFC 9562 định nghĩa cho phiên bản này, kèm thời gian đọc ra từ một UUID v7.Mọi định dạngNgoặc nhọn, không gạch ngang, chữ hoa, Base64url, số nguyên hoặc thứ tự byte của .NET.
Một UUID v7 được tách ra từng phần: dấu thời gian 48 bit, chữ số phiên bản, các bit biến thể và phần ngẫu nhiên. Chọn một số để xem từng phần thể hiện điều gì.

Định dạng và độ dài UUID: 36 ký tự

Một UUID dài 128 bit, được viết thành 32 chữ số hex và 4 dấu gạch ngang theo các nhóm 8, 4, 4, 4 và 12: tổng cộng 36 ký tự. Chữ số đầu tiên của nhóm thứ ba là phiên bản, còn chữ số đầu tiên của nhóm thứ tư cho biết biến thể (variant): 8, 9, a hoặc b với UUID theo RFC 9562.

Vậy 017f22e2-79b0-7cc3-98c4-dc0c0c07398f là phiên bản 7, biến thể RFC. Chữ hoa, chữ thường hay lẫn cả hai đều hợp lệ; phần lớn công cụ in chữ thường, còn uuidgen của macOS in chữ hoa. Không có dấu gạch ngang, UUID dài 32 ký tự; trong ngoặc nhọn là 38 (định dạng B của .NET), ở dạng urn:uuid: là 45, và ở dạng Base64url là 22.

Biểu thức chính quy (regex) kiểm tra dạng chuẩn RFC: ^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ kèm cờ không phân biệt hoa thường. Nó từ chối UUID Nil và UUID Max, hai giá trị hợp lệ nhưng đặc biệt; bộ giải mã ở trên gọi đúng tên chúng.

Dạng văn bảnRFC 9562 §4
017f22e28-79b04-7cc34-98c44-dc0c0c07398f12

32 chữ số hex + 4 dấu gạch ngang = 36 ký tự

xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxxM phiên bản: 1–8N biến thể: 8, 9, a hoặc b
Regex · không phân biệt hoa thường^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
Cùng 128 bit, viết theo cách khác
  • Chuẩn017f22e2-79b0-7cc3-98c4-dc0c0c07398f36
  • Không gạch ngang017f22e279b07cc398c4dc0c0c07398f32
  • Ngoặc nhọn {…}{017f22e2-79b0-7cc3-98c4-dc0c0c07398f}38
  • urn:uuid:urn:uuid:017f22e2-79b0-7cc3-98c4-dc0c0c07398f45
  • Base64urlAX8i4nmwfMOYxNwMDAc5jw22
  • Base64AX8i4nmwfMOYxNwMDAc5jw==24
  • Base58BihbxwwQ4NZZpKRH9JDCz21
  • Base3201FWHE4YDGFK1SHH6W1G60EECF26
  • Số nguyên1989357241971137676463954034883508623tối đa 39
  • Nhị phân01 7f 22 e2 79 b0 7c c3 98 c4 dc 0c 0c 07 39 8f16 byte
Ví dụ v7 của chính RFC 9562 ở từng dạng viết. Regex cố ý từ chối UUID Nil và UUID Max: chúng không có phiên bản.

Các phiên bản UUID: từ v1 đến v8

Phiên bản cho biết UUID được tạo ra như thế nào: v4 từ các bit ngẫu nhiên, v7 từ thời gian cộng các bit ngẫu nhiên, v1 và v6 từ dấu thời gian và một node ID, v3 và v5 bằng cách băm một cái tên, còn v8 theo bố cục riêng của bên tạo ra nó.

Phiên bản 2 và 0 không được tạo ở đây: v2 (DCE Security) chỉ được giữ chỗ và RFC 9562 không định nghĩa bố cục của nó, còn 0 không phải là một phiên bản. Hai giá trị đặc biệt không có phiên bản: UUID Nil toàn bit 0 và UUID Max toàn bit 1 (ffffffff-ffff-ffff-ffff-ffffffffffff, mới có từ RFC 9562).

Với hệ thống mới, RFC 9562 khuyến nghị dùng v7 thay cho v1 và v6, và v5 thay cho v3. v4 vẫn là lựa chọn đơn giản khi giá trị không nên tiết lộ gì về thời điểm nó được tạo.

Phiên bản128 bit của nóTạo từSắp theo thời gian
v1Thời gian + node · §5.1Thời gian (100 ns) + chuỗi đồng hồ + nodeKhông
v2DCE Security: chỉ giữ chỗ, RFC 9562 không có bố cụcKhông được tạo: chưa có bố cục–
v3Tên · MD5 · §5.3MD5 của namespace + tênKhông
v4Ngẫu nhiên · §5.4Bit ngẫu nhiênKhông
v5Tên · SHA-1 · §5.5SHA-1 của namespace + tênKhông
v6v1 sắp xếp được · §5.6Các trường của v1, bit cao của thời gian đứng trướcCó
v7Theo thời gian · §5.7Thời gian Unix (ms) + bit ngẫu nhiênCó
v8Tùy chỉnh · §5.8Bố cục riêng của bên tạoKhông
Nil§5.9Toàn bit 0: “không có giá trị”–
Max§5.10Toàn bit 1: giá trị đánh dấu–
  • thời gian
  • ngẫu nhiên
  • băm
  • chuỗi đồng hồ
  • node ID
  • phiên bản
  • biến thể
Mỗi thanh là 128 bit của một phiên bản theo bố cục của RFC 9562, lấy từ chính các vector kiểm thử của nó. Chỉ v6 và v7 đặt thời gian lên đầu, nên chỉ chúng sắp theo thời gian khi ở dạng văn bản.

UUID v4 và UUID v7: nên dùng loại nào?

Hãy dùng v7 cho khóa cơ sở dữ liệu và mọi thứ bạn sắp xếp hoặc đánh chỉ mục: nó bắt đầu bằng thời điểm tạo, nên các dòng mới nằm ở cuối chỉ mục. Hãy dùng v4 khi ID không được để lộ thời điểm tạo: cả 122 bit tự do của nó đều ngẫu nhiên.

Khóa v4 ngẫu nhiên rải mỗi lần chèn ra khắp chỉ mục B-tree, làm các trang bị tách và buộc nhiều phần hơn của chỉ mục phải luôn nằm trong bộ nhớ; khóa v7 đến theo thứ tự như một số tự tăng (auto-increment), nhưng máy chủ nào cũng tạo được mà không cần hỏi cơ sở dữ liệu. Một UUID v7 giữ 74 bit ngẫu nhiên cho mỗi mili giây, nên hai máy chủ cùng tạo một UUID trong cùng một khoảnh khắc vẫn không bị trùng.

Cái giá phải trả: ai nhìn thấy một UUID v7 cũng đọc được mili giây nó được tạo (hãy dán một UUID vào bộ giải mã ở trên để xem). Nếu điều đó quan trọng, hãy dùng v4, hoặc chỉ dùng v7 trong nội bộ và hiển thị một ID khác ra bên ngoài.

12 lần chèn vào chỉ mục B-tree8 trang lá · mỗi trang 16 khóa
khóa v4 rơi vào bất cứ đâu7 trên 8 trang được ghi vào · 3 lần tách trang
Trang theo byte đầu tiên
00–1ftách
20–3f
40–5f
60–7f
80–9f
a0–bf
c0–dftách
e0–fftách
c100eb4b-4f3f-4b29-ad77-da7cd9d1eda592c97333-2db8-4fc2-b5b6-cedd8c7abede
khóa v7 rơi vào cuối1 trên 8 trang được ghi vào · 0 lần tách trang
Trang theo ngày tạo khóa
17 thg 10
18 thg 10
19 thg 10
20 thg 10
21 thg 10
22 thg 10
23 thg 10
24 thg 10
01a16d3e-e1c0-70f6-99ec-6d454991b2fa01a16d3e-e1c0-70f6-99ec-6d45c2f6b35b
  • đã có trong chỉ mục
  • trống
  • v4 mới
  • v7 mới
  • tách trang: một nửa số khóa chuyển sang trang mới
Một mô hình, không phải phép đo hiệu năng: mỗi trang lá chứa 16 khóa. Khóa ngẫu nhiên rơi vào các trang cũ gần đầy và làm chúng bị tách; các byte đầu của v7 là thời gian, nên cả mười hai khóa đều vào trang mới nhất, nơi vẫn còn chỗ.

GUID là gì, và GUID có khác UUID không?

GUID và UUID là cùng một giá trị 128 bit với cùng một dạng văn bản; GUID là tên Microsoft đặt cho nó. Guid.NewGuid() trong .NET tạo một UUID phiên bản 4 ngẫu nhiên, còn Guid.CreateVersion7() của .NET 9 tạo một UUID phiên bản 7.

Khác biệt nằm ở bộ nhớ. Cấu trúc GUID của Microsoft lưu ba nhóm đầu dưới dạng số nguyên little-endian, nên ToByteArray() của .NET trả về 8 byte đầu theo thứ tự khác với thứ tự byte mạng (network byte order) của RFC 9562: 919108f7-52d1-… trở thành các byte f7 08 91 91 d1 52 …. Văn bản giống hệt nhau; byte thô chuyển giữa các hệ thống thì cần được chuyển đổi. Bộ giải mã hiển thị cả hai thứ tự.

uniqueidentifier của SQL Server còn sắp xếp theo sáu byte cuối trước, nên giá trị v7 không giữ được thứ tự thời gian ở đó; NEWSEQUENTIALID() tạo ra các giá trị giữ được thứ tự, dù chúng có thể bắt đầu lại từ giá trị thấp hơn sau khi khởi động lại và rất dễ đoán. GUID COM cũ có thể mang các bit biến thể riêng của Microsoft thay vì của RFC 9562; bộ giải mã gọi đúng tên biến thể đó.

Một GUID, ba thứ tự byte16 byte
919108f7-52d1-4320-9bac-f847db4148a8
RFC 9562 thứ tự mạng
.NET Guid.ToByteArray()
SQL Server thứ tự uniqueidentifierSáu byte cuối quyết định thứ tự
  • Data1 · 4 byte, đảo ngược
  • Data2 · đảo ngược
  • Data3 · đảo ngược
  • Data4 · giữ nguyên
Cùng một văn bản trong bộ nhớ: .NET lưu ba nhóm đầu theo little-endian, còn SQL Server sắp xếp theo sáu byte cuối trước, nên khóa v7 sắp theo thời gian không giữ được thứ tự ở đó.

Cách tạo UUID trong code

Hầu hết các ngôn ngữ tạo được UUID v4 chỉ với một dòng, và nhiều ngôn ngữ nay đã tạo được cả v7: uuid.uuid7() của Python 3.14, Guid.CreateVersion7() của .NET 9, UUID.ofEpochMillis() của Java 26, uuid.NewV7() của Go 1.27, crypto.randomUUIDv7() của Node.js 26.1 và uuidv7() của PostgreSQL 18. Trình duyệt vẫn chỉ có crypto.randomUUID(), hàm tạo v4.

Chọn ngôn ngữ của bạn để xem câu lệnh một dòng. Không phải v7 nào cũng giữ thứ tự cho các UUID tạo trong cùng một mili giây: của Python và Go thì có, còn của .NET và Node thì không cam kết. Ngoài ra, UUID() của MySQL trả về UUID phiên bản 1, loại mà trên Linux và Windows mang địa chỉ MAC thật của máy chủ.

Hàm UUID có sẵn trong từng ngôn ngữ

Python
import uuid

uuid.uuid4()   # v4
uuid.uuid7()   # v7, Python 3.14+
uuid.uuid5(uuid.NAMESPACE_DNS, "www.example.com")  # v5

uuid7() giữ một bộ đếm 42 bit, nên các UUID trong cùng một mili giây vẫn đúng thứ tự.

Các phiên bản theo tài liệu chính thức của từng ngôn ngữ; logo là logo của chính các dự án.

Hai UUID có thể trùng nhau không?

Về lý thuyết là có, trên thực tế là không: một UUID v4 có 122 bit ngẫu nhiên, khoảng 5,3 × 10³⁶ giá trị. Bạn sẽ phải tạo khoảng 103 nghìn tỷ UUID mới có xác suất một phần tỷ để hai cái bất kỳ trùng nhau, và khoảng 2,7 tỷ tỷ (2,7 × 10¹⁸) UUID mới có xác suất 50%.

Đó là cận ngày sinh (birthday bound): với n giá trị ngẫu nhiên trong N giá trị có thể, xác suất có một lần lặp lại xấp xỉ 1 − e^(−n(n−1)/2N). Nếu tạo một tỷ UUID mỗi giây, phải mất khoảng 86 năm mới đạt xác suất 50%. Trùng lặp thực tế đến từ các bộ tạo bị lỗi: seed không ngẫu nhiên, máy ảo được nhân bản cùng trạng thái ngẫu nhiên của nó, hoặc ID bị sao chép thủ công.

Với v7, chỉ những UUID tạo trong cùng một mili giây mới có thể trùng, và 74 bit ngẫu nhiên phân biệt chúng. Bộ tạo ở đây còn giữ một loạt UUID theo đúng thứ tự ngay trong cùng một mili giây (RFC 9562 §6.2), nên 10.000 UUID tạo cùng lúc vừa duy nhất vừa được sắp xếp.

Cận ngày sinhchúng tôi tự tính
Xác suất có hai cái trùng nhau1 trên 1,1 × 1019p ≈ 9,4 × 10−20

Với tốc độ một tỷ UUID mỗi giây, tạo được ngần ấy cần 1 giây.

p ≈ 1 − e^(−n(n−1)/2N), với N = 2¹²² cho v4 và 2⁷⁴ mỗi mili giây cho v7. RFC 9562 không đưa ra số liệu về trùng lặp: đây là con số của chúng tôi, từ chính hàm mà trang này dùng.

Giải mã UUID: cách đọc dấu thời gian của một UUID

Dán một UUID vào Giải mã & kiểm tra, bộ giải mã và kiểm tra UUID ở trên: nó đọc phiên bản và biến thể từ hai vị trí cố định, rồi đọc các trường mà phiên bản đó định nghĩa. UUID v7 cho biết mili giây nó được tạo, còn v1 hoặc v6 cho biết thời gian chính xác đến 100 nano giây, cùng một chuỗi đồng hồ (clock sequence) và một node ID.

Node của v1 hoặc v6 có bit multicast bằng 0 có thể là địa chỉ MAC thật của card mạng; hãy tra nhà sản xuất của nó bằng tra cứu địa chỉ MAC. Các bộ tạo tôn trọng quyền riêng tư sẽ bật bit đó và dùng node ngẫu nhiên, như bộ tạo này.

Thời gian là thứ bộ tạo đã ghi vào, không phải bằng chứng về thời điểm UUID được tạo. v4 không chứa thời gian, chỉ có bit ngẫu nhiên, còn v3, v5 và v8 chứa giá trị băm: không có gì để đọc ngược lại, và giá trị băm không thể đảo ngược ra tên ban đầu. Dán một danh sách để kiểm tra tới 1.000 UUID cùng lúc: dòng không hợp lệ, UUID trùng lặp và các UUID dựa trên thời gian có đúng thứ tự hay không.

Hai cách ghi cùng một thời điểmRFC 9562 · Appendix A
017f22e2-79b0-7cc3-98c4-dc0c0c07398f
  1. unix_ts_ms0x017f22e279b0
  2. ms kể từ 19701 645 557 742 000
  3. UTC2022-02-22T19:22:22.000Z
c232ab00-9414-11ec-b3c8-9f6bdeced846
  1. time_high · time_mid · time_low1ec 9414 c232ab00
  2. bước 100 ns kể từ 1582-10-15138 648 505 420 000 000
  3. UTC2022-02-22T19:22:22.0000000Z

Cùng một thời điểm: các ví dụ của RFC 9562 được tạo cùng lúc.

UUID v7 bắt đầu bằng số mili giây kể từ 1970. UUID v1 lưu phần thấp của thời gian trước, nên bộ giải mã xếp lại ba phần theo đúng thứ tự trước khi đếm từ ngày 15 tháng 10 năm 1582.

UUID dựa trên tên: v5 và v3

UUID v5 là giá trị băm SHA-1 của một UUID namespace (không gian tên) cộng với một tên, cắt còn 128 bit rồi đặt các bit phiên bản và biến thể; v3 làm tương tự với MD5. Cùng namespace và cùng tên luôn cho ra cùng một UUID, trên bất kỳ máy tính nào: chọn v5 ở trên để dùng trang này như một công cụ tạo UUID v5.

RFC 9562 định nghĩa bốn namespace: DNS cho tên miền, URL, OID và X.500. Vì vậy www.example.com trong namespace DNS luôn là 2ed6657d-e927-568b-95e1-2665a8aea6a2 ở dạng v5. Hãy dùng UUID dựa trên tên để cấp một ID ổn định cho thứ vốn đã có tên duy nhất, mà không cần lưu bảng ánh xạ.

Hãy chọn v5 thay vì v3: MD5 yếu hơn, và RFC 9562 khuyến nghị v5. Cả hai đều không phải là cách để giấu tên: ai đoán được tên cũng tính ra được đúng UUID đó. Tùy chọn v8 ở đây dùng SHA-256 theo cùng cách, như ví dụ v8 trong chính RFC.

Namespace + tên → v5RFC 9562 §5.5
  1. Namespace6ba7b810-9dad-11d1-80b4-00c04fd430c8DNS · 16 byte
  2. Tên"www.example.com"UTF-8 · 15 byte
  3. Giá trị băm SHA-1, 160 bit2ed6657de927468b55e12665a8aea6a22dee3e35giữ lại 128 bit đầu
  4. UUID kết quả2ed6657d-e927-568b-95e1-2665a8aea6a2chữ số phiên bản 4 → 5 · chữ số biến thể 5 → 9
  • DNS6ba7b810…
  • URL6ba7b811…
  • OID6ba7b812…
  • X.5006ba7b814…
Ví dụ v5 của chính RFC 9562: www.example.com trong namespace DNS. Bất kỳ máy tính nào băm cùng namespace và cùng tên đều nhận được cùng một UUID.

ULID và UUID v7 (cùng các loại ID khác)

ULID và UUID v7 đều bắt đầu bằng dấu thời gian mili giây 48 bit và sắp xếp được theo thời gian. Khác biệt: ULID dùng toàn bộ 80 bit còn lại cho phần ngẫu nhiên và được viết thành 26 ký tự Base32, còn v7 dành 6 bit cho phiên bản và biến thể, và vừa với mọi cột và thư viện UUID.

Nếu cơ sở dữ liệu, ORM hoặc API của bạn đã dùng UUID, v7 cho bạn thứ tự thời gian mà không cần một kiểu dữ liệu mới. NanoID và các ID ngắn tương tự là chuỗi ngẫu nhiên có độ dài tùy chọn, không có thời gian và không có bố cục chuẩn. Mọi UUID cũng có thể được viết ngắn hơn: 22 ký tự ở dạng Base64url, tối đa 22 ở dạng Base58.

Ba loại ID, mỗi loại 128 bitđúng tỷ lệ
UUID v7thời gian, rồi ngẫu nhiên
36 ký tựsắp theo thời gian
ULIDthời gian, rồi ngẫu nhiên
26 ký tựsắp theo thời gian
UUID v4chỉ ngẫu nhiên
36 ký tựkhông có thứ tự
  • mili giây kể từ 1970
  • ngẫu nhiên
  • phiên bản và biến thể
UUID v7 và ULID dùng chung đồng hồ mili giây 48 bit; v7 dành 6 bit cho phiên bản và biến thể, ULID dùng cả 80 bit cho phần ngẫu nhiên. UUID v4 chỉ có phần ngẫu nhiên; ở dạng Base64url, UUID nào cũng dài 22 ký tự.

Dùng UUID làm token có an toàn không?

Không. RFC 9562 nói không được cho rằng UUID khó đoán, và không bao giờ được dùng UUID như một quyền truy cập bảo mật (security capability): một ID mà ai nắm giữ cũng được cấp quyền truy cập, như liên kết đặt lại mật khẩu hay khóa API.

Một UUID v4 từ bộ tạo tốt là ngẫu nhiên, nhưng v1, v6 hoặc v7 để lộ thời điểm tạo, còn v3 hoặc v5 có thể được tính lại từ tên của nó. Với dữ liệu bí mật, hãy dùng token được tạo cho mục đích đó, chẳng hạn 256 bit ngẫu nhiên từ một bộ tạo số ngẫu nhiên mật mã, và kiểm tra quyền trên mọi yêu cầu. UUID vẫn ổn khi làm ID công khai nếu quyền truy cập được kiểm tra riêng.

IDĐiều mà ai nhìn thấy cũng biết đượcDùng làm bí mật
v1, v6Thời điểm tạo, và có thể cả địa chỉ MAC của card mạngKhông
v7Mili giây nó được tạoKhông
v5, v3Không có gì mới, nhưng đoán được tên là ra cùng UUIDKhông
v4Không có gì, nếu bộ tạo tốtKhông
Token 256 bitKhông có gì: được tạo cho dữ liệu bí mậtCó
RFC 9562 nói không được cho rằng UUID khó đoán, cũng không được dùng chúng như quyền truy cập bảo mật. Hãy dùng token từ bộ tạo số ngẫu nhiên mật mã cho dữ liệu bí mật và kiểm tra quyền truy cập trên mọi yêu cầu.

Tạo UUID: hỏi và đáp

Làm thế nào để tạo UUID?

Mở trang này: một UUID v4 ngẫu nhiên đã sẵn sàng để sao chép, và nút UUID mới tạo thêm một cái khác. Chọn v7 để dùng trang như công cụ tạo UUID v7, đặt số lượng để tạo tới 10.000 UUID cùng lúc, và chọn định dạng như ngoặc nhọn hoặc Base64url. Trong code, crypto.randomUUID() trong JavaScript, uuid.uuid4() trong Python và Guid.NewGuid() trong C# đều tạo một UUID v4 chỉ với một dòng.

UUID là viết tắt của từ gì?

Universally Unique Identifier, tức mã định danh duy nhất phổ quát. Đó là một giá trị 128 bit, viết thành 36 ký tự như 919108f7-52d1-4320-9bac-f847db4148a8, do các máy tính tự tạo độc lập mà không cần cơ quan đăng ký trung tâm nhưng vẫn có thể coi là duy nhất. RFC 9562 định nghĩa nó. Microsoft gọi cùng giá trị này là GUID, Globally Unique Identifier (mã định danh duy nhất toàn cầu).

GUID có giống UUID không?

Có, về mặt thực tế: cùng 128 bit và cùng dạng văn bản, và Guid.NewGuid() tạo một UUID phiên bản 4 chuẩn. Có hai chi tiết khác nhau. .NET lưu ba nhóm đầu theo little-endian, nên mảng byte thô ra theo thứ tự khác, và SQL Server sắp xếp giá trị uniqueidentifier theo nhóm cuối trước. Để tạo GUID, hãy dùng trang này như một công cụ tạo GUID ngẫu nhiên: văn bản bạn sao chép dùng được ở cả hai nơi.

Nên dùng phiên bản UUID nào?

Phiên bản 7 cho khóa cơ sở dữ liệu và mọi thứ cần sắp xếp, vì nó bắt đầu bằng thời điểm tạo và giữ chỉ mục gọn gàng. Phiên bản 4 khi ID không nên để lộ thời điểm tạo. Phiên bản 5 khi cùng một tên phải luôn ứng với cùng một ID. Tránh v1 cho dự án mới: RFC 9562 khuyến nghị dùng v7 thay thế, và v1 có thể mang một địa chỉ MAC thật.

Hai UUID có bao giờ trùng nhau không?

Chỉ với một xác suất cực kỳ nhỏ khi bộ tạo hoạt động đúng. Một UUID v4 có 122 bit ngẫu nhiên, nên khoảng 103 nghìn tỷ UUID cho xác suất một phần tỷ có một lần trùng, và xác suất 50% cần khoảng 2,7 tỷ tỷ UUID. Trùng lặp ngoài thực tế đến từ bộ tạo bị lỗi, máy ảo được nhân bản hoặc dữ liệu bị sao chép, không phải từ toán học.

Có giải mã được UUID không?

Được một phần. UUID nào cũng cho biết phiên bản và biến thể của nó. UUID v7 còn để lộ mili giây nó được tạo, còn v1 hoặc v6 cho biết thời gian chính xác đến 100 nano giây, một chuỗi đồng hồ và một node ID, đôi khi là một địa chỉ MAC thật. v4 chỉ chứa bit ngẫu nhiên, còn v3 và v5 chứa giá trị băm không thể đảo ngược ra tên ban đầu. Hãy dán một UUID vào mục Giải mã & kiểm tra.

Độ dài của UUID là bao nhiêu?

128 bit, tức 16 byte. Ở dạng văn bản, UUID dài 36 ký tự: 32 chữ số thập lục phân và 4 dấu gạch ngang theo các nhóm 8-4-4-4-12. Không có dấu gạch ngang thì dài 32 ký tự, trong ngoặc nhọn là 38, có tiền tố urn:uuid: là 45, ở dạng Base64url là 22 và ở dạng số nguyên thập phân là tối đa 39 chữ số. Khi có thể, hãy lưu nó bằng kiểu UUID gốc hoặc 16 byte thay vì văn bản.

GUID rỗng hay UUID Nil là gì?

Đó là giá trị có toàn bộ 128 bit bằng 0: 00000000-0000-0000-0000-000000000000. RFC 9562 gọi nó là UUID Nil, và Guid.Empty của .NET cũng chính là giá trị này, thường dùng để chỉ chưa đặt ID. RFC 9562 còn định nghĩa UUID Max, toàn bit 1, ffffffff-ffff-ffff-ffff-ffffffffffff, làm giá trị đánh dấu hay sentinel (.NET 9: Guid.AllBitsSet). Cả hai đều không ngẫu nhiên, nên đừng bao giờ dùng chúng làm ID thật.

UUID v7 có sắp xếp được không?

Có. 48 bit đầu của nó là thời gian Unix tính bằng mili giây, nên sắp xếp UUID v7 dưới dạng văn bản hay dạng byte đều sắp chúng theo thời điểm tạo, chính xác đến mili giây. Trong cùng một mili giây, thứ tự phụ thuộc vào bộ tạo: bộ tạo này giữ một loạt UUID tăng nghiêm ngặt, như RFC 9562 mục 6.2 mô tả. uniqueidentifier của SQL Server là ngoại lệ: nó so sánh nhóm cuối trước.

Dùng UUID làm mật khẩu hoặc access token có an toàn không?

Không. RFC 9562 cảnh báo không được cho rằng UUID khó đoán, cũng không được dùng chúng như quyền truy cập bảo mật. Các phiên bản dựa trên thời gian để lộ thời điểm tạo, còn các phiên bản dựa trên tên có thể được tính lại. Hãy dùng token ngẫu nhiên từ bộ tạo số ngẫu nhiên mật mã cho dữ liệu bí mật, và coi UUID là ID công khai, với quyền truy cập được kiểm tra riêng. Với mật khẩu, hãy dùng trình tạo mật khẩu.

UUID tạo ở đây có bị gửi đi đâu không?

Không. Chúng được tạo trong trình duyệt của bạn bằng crypto.getRandomValues, bộ tạo số ngẫu nhiên an toàn về mặt mật mã của trình duyệt, và UUID bạn dán vào được giải mã ngay trên thiết bị của bạn. Không có gì bạn tạo hay dán bị gửi cho chúng tôi hay bất kỳ ai khác. Liên kết chia sẻ chỉ chứa những gì bạn đã chọn: phiên bản, số lượng và định dạng, tên dùng cho v5, hoặc các UUID bạn đã dán vào bộ giải mã, nên hãy chia sẻ nó như cách bạn chia sẻ chính những thứ đó.

Còn thiếu điều gì?Đề xuất tính năng hoặc công cụ mới