Çfarë është UUID?
UUID-të tani janë 128 bit në madhësi, dyfishi i asaj që ishin fillimisht. Formati i përgjithshëm i një UUID është se 16 bajtë e tij përfaqësohen si vlera 32 heksadecimal (Baza 16) të ndara në pesë grupe me gjatësi përkatësisht 8, 4, 4, 4 dhe 12 (gjithsej 32 karaktere), të ndara me viza "-", që e bën një UUID të vetme 36 karaktere të gjatë, 32 karaktere heksadecimal + 4 viza.
UUID-të ndahen në grupe të ndryshme sipas Variantit dhe Versioneve të tyre. Varianti i UUID përfaqësohet në vetë UUID nga një nga karakteret heksadecimal dhe e njëjta gjë vlen edhe për versionin e UUID. Më poshtë është formati i përgjithshëm ose përfaqësimi tekstual kanonik i një UUID.
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxxx
Karakteri heksadecimal M përfaqëson versionin e UUID dhe 1 deri në 3 bitët e parë më të rëndësishëm, në formën binare, të karakterit N përfaqësojnë variantin e UUID.
Si ndryshon UUID5 nga versionet e tjera?
UUID5 krijohet duke hash së bashku një identifikues space name me një string hyrje.
- Vargu i hyrjes: Çdo varg që mund të ndryshojë në aplikacionin tuaj.
- Hapësira e emrave: Një UUID fikse e përdorur në kombinim me vargun hyrës për të bërë dallimin midis UUID-ve të krijuara në aplikacione të ndryshme dhe për të parandaluar "hakimet e tabelës së ylberit"
Këto dy pjesë të informacionit konvertohen në një UUID duke përdorur algoritmin e hashimit SHA1.
Një hash SHA1 nxjerr 160 bit (20 byte); rezultati i hash-it konvertohet në një UUID.
Me një përmbledhje 20-bajtë nga SHA1:
SHA1 Digest: 74738ff5 5367 e958 1aee 98fffdcd1876 94028007 UUID (v5): 74738ff5-5367-5958-9aee-98fffdcd1876 ⭡ ⬑first two bits set to 1 and 0, respectively ╰─low nibble is set to 5, to indicate type 5
sha1(NamespaceUUID+String Input);
Një pikë e rëndësishme për t'u theksuar është se UUID v5 është konsistent. Kjo do të thotë që çdo kombinim i dhënë i hyrjes dhe hapësirës së emrit do të rezultojë në të njëjtin UUID, çdo herë. Mund ta provoni vetë:
// Reference from SHA1 and UUID npm module // http://www.movable-type.co.uk/scripts/sha1.html function sha1(bytes) { const K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6]; const H = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]; if (typeof bytes === 'string') { const msg = unescape(encodeURIComponent(bytes)); // UTF8 escape bytes = []; for (let i = 0; i < msg.length; ++i) { bytes.push(msg.charCodeAt(i)); } } else if (!Array.isArray(bytes)) { // Convert Array-like to Array bytes = Array.prototype.slice.call(bytes); } bytes.push(0x80); const l = bytes.length / 4 + 2; const N = Math.ceil(l / 16); const M = new Array(N); for (let i = 0; i < N; ++i) { const arr = new Uint32Array(16); for (let j = 0; j < 16; ++j) { arr[j] = bytes[i * 64 + j * 4] << 24 | bytes[i * 64 + j * 4 + 1] << 16 | bytes[i * 64 + j * 4 + 2] << 8 | bytes[i * 64 + j * 4 + 3]; } M[i] = arr; } M[N - 1][14] = (bytes.length - 1) * 8 / Math.pow(2, 32); M[N - 1][14] = Math.floor(M[N - 1][14]); M[N - 1][15] = (bytes.length - 1) * 8 & 0xffffffff; for (let i = 0; i < N; ++i) { const W = new Uint32Array(80); for (let t = 0; t < 16; ++t) { W[t] = M[i][t]; } for (let t = 16; t < 80; ++t) { W[t] = ROTL(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1); } let a = H[0]; let b = H[1]; let c = H[2]; let d = H[3]; let e = H[4]; for (let t = 0; t < 80; ++t) { const s = Math.floor(t / 20); const T = ROTL(a, 5) + f(s, b, c, d) + e + K[s] + W[t] >>> 0; e = d; d = c; c = ROTL(b, 30) >>> 0; b = a; a = T; } H[0] = H[0] + a >>> 0; H[1] = H[1] + b >>> 0; H[2] = H[2] + c >>> 0; H[3] = H[3] + d >>> 0; H[4] = H[4] + e >>> 0; } return [H[0] >> 24 & 0xff, H[0] >> 16 & 0xff, H[0] >> 8 & 0xff, H[0] & 0xff, H[1] >> 24 & 0xff, H[1] >> 16 & 0xff, H[1] >> 8 & 0xff, H[1] & 0xff, H[2] >> 24 & 0xff, H[2] >> 16 & 0xff, H[2] >> 8 & 0xff, H[2] & 0xff, H[3] >> 24 & 0xff, H[3] >> 16 & 0xff, H[3] >> 8 & 0xff, H[3] & 0xff, H[4] >> 24 & 0xff, H[4] >> 16 & 0xff, H[4] >> 8 & 0xff, H[4] & 0xff]; } function f(s, x, y, z) { switch (s) { case 0: return x & y ^ ~x & z; case 1: return x ^ y ^ z; case 2: return x & y ^ x & z ^ y & z; case 3: return x ^ y ^ z; } } function ROTL(x, n) { return x << n | x >>> 32 - n; } const uuidRegex = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; function validateUUID(uuid) { return (typeof uuid === 'string' && uuidRegex.test(uuid)); } function parse(uuid) { if (!validateUUID(uuid)) { throw TypeError('Invalid UUID'); } let v; const arr = new Uint8Array(16); // Parse ########-....-....-....-............ arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; arr[1] = v >>> 16 & 0xff; arr[2] = v >>> 8 & 0xff; arr[3] = v & 0xff; // Parse ........-####-....-....-............ arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; arr[5] = v & 0xff; // Parse ........-....-####-....-............ arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; arr[7] = v & 0xff; // Parse ........-....-....-####-............ arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; arr[9] = v & 0xff; // Parse ........-....-....-....-############ // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; arr[11] = v / 0x100000000 & 0xff; arr[12] = v >>> 24 & 0xff; arr[13] = v >>> 16 & 0xff; arr[14] = v >>> 8 & 0xff; arr[15] = v & 0xff; return arr; } const byteToHex = []; for (let i = 0; i < 256; ++i) { byteToHex.push((i + 0x100).toString(16).slice(1)); } function byteToString(arr, offset = 0) { return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); } function stringToBytes(str) { str = unescape(encodeURIComponent(str)); // UTF8 escape const bytes = []; for (let i = 0; i < str.length; ++i) { bytes.push(str.charCodeAt(i)); } return bytes; } function generateUUID5(value, namespace, buf, offset) { var _namespace; if (typeof value === 'string') { value = stringToBytes(value); } if (typeof namespace === 'string') { namespace = parse(namespace); } if (((_namespace = namespace) === null || _namespace === void 0 ? void 0 : _namespace.length) !== 16) { throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); } let bytes = new Uint8Array(16 + value.length); bytes.set(namespace); bytes.set(value, namespace.length); bytes = sha1(bytes); bytes[6] = bytes[6] & 0x0f | 0x50; bytes[8] = bytes[8] & 0x3f | 0x80; if (buf) { offset = offset || 0; for (let i = 0; i < 16; ++i) { buf[offset + i] = bytes[i]; } return buf; } return byteToString(bytes); }
Ju mund të jepni "vlerë" do të jetë çdo varg ex: ju mund të jepni edhe emrin e domenit tuaj këtu. "Hapësira e emrit" do të fiksohet uuid.
generateUUID5("www.google.com", "e95055fe-5034-5b8d-ab3d-62ea74997e21") // will give you // "de0a6373-7879-5d60-a3b4-a74c1c74d993" => hasing of "www.google.com" with "e95055fe-5034-5b8d-ab3d-62ea74997e21"
Përfundim
UUID v5 zakonisht përdoret vetëm për raste përdorimi shumë specifik kur dëshironi të nxirrni një UUID nga një pjesë tjetër e informacionit në fluturim. Ju lutemi rishikoni rastin tuaj të përdorimit kur jeni në lidhje me përdorimin e UUID5.
Gëzuar kodimin :)