From 3aa232a894340ea13d2fc57090c8ad149f5c482a Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Sat, 22 Jun 2024 13:04:21 -0400 Subject: [PATCH] Move v3 and v5 UUID procs to `uuid/legacy` --- core/encoding/uuid/generation.odin | 135 ----------------- core/encoding/uuid/legacy/legacy.odin | 150 +++++++++++++++++++ examples/all/all_main.odin | 2 + tests/core/encoding/uuid/test_core_uuid.odin | 11 +- 4 files changed, 158 insertions(+), 140 deletions(-) create mode 100644 core/encoding/uuid/legacy/legacy.odin diff --git a/core/encoding/uuid/generation.odin b/core/encoding/uuid/generation.odin index 08fd84c0c..2ca5d0e5f 100644 --- a/core/encoding/uuid/generation.odin +++ b/core/encoding/uuid/generation.odin @@ -1,7 +1,5 @@ package uuid -import "core:crypto/legacy/md5" -import "core:crypto/legacy/sha1" import "core:math/rand" import "core:mem" import "core:time" @@ -50,71 +48,6 @@ generate_v1 :: proc(clock_seq: u16, node: Maybe([6]u8) = nil) -> (result: Identi return } -/* -Generate a version 3 UUID. - -This UUID is generated from a name within a namespace. -MD5 is used to hash the name with the namespace to produce the UUID. - -Inputs: -- namespace: Another `Identifier` that is used to represent the underlying namespace. - This can be any one of the `Namespace_*` values provided in this package. -- name: The byte slice used to generate the name on top of the namespace. - -Returns: -- result: The generated UUID. -*/ -generate_v3_bytes :: proc( - namespace: Identifier, - name: []byte, -) -> ( - result: Identifier, -) { - namespace := namespace - - ctx: md5.Context - md5.init(&ctx) - md5.update(&ctx, namespace[:]) - md5.update(&ctx, name) - md5.final(&ctx, result[:]) - - result[VERSION_BYTE_INDEX] &= 0x0F - result[VERSION_BYTE_INDEX] |= 0x30 - - result[VARIANT_BYTE_INDEX] &= 0x3F - result[VARIANT_BYTE_INDEX] |= 0x80 - - return -} - -/* -Generate a version 3 UUID. - -This UUID is generated from a name within a namespace. -MD5 is used to hash the name with the namespace to produce the UUID. - -Inputs: -- namespace: Another `Identifier` that is used to represent the underlying namespace. - This can be any one of the `Namespace_*` values provided in this package. -- name: The string used to generate the name on top of the namespace. - -Returns: -- result: The generated UUID. -*/ -generate_v3_string :: proc( - namespace: Identifier, - name: string, -) -> ( - result: Identifier, -) { - return generate_v3_bytes(namespace, transmute([]byte)name) -} - -generate_v3 :: proc { - generate_v3_bytes, - generate_v3_string, -} - /* Generate a version 4 UUID. @@ -136,74 +69,6 @@ generate_v4 :: proc() -> (result: Identifier) { return } -/* -Generate a version 5 UUID. - -This UUID is generated from a name within a namespace. -SHA1 is used to hash the name with the namespace to produce the UUID. - -Inputs: -- namespace: Another `Identifier` that is used to represent the underlying namespace. - This can be any one of the `Namespace_*` values provided in this package. -- name: The byte slice used to generate the name on top of the namespace. - -Returns: -- result: The generated UUID. -*/ -generate_v5_bytes :: proc( - namespace: Identifier, - name: []byte, -) -> ( - result: Identifier, -) { - namespace := namespace - digest: [sha1.DIGEST_SIZE]byte - - ctx: sha1.Context - sha1.init(&ctx) - sha1.update(&ctx, namespace[:]) - sha1.update(&ctx, name) - sha1.final(&ctx, digest[:]) - - mem.copy_non_overlapping(&result, &digest, 16) - - result[VERSION_BYTE_INDEX] &= 0x0F - result[VERSION_BYTE_INDEX] |= 0x50 - - result[VARIANT_BYTE_INDEX] &= 0x3F - result[VARIANT_BYTE_INDEX] |= 0x80 - - return -} - -/* -Generate a version 5 UUID. - -This UUID is generated from a name within a namespace. -SHA1 is used to hash the name with the namespace to produce the UUID. - -Inputs: -- namespace: Another `Identifier` that is used to represent the underlying namespace. - This can be any one of the `Namespace_*` values provided in this package. -- name: The string used to generate the name on top of the namespace. - -Returns: -- result: The generated UUID. -*/ -generate_v5_string :: proc( - namespace: Identifier, - name: string, -) -> ( - result: Identifier, -) { - return generate_v5_bytes(namespace, transmute([]byte)name) -} - -generate_v5 :: proc { - generate_v5_bytes, - generate_v5_string, -} - /* Generate a version 6 UUID. diff --git a/core/encoding/uuid/legacy/legacy.odin b/core/encoding/uuid/legacy/legacy.odin new file mode 100644 index 000000000..44057f1f8 --- /dev/null +++ b/core/encoding/uuid/legacy/legacy.odin @@ -0,0 +1,150 @@ +/* +package uuid/legacy implements versions 3 and 5 of UUID generation, both of +which are using hashing algorithms (MD5 and SHA1, respectively) that are known +these days to no longer be secure. +*/ +package uuid_legacy + +import "base:runtime" +import "core:crypto/legacy/md5" +import "core:crypto/legacy/sha1" +import "core:encoding/uuid" + +Identifier :: uuid.Identifier +VERSION_BYTE_INDEX :: uuid.VERSION_BYTE_INDEX +VARIANT_BYTE_INDEX :: uuid.VARIANT_BYTE_INDEX + + +/* +Generate a version 3 UUID. + +This UUID is generated from a name within a namespace. +MD5 is used to hash the name with the namespace to produce the UUID. + +Inputs: +- namespace: Another `Identifier` that is used to represent the underlying namespace. + This can be any one of the `Namespace_*` values provided in the `uuid` package. +- name: The byte slice used to generate the name on top of the namespace. + +Returns: +- result: The generated UUID. +*/ +generate_v3_bytes :: proc( + namespace: Identifier, + name: []byte, +) -> ( + result: Identifier, +) { + namespace := namespace + + ctx: md5.Context + md5.init(&ctx) + md5.update(&ctx, namespace[:]) + md5.update(&ctx, name) + md5.final(&ctx, result[:]) + + result[VERSION_BYTE_INDEX] &= 0x0F + result[VERSION_BYTE_INDEX] |= 0x30 + + result[VARIANT_BYTE_INDEX] &= 0x3F + result[VARIANT_BYTE_INDEX] |= 0x80 + + return +} + +/* +Generate a version 3 UUID. + +This UUID is generated from a name within a namespace. +MD5 is used to hash the name with the namespace to produce the UUID. + +Inputs: +- namespace: Another `Identifier` that is used to represent the underlying namespace. + This can be any one of the `Namespace_*` values provided in the `uuid` package. +- name: The string used to generate the name on top of the namespace. + +Returns: +- result: The generated UUID. +*/ +generate_v3_string :: proc( + namespace: Identifier, + name: string, +) -> ( + result: Identifier, +) { + return generate_v3_bytes(namespace, transmute([]byte)name) +} + +generate_v3 :: proc { + generate_v3_bytes, + generate_v3_string, +} + +/* +Generate a version 5 UUID. + +This UUID is generated from a name within a namespace. +SHA1 is used to hash the name with the namespace to produce the UUID. + +Inputs: +- namespace: Another `Identifier` that is used to represent the underlying namespace. + This can be any one of the `Namespace_*` values provided in the `uuid` package. +- name: The byte slice used to generate the name on top of the namespace. + +Returns: +- result: The generated UUID. +*/ +generate_v5_bytes :: proc( + namespace: Identifier, + name: []byte, +) -> ( + result: Identifier, +) { + namespace := namespace + digest: [sha1.DIGEST_SIZE]byte + + ctx: sha1.Context + sha1.init(&ctx) + sha1.update(&ctx, namespace[:]) + sha1.update(&ctx, name) + sha1.final(&ctx, digest[:]) + + runtime.mem_copy_non_overlapping(&result, &digest, 16) + + result[VERSION_BYTE_INDEX] &= 0x0F + result[VERSION_BYTE_INDEX] |= 0x50 + + result[VARIANT_BYTE_INDEX] &= 0x3F + result[VARIANT_BYTE_INDEX] |= 0x80 + + return +} + +/* +Generate a version 5 UUID. + +This UUID is generated from a name within a namespace. +SHA1 is used to hash the name with the namespace to produce the UUID. + +Inputs: +- namespace: Another `Identifier` that is used to represent the underlying namespace. + This can be any one of the `Namespace_*` values provided in the `uuid` package. +- name: The string used to generate the name on top of the namespace. + +Returns: +- result: The generated UUID. +*/ +generate_v5_string :: proc( + namespace: Identifier, + name: string, +) -> ( + result: Identifier, +) { + return generate_v5_bytes(namespace, transmute([]byte)name) +} + +generate_v5 :: proc { + generate_v5_bytes, + generate_v5_string, +} + diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index d39fbe79f..9c0d28a91 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -63,6 +63,7 @@ import xml "core:encoding/xml" import endian "core:encoding/endian" import cbor "core:encoding/cbor" import uuid "core:encoding/uuid" +import uuid_legacy "core:encoding/uuid/legacy" import fmt "core:fmt" import hash "core:hash" @@ -239,6 +240,7 @@ _ :: flags _ :: sysinfo _ :: unicode _ :: uuid +_ :: uuid_legacy _ :: utf8 _ :: utf8string _ :: utf16 diff --git a/tests/core/encoding/uuid/test_core_uuid.odin b/tests/core/encoding/uuid/test_core_uuid.odin index 90e299143..fc2615fe0 100644 --- a/tests/core/encoding/uuid/test_core_uuid.odin +++ b/tests/core/encoding/uuid/test_core_uuid.odin @@ -1,6 +1,7 @@ package test_core_uuid import "core:encoding/uuid" +import uuid_legacy "core:encoding/uuid/legacy" import "core:log" import "core:testing" import "core:time" @@ -8,9 +9,9 @@ import "core:time" @(test) test_version_and_variant :: proc(t: ^testing.T) { v1 := uuid.generate_v1(0) - v3 := uuid.generate_v3(uuid.Namespace_DNS, "") + v3 := uuid_legacy.generate_v3(uuid.Namespace_DNS, "") v4 := uuid.generate_v4() - v5 := uuid.generate_v5(uuid.Namespace_DNS, "") + v5 := uuid_legacy.generate_v5(uuid.Namespace_DNS, "") v6 := uuid.generate_v6() v7 := uuid.generate_v7() @@ -29,7 +30,7 @@ test_version_and_variant :: proc(t: ^testing.T) { } @(test) -test_namespaced_uuids :: proc(t: ^testing.T) { +test_legacy_namespaced_uuids :: proc(t: ^testing.T) { TEST_NAME :: "0123456789ABCDEF0123456789ABCDEF" Expected_Result :: struct { @@ -45,8 +46,8 @@ test_namespaced_uuids :: proc(t: ^testing.T) { } for exp in Expected_Results { - v3 := uuid.generate_v3(exp.namespace, TEST_NAME) - v5 := uuid.generate_v5(exp.namespace, TEST_NAME) + v3 := uuid_legacy.generate_v3(exp.namespace, TEST_NAME) + v5 := uuid_legacy.generate_v5(exp.namespace, TEST_NAME) v3_str := uuid.to_string(v3) defer delete(v3_str)